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 #include <stddef.h>
00044 
00045 /* case unsensitivity */
00046 #define STRCMP   strcasecmp
00047 
00048 char *VFSFSAL_GetFSName()
00049 {
00050   return "VFS";
00051 }
00052 
00069 int VFSFSAL_handlecmp(fsal_handle_t * handle_1, fsal_handle_t * handle_2,
00070                    fsal_status_t * status)
00071 {
00072   vfsfsal_handle_t * handle1 = (vfsfsal_handle_t *)handle_1;
00073   vfsfsal_handle_t * handle2 = (vfsfsal_handle_t *)handle_2;
00074 
00075   *status = FSAL_STATUS_NO_ERROR;
00076 
00077   if(!handle1 || !handle2)
00078     {
00079       status->major = ERR_FSAL_FAULT;
00080       return -1;
00081     }
00082 
00083   if(handle1->data.vfs_handle.handle_bytes != handle2->data.vfs_handle.handle_bytes)
00084     return -2;
00085 
00086   if(memcmp(&handle1->data.vfs_handle, &handle2->data.vfs_handle, sizeof( vfs_file_handle_t) ) )
00087     return -3;
00088 
00089   return 0;
00090 }
00091 
00105 unsigned int VFSFSAL_Handle_to_HashIndex(fsal_handle_t *handle,
00106                                       unsigned int cookie,
00107                                       unsigned int alphabet_len, unsigned int index_size)
00108 {
00109   vfsfsal_handle_t * p_handle = (vfsfsal_handle_t *)handle;
00110   unsigned int cpt = 0;
00111   unsigned int sum = 0;
00112   unsigned int extract = 0;
00113   unsigned int mod;
00114 
00115   /* XXX If the handle is not 32 bits-aligned, the last loop will get uninitialized
00116    * chars after the end of the handle. We must avoid this by skipping the last loop
00117    * and doing a special processing for the last bytes */
00118 
00119   mod = p_handle->data.vfs_handle.handle_bytes % sizeof(unsigned int);
00120 
00121   sum = cookie;
00122   for(cpt = 0; cpt < p_handle->data.vfs_handle.handle_bytes - mod; cpt += sizeof(unsigned int))
00123     {
00124       memcpy(&extract, &(p_handle->data.vfs_handle.handle[cpt]), sizeof(unsigned int));
00125       sum = (3 * sum + 5 * extract + 1999) % index_size;
00126     }
00127 
00128   if(mod)
00129     {
00130       extract = 0;
00131       for(cpt = p_handle->data.vfs_handle.handle_bytes - mod; cpt < p_handle->data.vfs_handle.handle_bytes; cpt++ )
00132         {
00133           /* shift of 1 byte */
00134           extract <<= 8;
00135           extract |= (unsigned int)p_handle->data.vfs_handle.handle[cpt];
00136         }
00137       sum = (3 * sum + 5 * extract + 1999) % index_size;
00138     }
00139 
00140   return sum;
00141 }
00142 
00143 /*
00144  * FSAL_Handle_to_RBTIndex
00145  * This function is used for generating a RBT node ID
00146  * in order to identify entries into the RBT.
00147  *
00148  * \param p_handle      The handle to be hashed
00149  * \param cookie        Makes it possible to have different hash value for the
00150  *                      same handle, when cookie changes.
00151  *
00152  * \return The hash value
00153  */
00154 
00155 unsigned int VFSFSAL_Handle_to_RBTIndex(fsal_handle_t *handle, unsigned int cookie)
00156 {
00157   vfsfsal_handle_t * p_handle = (vfsfsal_handle_t *)handle;
00158   unsigned int h = 0;
00159   unsigned int cpt = 0;
00160   unsigned int extract = 0;
00161   unsigned int mod;
00162 
00163   h = cookie;
00164 
00165   /* XXX If the handle is not 32 bits-aligned, the last loop will get uninitialized
00166    * chars after the end of the handle. We must avoid this by skipping the last loop
00167    * and doing a special processing for the last bytes */
00168 
00169   mod = p_handle->data.vfs_handle.handle_bytes % sizeof(unsigned int);
00170 
00171   for(cpt = 0; cpt < p_handle->data.vfs_handle.handle_bytes - mod; cpt += sizeof(unsigned int))
00172     {
00173       memcpy(&extract, &(p_handle->data.vfs_handle.handle[cpt]), sizeof(unsigned int));
00174       h = (857 * h ^ extract) % 715827883;
00175     }
00176 
00177   if(mod)
00178     {
00179       extract = 0;
00180       for(cpt = p_handle->data.vfs_handle.handle_bytes - mod; cpt < p_handle->data.vfs_handle.handle_bytes;
00181           cpt++)
00182         {
00183           /* shift of 1 byte */
00184           extract <<= 8;
00185           extract |= (unsigned int)p_handle->data.vfs_handle.handle[cpt];
00186         }
00187       h = (857 * h ^ extract) % 715827883;
00188     }
00189 
00190   return h;
00191 }
00192 
00209 fsal_status_t VFSFSAL_DigestHandle(fsal_export_context_t * p_expcontext,     /* IN */
00210                                    fsal_digesttype_t output_type,       /* IN */
00211                                    fsal_handle_t *in_fsal_handle, /* IN */
00212                                    struct fsal_handle_desc *fh_desc     /* IN/OUT */
00213     )
00214 {
00215   uint32_t ino32;
00216   uint64_t ino64;
00217   size_t fh_size;
00218   vfsfsal_handle_t * p_in_fsal_handle = (vfsfsal_handle_t *)in_fsal_handle;
00219 
00220   /* sanity checks */
00221   if(!p_in_fsal_handle || !fh_desc || !fh_desc->start || !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     case FSAL_DIGEST_NFSV3:
00230     case FSAL_DIGEST_NFSV4:
00231       fh_size = vfs_sizeof_handle((struct file_handle *)in_fsal_handle);
00232       if(fh_desc->len < fh_size)
00233         {
00234           LogMajor(COMPONENT_FSAL,
00235                    "VFS DigestHandle: space too small for handle.  need %lu, have %lu",
00236                    fh_size, fh_desc->len);
00237           ReturnCode(ERR_FSAL_TOOSMALL, 0);
00238         }
00239       memcpy(fh_desc->start, (caddr_t)p_in_fsal_handle, fh_size);
00240       fh_desc->len = fh_size;
00241       break;
00242   
00243    case FSAL_DIGEST_FILEID2:
00244       memcpy(fh_desc->start, p_in_fsal_handle->data.vfs_handle.handle, FSAL_DIGEST_SIZE_FILEID2);
00245       fh_desc->len = FSAL_DIGEST_SIZE_FILEID2;
00246       break;
00247 
00248    case FSAL_DIGEST_FILEID3:
00249       /* Extracting FileId from VFS handle requires internal knowledge on the handle's structure 
00250        * which is given by 'struct fid' in kernel's sources. For most FS, it looks like this:
00251        * struct fid {
00252         union {
00253                 struct {
00254                         u32 ino;
00255                         u32 gen;
00256                         u32 parent_ino;
00257                         u32 parent_gen;
00258                 } i32;
00259                 struct {
00260                         u32 block;
00261                         u16 partref;
00262                         u16 parent_partref;
00263                         u32 generation;
00264                         u32 parent_block;
00265                         u32 parent_generation;
00266                 } udf;
00267                 __u32 raw[0];
00268         };
00269       }; 
00270       This means that in most cases, fileid will be found in the first 32 bits of the structure. But there are exception
00271       BTRFS is one of them, with a struct fid like this 
00272       struct btrfs_fid {
00273         u64 objectid;
00274         u64 root_objectid;
00275         u32 gen;
00276 
00277         u64 parent_objectid;
00278         u32 parent_gen;
00279 
00280         u64 parent_root_objectid;
00281       } __attribute__ ((packed));*/
00282       memcpy(&ino32, p_in_fsal_handle->data.vfs_handle.handle, sizeof(ino32));
00283       ino64 = ino32;
00284       memcpy(fh_desc->start, &ino64, FSAL_DIGEST_SIZE_FILEID3);
00285       fh_desc->len = FSAL_DIGEST_SIZE_FILEID3;
00286       break;
00287 
00288 
00289    case FSAL_DIGEST_FILEID4:
00290       memcpy(&ino32, p_in_fsal_handle->data.vfs_handle.handle, sizeof(ino32));
00291       ino64 = ino32;
00292       memcpy(fh_desc->start, &ino64, FSAL_DIGEST_SIZE_FILEID4);
00293       fh_desc->len = FSAL_DIGEST_SIZE_FILEID4;
00294       break;
00295 
00296     default:
00297       ReturnCode(ERR_FSAL_SERVERFAULT, 0);
00298 
00299     }
00300 
00301   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00302 
00303 }
00304 
00321 fsal_status_t VFSFSAL_ExpandHandle(fsal_export_context_t * p_expcontext,     /* IN not used */
00322                                    fsal_digesttype_t in_type,   /* IN */
00323                                    struct fsal_handle_desc *fh_desc  /* IN/OUT */ )
00324 {
00325   struct file_handle *hdl;
00326   size_t fh_size;
00327 
00328   /* sanity checks */
00329   if( !fh_desc || !fh_desc->start)
00330     ReturnCode(ERR_FSAL_FAULT, 0);
00331 
00332   hdl = (struct file_handle *)fh_desc->start;
00333   fh_size = vfs_sizeof_handle(hdl);
00334   if(in_type == FSAL_DIGEST_NFSV2)
00335     {
00336       if(fh_desc->len < fh_size)
00337         {
00338           LogMajor(COMPONENT_FSAL,
00339                    "VFS ExpandHandle: V2 size too small for handle.  should be %lu, got %lu",
00340                    fh_size, fh_desc->len);
00341           ReturnCode(ERR_FSAL_SERVERFAULT, 0);
00342         }
00343     }
00344   else if(in_type != FSAL_DIGEST_SIZEOF && fh_desc->len != fh_size)
00345     {
00346       LogMajor(COMPONENT_FSAL,
00347                "VFS ExpandHandle: size mismatch for handle.  should be %lu, got %lu",
00348                fh_size, fh_desc->len);
00349       ReturnCode(ERR_FSAL_SERVERFAULT, 0);
00350     }
00351   fh_desc->len = fh_size;  /* pass back the actual size */
00352   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00353 
00354 }
00355 
00364 fsal_status_t VFSFSAL_SetDefault_FS_specific_parameter(fsal_parameter_t * out_parameter)
00365 {
00366   /* defensive programming... */
00367   if(out_parameter == NULL)
00368     ReturnCode(ERR_FSAL_FAULT, 0);
00369 
00370   /* set default values for all parameters of fs_specific_info */
00371 
00372 #ifdef _USE_PGSQL
00373 
00374   /* pgsql db */
00375 q  strcpy(out_parameter->fs_specific_info.dbparams.host, "localhost");
00376   strcpy(out_parameter->fs_specific_info.dbparams.port, "5432");
00377   out_parameter->fs_specific_info.dbparams.dbname[0] = '\0';
00378   out_parameter->fs_specific_info.dbparams.login[0] = '\0';
00379   out_parameter->fs_specific_info.dbparams.passwdfile[0] = '\0';
00380 
00381 #elif defined(_USE_MYSQL)
00382 
00383   strcpy(out_parameter->fs_specific_info.dbparams.host, "localhost");
00384   strcpy(out_parameter->fs_specific_info.dbparams.port, "");
00385   out_parameter->fs_specific_info.dbparams.dbname[0] = '\0';
00386   out_parameter->fs_specific_info.dbparams.login[0] = '\0';
00387   out_parameter->fs_specific_info.dbparams.passwdfile[0] = '\0';
00388 
00389 #endif
00390 
00391   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00392 
00393 }
00394 
00416 /* load FSAL init info */
00417 
00418 
00419 /* load specific filesystem configuration options */
00420 fsal_status_t VFSFSAL_load_FS_specific_parameter_from_conf(config_file_t in_config,
00421                                                            fsal_parameter_t *
00422                                                            out_parameter)
00423 {
00424 
00425   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00426 
00427 }                               /* FSAL_load_FS_specific_parameter_from_conf */