nfs-ganesha 1.4

handle_mapping.c

Go to the documentation of this file.
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 }