nfs-ganesha 1.4

fsal_tools.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ------------- 
00024  */
00025 
00034 #ifdef HAVE_CONFIG_H
00035 #include "config.h"
00036 #endif
00037 
00038 #include "fsal.h"
00039 #include "fsal_internal.h"
00040 #include "fsal_convert.h"
00041 #include "config_parsing.h"
00042 #include <string.h>
00043 
00044 /* case unsensitivity */
00045 #define STRCMP   strcasecmp
00046 
00047 char *GPFSFSAL_GetFSName()
00048 {
00049   return "GPFS";
00050 }
00051 
00068 int GPFSFSAL_handlecmp(fsal_handle_t * handle_1, fsal_handle_t * handle_2,
00069                    fsal_status_t * status)
00070 {
00071   gpfsfsal_handle_t *handle1 = (gpfsfsal_handle_t *)handle_1;
00072   gpfsfsal_handle_t *handle2 = (gpfsfsal_handle_t *)handle_2;
00073 
00074   *status = FSAL_STATUS_NO_ERROR;
00075 
00076   if(!handle1 || !handle2)
00077     {
00078       status->major = ERR_FSAL_FAULT;
00079       return -1;
00080     }
00081 
00082   if(handle1->data.handle.handle_size != handle2->data.handle.handle_size)
00083     return -2;
00084 
00085   if(memcmp
00086      (handle1->data.handle.f_handle, handle2->data.handle.f_handle, handle1->data.handle.handle_key_size))
00087     //FSF && (handle1->fsid[0] == handle2->fsid[0])
00088     //FSF && (handle1->fsid[1] == handle2->fsid[1]) )
00089     return -3;
00090 
00091   return 0;
00092 }
00093 
00107 unsigned int GPFSFSAL_Handle_to_HashIndex(fsal_handle_t * handle,
00108                                       unsigned int cookie,
00109                                       unsigned int alphabet_len, unsigned int index_size)
00110 {
00111   unsigned int cpt = 0;
00112   unsigned int sum = 0;
00113   unsigned int extract = 0;
00114   unsigned int mod;
00115   gpfsfsal_handle_t *p_handle = (gpfsfsal_handle_t *)handle;
00116 
00117   /* XXX If the handle is not 32 bits-aligned, the last loop will get uninitialized
00118    * chars after the end of the handle. We must avoid this by skipping the last loop
00119    * and doing a special processing for the last bytes */
00120 
00121   mod = p_handle->data.handle.handle_key_size % sizeof(unsigned int);
00122 
00123   sum = cookie;
00124   for(cpt = 0; cpt < p_handle->data.handle.handle_key_size - mod; cpt += sizeof(unsigned int))
00125     {
00126       memcpy(&extract, &(p_handle->data.handle.f_handle[cpt]), sizeof(unsigned int));
00127       sum = (3 * sum + 5 * extract + 1999) % index_size;
00128     }
00129 
00130   if(mod)
00131     {
00132       extract = 0;
00133       for(cpt = p_handle->data.handle.handle_key_size - mod; cpt < p_handle->data.handle.handle_key_size;
00134           cpt++)
00135         {
00136           /* shift of 1 byte */
00137           extract <<= 8;
00138           extract |= (unsigned int)p_handle->data.handle.f_handle[cpt];
00139         }
00140       sum = (3 * sum + 5 * extract + 1999) % index_size;
00141     }
00142 
00143   return sum;
00144 }
00145 
00146 /*
00147  * FSAL_Handle_to_RBTIndex
00148  * This function is used for generating a RBT node ID
00149  * in order to identify entries into the RBT.
00150  *
00151  * \param p_handle      The handle to be hashed
00152  * \param cookie        Makes it possible to have different hash value for the
00153  *                      same handle, when cookie changes.
00154  *
00155  * \return The hash value
00156  */
00157 
00158 unsigned int GPFSFSAL_Handle_to_RBTIndex(fsal_handle_t * handle, unsigned int cookie)
00159 {
00160   unsigned int h = 0;
00161   unsigned int cpt = 0;
00162   unsigned int extract = 0;
00163   unsigned int mod;
00164   gpfsfsal_handle_t * p_handle = (gpfsfsal_handle_t *)handle;
00165 
00166   h = cookie;
00167 
00168   /* XXX If the handle is not 32 bits-aligned, the last loop will get uninitialized
00169    * chars after the end of the handle. We must avoid this by skipping the last loop
00170    * and doing a special processing for the last bytes */
00171 
00172   mod = p_handle->data.handle.handle_key_size % sizeof(unsigned int);
00173 
00174   for(cpt = 0; cpt < p_handle->data.handle.handle_key_size - mod; cpt += sizeof(unsigned int))
00175     {
00176       memcpy(&extract, &(p_handle->data.handle.f_handle[cpt]), sizeof(unsigned int));
00177       h = (857 * h ^ extract) % 715827883;
00178     }
00179 
00180   if(mod)
00181     {
00182       extract = 0;
00183       for(cpt = p_handle->data.handle.handle_key_size - mod; cpt < p_handle->data.handle.handle_key_size;
00184           cpt++)
00185         {
00186           /* shift of 1 byte */
00187           extract <<= 8;
00188           extract |= (unsigned int)p_handle->data.handle.f_handle[cpt];
00189         }
00190       h = (857 * h ^ extract) % 715827883;
00191     }
00192 
00193   return h;
00194 }
00195 
00210 fsal_status_t GPFSFSAL_DigestHandle(fsal_export_context_t *exp_context,   /* IN */
00211                                 fsal_digesttype_t output_type,  /* IN */
00212                                 fsal_handle_t * in_fsal_handle,       /* IN */
00213                                 struct fsal_handle_desc *fh_desc /* IN/OUT */
00214     )
00215 {
00216   gpfsfsal_export_context_t * p_expcontext = (gpfsfsal_export_context_t *)exp_context;
00217   gpfsfsal_handle_t * p_in_fsal_handle = (gpfsfsal_handle_t *)in_fsal_handle;
00218   size_t fh_size;
00219 
00220   /* sanity checks */
00221   if(!p_in_fsal_handle || !fh_desc || !p_expcontext)
00222     ReturnCode(ERR_FSAL_FAULT, 0);
00223 
00224   switch (output_type)
00225     {
00226 
00227       /* NFS handle digest */
00228     case FSAL_DIGEST_NFSV2:
00229 
00230       /* GPFS FSAL can no longer support NFS v2 */
00231       ReturnCode(ERR_FSAL_NOTSUPP, 0);
00232 
00233     case FSAL_DIGEST_NFSV3:
00234     case FSAL_DIGEST_NFSV4:
00235       fh_size = gpfs_sizeof_handle((struct gpfs_file_handle *)in_fsal_handle);
00236       if(fh_desc->len < fh_size)
00237         {
00238           LogMajor(COMPONENT_FSAL,
00239                    "GPFSFSAL_DigestHandle: space too small for handle.Need %lu, have %lu",
00240                    (unsigned long)fh_size, (unsigned long)fh_desc->len);
00241           ReturnCode(ERR_FSAL_TOOSMALL, 0);
00242         }
00243       memcpy(fh_desc->start, (caddr_t)p_in_fsal_handle, fh_size);
00244       fh_desc->len = fh_size;
00245       break;
00246 
00247       /* FileId digest for NFSv2 */
00248     case FSAL_DIGEST_FILEID2:
00249 
00250       /* GPFS FSAL can no longer support NFS v2 */
00251       ReturnCode(ERR_FSAL_NOTSUPP, 0);
00252 
00253       /* FileId digest for NFSv3 */
00254     case FSAL_DIGEST_FILEID3:
00255 
00256       /* sanity check about output size */
00257       /* If the handle_size is the full OPENHANDLE_HANDLE_LEN then we assume it's a new style GPFS handle */
00258       if (fh_desc->len == 8)
00259         memset(fh_desc->start, 0, sizeof(uint64_t));
00260       if(p_in_fsal_handle->data.handle.handle_size < OPENHANDLE_HANDLE_LEN)
00261         memcpy(fh_desc->start, p_in_fsal_handle->data.handle.f_handle, sizeof(uint32_t));
00262       else
00263         memcpy(fh_desc->start, p_in_fsal_handle->data.handle.f_handle + OPENHANDLE_OFFSET_OF_FILEID, sizeof(uint64_t));
00264       break;
00265 
00266       /* FileId digest for NFSv4 */
00267     case FSAL_DIGEST_FILEID4:
00268 
00269       if(p_in_fsal_handle->data.handle.handle_size < OPENHANDLE_HANDLE_LEN)
00270         memcpy(fh_desc->start, p_in_fsal_handle->data.handle.f_handle, sizeof(uint32_t));
00271       else
00272         memcpy(fh_desc->start, p_in_fsal_handle->data.handle.f_handle + OPENHANDLE_OFFSET_OF_FILEID, sizeof(uint64_t));
00273       break;
00274 
00275     default:
00276       ReturnCode(ERR_FSAL_SERVERFAULT, 0);
00277     }
00278 
00279   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00280 
00281 }
00282 
00299 fsal_status_t GPFSFSAL_ExpandHandle(fsal_export_context_t *exp_context,   /* IN */
00300                                 fsal_digesttype_t in_type,      /* IN */
00301                                 struct fsal_handle_desc *fh_desc  /* IN/OUT */
00302     )
00303 {
00304   struct gpfs_file_handle *hdl;
00305   size_t fh_size;
00306 
00307   /* sanity checks */
00308   if(!fh_desc || !fh_desc->start)
00309     ReturnCode(ERR_FSAL_FAULT, 0);
00310 
00311   hdl = (struct gpfs_file_handle *)fh_desc->start;
00312   fh_size = gpfs_sizeof_handle(hdl);
00313 
00314   if(in_type == FSAL_DIGEST_NFSV2)
00315     {
00316       /* GPFS FSAL can no longer support NFS v2 */
00317       ReturnCode(ERR_FSAL_NOTSUPP, 0);
00318     }
00319   else if(in_type != FSAL_DIGEST_SIZEOF && fh_desc->len != fh_size)
00320     {
00321       LogMajor(COMPONENT_FSAL,
00322                "GPFSFSAL_ExpandHandle: size mismatch for handle.  should be %lu, got %lu",
00323                fh_size, fh_desc->len);
00324       ReturnCode(ERR_FSAL_SERVERFAULT, 0);
00325     }
00326 
00327   fh_desc->len = fh_size;  /* pass back the actual size */
00328   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00329 
00330 }
00331 
00340 fsal_status_t GPFSFSAL_SetDefault_FS_specific_parameter(fsal_parameter_t * out_parameter)
00341 {
00342   /* defensive programming... */
00343   if(out_parameter == NULL)
00344     ReturnCode(ERR_FSAL_FAULT, 0);
00345 
00346   /* set default values for all parameters of fs_specific_info */
00347 
00348 #ifdef _USE_PGSQL
00349 
00350   /* pgsql db */
00351   strcpy(out_parameter->fs_specific_info.dbparams.host, "localhost");
00352   strcpy(out_parameter->fs_specific_info.dbparams.port, "5432");
00353   out_parameter->fs_specific_info.dbparams.dbname[0] = '\0';
00354   out_parameter->fs_specific_info.dbparams.login[0] = '\0';
00355   out_parameter->fs_specific_info.dbparams.passwdfile[0] = '\0';
00356 
00357 #elif defined(_USE_MYSQL)
00358 
00359   strcpy(out_parameter->fs_specific_info.dbparams.host, "localhost");
00360   strcpy(out_parameter->fs_specific_info.dbparams.port, "");
00361   out_parameter->fs_specific_info.dbparams.dbname[0] = '\0';
00362   out_parameter->fs_specific_info.dbparams.login[0] = '\0';
00363   out_parameter->fs_specific_info.dbparams.passwdfile[0] = '\0';
00364 
00365 #endif
00366 
00367   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00368 
00369 }
00370 
00392 /* load specific filesystem configuration options */
00393 
00394 fsal_status_t GPFSFSAL_load_FS_specific_parameter_from_conf(config_file_t in_config,
00395                                                         fsal_parameter_t * out_parameter)
00396 {
00397   int err;
00398   int var_max, var_index;
00399   char *key_name;
00400   char *key_value;
00401   config_item_t block;
00402   gpfsfs_specific_initinfo_t *initinfo
00403           = (gpfsfs_specific_initinfo_t *) &out_parameter->fs_specific_info;
00404 
00405   block = config_FindItemByName(in_config, CONF_LABEL_FS_SPECIFIC);
00406 
00407   /* cannot read item */
00408   if(block == NULL)
00409     {
00410       LogCrit(COMPONENT_CONFIG,
00411               "FSAL LOAD PARAMETER: Cannot read item \"%s\" from configuration file",
00412               CONF_LABEL_FS_SPECIFIC);
00413       ReturnCode(ERR_FSAL_NOENT, 0);
00414     }
00415   else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
00416     {
00417       LogCrit(COMPONENT_CONFIG,
00418               "FSAL LOAD PARAMETER: Item \"%s\" is expected to be a block",
00419               CONF_LABEL_FS_SPECIFIC);
00420       ReturnCode(ERR_FSAL_INVAL, 0);
00421     }
00422 
00423   var_max = config_GetNbItems(block);
00424 
00425   for(var_index = 0; var_index < var_max; var_index++)
00426     {
00427       config_item_t item;
00428 
00429       item = config_GetItemByIndex(block, var_index);
00430 
00431       err = config_GetKeyValue(item, &key_name, &key_value);
00432       if(err)
00433         {
00434           LogCrit(COMPONENT_CONFIG,
00435                   "FSAL LOAD PARAMETER: ERROR reading key[%d] from section \"%s\" of configuration file.",
00436                   var_index, CONF_LABEL_FS_SPECIFIC);
00437           ReturnCode(ERR_FSAL_SERVERFAULT, err);
00438         }
00439       /* does the variable exists ? */
00440       if(!STRCMP(key_name, "OpenByHandleDeviceFile"))
00441         {
00442           strncpy(initinfo->open_by_handle_dev_file, key_value,
00443                   MAXPATHLEN);
00444         }
00445       else if(!STRCMP(key_name, "Use_Kernel_Module_Interface"))
00446         {
00447           int bool = StrToBoolean(key_value);
00448           if (bool == -1)
00449             {
00450               LogCrit(COMPONENT_CONFIG,
00451                       "FSAL LOAD PARAMETER: ERROR: Unexpected value for %s: 0 or 1 expected.",
00452                       key_name);
00453               ReturnCode(ERR_FSAL_INVAL, 0);
00454             }
00455           initinfo->use_kernel_module_interface = bool;
00456         }
00457       else
00458         {
00459           LogCrit(COMPONENT_CONFIG,
00460                   "FSAL LOAD PARAMETER: ERROR: Unknown or unsettable key: %s (item %s)",
00461                   key_name, CONF_LABEL_FS_SPECIFIC);
00462           ReturnCode(ERR_FSAL_INVAL, 0);
00463         }
00464     }
00465 
00466   if(initinfo->use_kernel_module_interface && initinfo->open_by_handle_dev_file[0] == '\0')
00467     {
00468       LogCrit(COMPONENT_CONFIG,
00469               "FSAL LOAD PARAMETER: OpenByHandleDeviceFile MUST be specified in the configuration file (item %s)",
00470               CONF_LABEL_FS_SPECIFIC);
00471       ReturnCode(ERR_FSAL_NOENT, 0);
00472     }
00473 
00474   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00475 
00476 }                               /* FSAL_load_FS_specific_parameter_from_conf */