nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00005 /* 00006 * Copyright CEA/DAM/DIF (2008) 00007 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00008 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00009 * 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Lesser General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 3 of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this library; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00024 * 00025 * --------------------------------------- 00026 */ 00027 00035 #include "config.h" 00036 #include "handle_mapping.h" 00037 #include "handle_mapping_db.h" 00038 #include "handle_mapping_internal.h" 00039 #include "../fsal_internal.h" 00040 00041 /* hashe table definitions */ 00042 00043 static unsigned long hash_digest_idx(hash_parameter_t * p_conf, hash_buffer_t * p_key); 00044 static unsigned long hash_digest_rbt(hash_parameter_t * p_conf, hash_buffer_t * p_key); 00045 static int cmp_digest(hash_buffer_t * p_key1, hash_buffer_t * p_key2); 00046 00047 static int print_digest(hash_buffer_t * p_val, char *outbuff); 00048 static int print_handle(hash_buffer_t * p_val, char *outbuff); 00049 00050 /* DEFAULT PARAMETERS for hash table */ 00051 00052 static hash_parameter_t handle_hash_config = { 00053 .index_size = 67, 00054 .alphabet_length = 10, 00055 .nb_node_prealloc = 1024, 00056 .hash_func_key = hash_digest_idx, 00057 .hash_func_rbt = hash_digest_rbt, 00058 .compare_key = cmp_digest, 00059 .key_to_str = print_digest, 00060 .val_to_str = print_handle, 00061 .ht_name = "PROXY Handle Cache", 00062 .flags = HT_FLAG_CACHE, 00063 .ht_log_component = COMPONENT_FSAL 00064 }; 00065 00066 static hash_table_t *handle_map_hash = NULL; 00067 00068 /* memory pool definitions */ 00069 00070 typedef struct digest_pool_entry__ 00071 { 00072 nfs23_map_handle_t nfs23_digest; 00073 struct digest_pool_entry__ *p_next; 00074 } digest_pool_entry_t; 00075 00076 typedef struct handle_pool_entry__ 00077 { 00078 fsal_handle_t handle; 00079 struct handle_pool_entry__ *p_next; 00080 } handle_pool_entry_t; 00081 00082 static unsigned int nb_pool_prealloc = 1024; 00083 00084 struct pool_t *digest_pool; 00085 static pthread_mutex_t digest_pool_mutex = PTHREAD_MUTEX_INITIALIZER; 00086 00087 struct pool_th andle_pool; 00088 static pthread_mutex_t handle_pool_mutex = PTHREAD_MUTEX_INITIALIZER; 00089 00090 /* helpers for pool allocation */ 00091 00092 static digest_pool_entry_t *digest_alloc() 00093 { 00094 digest_pool_entry_t *p_new; 00095 00096 P(digest_pool_mutex); 00097 p_new = pool_alloc(digest_pool, NULL); 00098 V(digest_pool_mutex); 00099 00100 memset(p_new, 0, sizeof(digest_pool_entry_t)); 00101 00102 return p_new; 00103 } 00104 00105 static void digest_free(digest_pool_entry_t * p_digest) 00106 { 00107 memset(p_digest, 0, sizeof(digest_pool_entry_t)); 00108 00109 P(digest_pool_mutex); 00110 pool_free(digest_pool, p_digest); 00111 V(digest_pool_mutex); 00112 } 00113 00114 static handle_pool_entry_t *handle_alloc() 00115 { 00116 handle_pool_entry_t *p_new; 00117 00118 P(handle_pool_mutex); 00119 p_new = pool_alloc(handle_pool, NULL); 00120 V(handle_pool_mutex); 00121 00122 memset(p_new, 0, sizeof(handle_pool_entry_t)); 00123 00124 return p_new; 00125 } 00126 00127 static void handle_free(handle_pool_entry_t * p_handle) 00128 { 00129 memset(p_handle, 0, sizeof(handle_pool_entry_t)); 00130 00131 P(handle_pool_mutex); 00132 pool_free(handle_pool, p_handle); 00133 V(handle_pool_mutex); 00134 } 00135 00136 /* hash table functions */ 00137 00138 static unsigned long hash_digest_idx(hash_parameter_t * p_conf, hash_buffer_t * p_key) 00139 { 00140 unsigned long hash; 00141 digest_pool_entry_t *p_digest = (digest_pool_entry_t *) p_key->pdata; 00142 00143 hash = 00144 (p_conf->alphabet_length + 00145 ((unsigned long)p_digest->nfs23_digest.object_id ^ (unsigned int)p_digest-> 00146 nfs23_digest.handle_hash)); 00147 hash = (743 * hash + 1999) % p_conf->index_size; 00148 00149 return hash; 00150 00151 } 00152 00153 static unsigned long hash_digest_rbt(hash_parameter_t * p_conf, hash_buffer_t * p_key) 00154 { 00155 unsigned long hash; 00156 digest_pool_entry_t *p_digest = (digest_pool_entry_t *) p_key->pdata; 00157 00158 hash = (257 * p_digest->nfs23_digest.object_id + 541); 00159 00160 return hash; 00161 } 00162 00163 static int cmp_digest(hash_buffer_t * p_key1, hash_buffer_t * p_key2) 00164 { 00165 digest_pool_entry_t *p_digest1 = (digest_pool_entry_t *) p_key1->pdata; 00166 digest_pool_entry_t *p_digest2 = (digest_pool_entry_t *) p_key2->pdata; 00167 00168 /* compare object_id and handle_hash */ 00169 00170 if(p_digest1->nfs23_digest.object_id != p_digest2->nfs23_digest.object_id) 00171 return (int)(p_digest1->nfs23_digest.object_id - p_digest2->nfs23_digest.object_id); 00172 else if(p_digest1->nfs23_digest.handle_hash != p_digest2->nfs23_digest.handle_hash) 00173 return (int)p_digest1->nfs23_digest.handle_hash - 00174 (int)p_digest2->nfs23_digest.handle_hash; 00175 else /* same */ 00176 return 0; 00177 } 00178 00179 static int print_digest(hash_buffer_t * p_val, char *outbuff) 00180 { 00181 digest_pool_entry_t *p_digest = (digest_pool_entry_t *) p_val->pdata; 00182 00183 return sprintf(outbuff, "%llu, %u", (unsigned long long)p_digest->nfs23_digest.object_id, 00184 p_digest->nfs23_digest.handle_hash); 00185 } 00186 00187 static int print_handle(hash_buffer_t * p_val, char *outbuff) 00188 { 00189 handle_pool_entry_t *p_handle = (handle_pool_entry_t *) p_val->pdata; 00190 00191 return snprintHandle(outbuff, HASHTABLE_DISPLAY_STRLEN, &p_handle->handle); 00192 } 00193 00194 int handle_mapping_hash_add(hash_table_t * p_hash, 00195 uint64_t object_id, 00196 unsigned int handle_hash, fsal_handle_t * p_handle) 00197 { 00198 int rc; 00199 hash_buffer_t buffkey; 00200 hash_buffer_t buffval; 00201 digest_pool_entry_t *digest; 00202 handle_pool_entry_t *handle; 00203 00204 digest = digest_alloc(); 00205 handle = handle_alloc(); 00206 00207 if(!digest || !handle) 00208 return HANDLEMAP_SYSTEM_ERROR; 00209 00210 digest->nfs23_digest.object_id = object_id; 00211 digest->nfs23_digest.handle_hash = handle_hash; 00212 handle->handle = *p_handle; 00213 00214 buffkey.pdata = (caddr_t) digest; 00215 buffkey.len = sizeof(digest_pool_entry_t); 00216 00217 buffval.pdata = (caddr_t) handle; 00218 buffval.len = sizeof(handle_pool_entry_t); 00219 00220 rc = HashTable_Test_And_Set(handle_map_hash, &buffkey, &buffval, 00221 HASHTABLE_SET_HOW_SET_NO_OVERWRITE); 00222 00223 if(rc != HASHTABLE_SUCCESS) 00224 { 00225 digest_free(digest); 00226 handle_free(handle); 00227 00228 if(rc != HASHTABLE_ERROR_KEY_ALREADY_EXISTS) 00229 { 00230 LogCrit(COMPONENT_FSAL, 00231 "ERROR %d inserting entry to handle mapping hash table", rc); 00232 return HANDLEMAP_HASHTABLE_ERROR; 00233 } 00234 else 00235 { 00236 return HANDLEMAP_EXISTS; 00237 } 00238 } 00239 00240 return HANDLEMAP_SUCCESS; 00241 } 00242 00249 int HandleMap_Init(const handle_map_param_t * p_param) 00250 { 00251 int rc; 00252 00253 nb_pool_prealloc = p_param->nb_handles_prealloc; 00254 00255 /* first check database count */ 00256 00257 rc = handlemap_db_count(p_param->databases_directory); 00258 00259 if((rc > 0) && (rc != p_param->database_count)) 00260 { 00261 LogCrit(COMPONENT_FSAL, 00262 "ERROR: The number of existing databases (%u) does not match the requested DB thread count (%u)", 00263 rc, p_param->database_count); 00264 00265 return HANDLEMAP_INVALID_PARAM; 00266 } 00267 else if(rc < 0) 00268 return -rc; 00269 00270 /* init database module */ 00271 00272 rc = handlemap_db_init(p_param->databases_directory, 00273 p_param->temp_directory, 00274 p_param->database_count, 00275 p_param->nb_db_op_prealloc, p_param->synchronous_insert); 00276 00277 if(rc) 00278 { 00279 LogCrit(COMPONENT_FSAL, "ERROR %d initializing database access", rc); 00280 return rc; 00281 } 00282 00283 /* initialize memory pool of digests and handles */ 00284 00285 digest_pool = init_pool(NULL, sizeof(digest_pool_entry_t), NULL, NULL); 00286 00287 handle_pool = init_pool(NULL, sizeof(handle_pool_entry_t), NULL, NULL); 00288 00289 /* create hash table */ 00290 00291 handle_hash_config.index_size = p_param->hashtable_size; 00292 handle_hash_config.nb_node_prealloc = p_param->nb_handles_prealloc; 00293 00294 handle_map_hash = HashTable_Init(&handle_hash_config); 00295 00296 if(!handle_map_hash) 00297 { 00298 LogCrit(COMPONENT_FSAL, "ERROR creating hash table for handle mapping"); 00299 return HANDLEMAP_INTERNAL_ERROR; 00300 } 00301 00302 /* reload previous data */ 00303 00304 rc = handlemap_db_reaload_all(handle_map_hash); 00305 00306 if(rc) 00307 { 00308 LogCrit(COMPONENT_FSAL, "ERROR %d reloading handle mapping from database", rc); 00309 return rc; 00310 } 00311 00312 return HANDLEMAP_SUCCESS; 00313 } 00314 00324 int HandleMap_GetFH(nfs23_map_handle_t * p_in_nfs23_digest, 00325 fsal_handle_t * p_out_fsal_handle) 00326 { 00327 00328 int rc; 00329 hash_buffer_t buffkey; 00330 hash_buffer_t buffval; 00331 digest_pool_entry_t digest; 00332 fsal_handle_t *p_handle; 00333 00334 digest.nfs23_digest = *p_in_nfs23_digest; 00335 00336 buffkey.pdata = (caddr_t) & digest; 00337 buffkey.len = sizeof(digest_pool_entry_t); 00338 00339 rc = HashTable_Get(handle_map_hash, &buffkey, &buffval); 00340 00341 if(rc == HASHTABLE_SUCCESS) 00342 { 00343 p_handle = (fsal_handle_t *) buffval.pdata; 00344 *p_out_fsal_handle = *p_handle; 00345 00346 return HANDLEMAP_SUCCESS; 00347 } 00348 else 00349 return HANDLEMAP_STALE; 00350 00351 } /* HandleMap_GetFH */ 00352 00356 int HandleMap_SetFH(nfs23_map_handle_t * p_in_nfs23_digest, fsal_handle_t * p_in_handle) 00357 { 00358 int rc; 00359 00360 /* first, try to insert it to the hash table */ 00361 00362 rc = handle_mapping_hash_add(handle_map_hash, p_in_nfs23_digest->object_id, 00363 p_in_nfs23_digest->handle_hash, p_in_handle); 00364 00365 if((rc != 0) && (rc != HANDLEMAP_EXISTS)) 00366 /* error */ 00367 return rc; 00368 else if(rc == HANDLEMAP_EXISTS) 00369 /* already in database */ 00370 return HANDLEMAP_EXISTS; 00371 else 00372 { 00373 /* insert it to DB */ 00374 return handlemap_db_insert(p_in_nfs23_digest, p_in_handle); 00375 } 00376 } 00377 00383 int HandleMap_DelFH(nfs23_map_handle_t * p_in_nfs23_digest) 00384 { 00385 int rc; 00386 hash_buffer_t buffkey, stored_buffkey; 00387 hash_buffer_t stored_buffval; 00388 00389 digest_pool_entry_t digest; 00390 00391 digest_pool_entry_t *p_stored_digest; 00392 handle_pool_entry_t *p_stored_handle; 00393 00394 /* first, delete it from hash table */ 00395 00396 digest.nfs23_digest = *p_in_nfs23_digest; 00397 00398 buffkey.pdata = (caddr_t) & digest; 00399 buffkey.len = sizeof(digest_pool_entry_t); 00400 00401 rc = HashTable_Del(handle_map_hash, &buffkey, &stored_buffkey, &stored_buffval); 00402 00403 if(rc != HASHTABLE_SUCCESS) 00404 { 00405 return HANDLEMAP_STALE; 00406 } 00407 00408 p_stored_digest = (digest_pool_entry_t *) stored_buffkey.pdata; 00409 p_stored_handle = (handle_pool_entry_t *) stored_buffval.pdata; 00410 00411 digest_free(p_stored_digest); 00412 handle_free(p_stored_handle); 00413 00414 /* then, submit the request to the database */ 00415 00416 return handlemap_db_delete(p_in_nfs23_digest); 00417 00418 } 00419 00423 int HandleMap_Flush() 00424 { 00425 return handlemap_db_flush(); 00426 }