nfs-ganesha 1.4

fsal_internal.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 
00036 #define FSAL_INTERNAL_C
00037 #ifdef HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040 
00041 #include  "fsal.h"
00042 #include "fsal_internal.h"
00043 #include "SemN.h"
00044 #include "fsal_convert.h"
00045 #include <libgen.h>             /* used for 'dirname' */
00046 #include <pthread.h>
00047 #include <string.h>
00048 #include <sys/types.h>
00049 #include <mntent.h>
00050 #include "abstract_mem.h"
00051 
00052 
00053 /* Add missing prototype in vfs.h */
00054 int fd_to_handle(int fd, void **hanp, size_t * hlen);
00055 
00056 /* credential lifetime (1h) */
00057 fsal_uint_t CredentialLifetime = 3600;
00058 
00059 /* static filesystem info.
00060  * The access is thread-safe because
00061  * it is read-only, except during initialization.
00062  */
00063 fsal_staticfsinfo_t global_fs_info;
00064 
00065 /* filesystem info for VFS */
00066 static fsal_staticfsinfo_t default_posix_info = {
00067   0xFFFFFFFFFFFFFFFFLL,         /* max file size (64bits) */
00068   _POSIX_LINK_MAX,              /* max links */
00069   FSAL_MAX_NAME_LEN,            /* max filename */
00070   FSAL_MAX_PATH_LEN,            /* max pathlen */
00071   TRUE,                         /* no_trunc */
00072   TRUE,                         /* chown restricted */
00073   FALSE,                        /* case insensitivity */
00074   TRUE,                         /* case preserving */
00075   FSAL_EXPTYPE_PERSISTENT,      /* FH expire type */
00076   TRUE,                         /* hard link support */
00077   TRUE,                         /* symlink support */
00078   TRUE,                         /* lock management */
00079   FALSE,                        /* lock owners */
00080   FALSE,                        /* async blocking locks */
00081   TRUE,                         /* named attributes */
00082   TRUE,                         /* handles are unique and persistent */
00083   {10, 0},                      /* Duration of lease at FS in seconds */
00084   FSAL_ACLSUPPORT_ALLOW,        /* ACL support */
00085   TRUE,                         /* can change times */
00086   TRUE,                         /* homogenous */
00087   VFS_SUPPORTED_ATTRIBUTES,     /* supported attributes */
00088   0,                            /* maxread size */
00089   0,                            /* maxwrite size */
00090   0,                            /* default umask */
00091   0,                            /* cross junctions */
00092   0400,                         /* default access rights for xattrs: root=RW, owner=R */
00093   0,                            /* default access check support in FSAL */
00094   0,                            /* default share reservation support in FSAL */
00095   0                             /* default share reservation support with open owners in FSAL */
00096 };
00097 
00098 /* variables for limiting the calls to the filesystem */
00099 static int limit_calls = FALSE;
00100 semaphore_t sem_fs_calls;
00101 
00102 /* threads keys for stats */
00103 static pthread_key_t key_stats;
00104 static pthread_once_t once_key = PTHREAD_ONCE_INIT;
00105 
00106 /* init keys */
00107 static void init_keys(void)
00108 {
00109   if(pthread_key_create(&key_stats, NULL) == -1)
00110     LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_KEY_CREATE, errno);
00111 
00112   return;
00113 }                               /* init_keys */
00114 
00126 void fsal_increment_nbcall(int function_index, fsal_status_t status)
00127 {
00128 
00129   fsal_statistics_t *bythread_stat = NULL;
00130 
00131   /* verify index */
00132 
00133   if(function_index >= FSAL_NB_FUNC)
00134     return;
00135 
00136   /* first, we init the keys if this is the first time */
00137 
00138   if(pthread_once(&once_key, init_keys) != 0)
00139     {
00140       LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_ONCE, errno);
00141       return;
00142     }
00143 
00144   /* we get the specific value */
00145 
00146   bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats);
00147 
00148   /* we allocate stats if this is the first time */
00149 
00150   if(bythread_stat == NULL)
00151     {
00152       int i;
00153 
00154       bythread_stat = gsh_malloc(sizeof(fsal_statistics_t));
00155 
00156       if(bythread_stat == NULL)
00157         {
00158           LogError(COMPONENT_FSAL, ERR_SYS, ERR_MALLOC, ENOMEM);
00159         }
00160 
00161       /* inits the struct */
00162 
00163       for(i = 0; i < FSAL_NB_FUNC; i++)
00164         {
00165           bythread_stat->func_stats.nb_call[i] = 0;
00166           bythread_stat->func_stats.nb_success[i] = 0;
00167           bythread_stat->func_stats.nb_err_retryable[i] = 0;
00168           bythread_stat->func_stats.nb_err_unrecover[i] = 0;
00169         }
00170 
00171       /* set the specific value */
00172       pthread_setspecific(key_stats, (void *)bythread_stat);
00173 
00174     }
00175 
00176   /* we increment the values */
00177 
00178   if(bythread_stat)
00179     {
00180       bythread_stat->func_stats.nb_call[function_index]++;
00181 
00182       if(!FSAL_IS_ERROR(status))
00183         bythread_stat->func_stats.nb_success[function_index]++;
00184       else if(status.major == ERR_FSAL_DELAY)   /* Error is retryable */
00185         bythread_stat->func_stats.nb_err_retryable[function_index]++;
00186       else
00187         bythread_stat->func_stats.nb_err_unrecover[function_index]++;
00188     }
00189 
00190   return;
00191 }
00192 
00203 void fsal_internal_getstats(fsal_statistics_t * output_stats)
00204 {
00205 
00206   fsal_statistics_t *bythread_stat = NULL;
00207 
00208   /* first, we init the keys if this is the first time */
00209   if(pthread_once(&once_key, init_keys) != 0)
00210     {
00211       LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_ONCE, errno);
00212       return;
00213     }
00214 
00215   /* we get the specific value */
00216   bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats);
00217 
00218   /* we allocate stats if this is the first time */
00219   if(bythread_stat == NULL)
00220     {
00221       int i;
00222 
00223       if((bythread_stat =
00224           gsh_malloc(sizeof(fsal_statistics_t))) == NULL)
00225         LogError(COMPONENT_FSAL, ERR_SYS, ERR_MALLOC, ENOMEM);
00226 
00227       /* inits the struct */
00228       for(i = 0; i < FSAL_NB_FUNC; i++)
00229         {
00230           bythread_stat->func_stats.nb_call[i] = 0;
00231           bythread_stat->func_stats.nb_success[i] = 0;
00232           bythread_stat->func_stats.nb_err_retryable[i] = 0;
00233           bythread_stat->func_stats.nb_err_unrecover[i] = 0;
00234         }
00235 
00236       /* set the specific value */
00237       pthread_setspecific(key_stats, (void *)bythread_stat);
00238 
00239     }
00240 
00241   if(output_stats)
00242     (*output_stats) = (*bythread_stat);
00243 
00244   return;
00245 
00246 }
00247 
00251 void TakeTokenFSCall()
00252 {
00253   /* no limits */
00254   if(limit_calls == FALSE)
00255     return;
00256 
00257   /* there is a limit */
00258   semaphore_P(&sem_fs_calls);
00259 
00260 }
00261 
00262 void ReleaseTokenFSCall()
00263 {
00264   /* no limits */
00265   if(limit_calls == FALSE)
00266     return;
00267 
00268   /* there is a limit */
00269   semaphore_V(&sem_fs_calls);
00270 
00271 }
00272 
00273 /*
00274  *  This function initializes shared variables of the fsal.
00275  */
00276 fsal_status_t fsal_internal_init_global(fsal_init_info_t * fsal_info,
00277                                         fs_common_initinfo_t * fs_common_info,
00278                                         fs_specific_initinfo_t * fs_specific_info)
00279 {
00280 
00281   /* sanity check */
00282   if(!fsal_info || !fs_common_info || !fs_specific_info)
00283     ReturnCode(ERR_FSAL_FAULT, 0);
00284 
00285   /* inits FS call semaphore */
00286   if(fsal_info->max_fs_calls > 0)
00287     {
00288       int rc;
00289 
00290       limit_calls = TRUE;
00291 
00292       rc = semaphore_init(&sem_fs_calls, fsal_info->max_fs_calls);
00293 
00294       if(rc != 0)
00295         ReturnCode(ERR_FSAL_SERVERFAULT, rc);
00296 
00297       LogDebug(COMPONENT_FSAL,
00298                         "FSAL INIT: Max simultaneous calls to filesystem is limited to %u.",
00299                         fsal_info->max_fs_calls);
00300 
00301     }
00302   else
00303     {
00304       LogDebug(COMPONENT_FSAL,
00305                         "FSAL INIT: Max simultaneous calls to filesystem is unlimited.");
00306     }
00307 
00308   /* setting default values. */
00309   global_fs_info = default_posix_info;
00310 
00311   display_fsinfo(&default_posix_info);
00312 
00313   /* Analyzing fs_common_info struct */
00314 
00315   if((fs_common_info->behaviors.maxfilesize != FSAL_INIT_FS_DEFAULT) ||
00316      (fs_common_info->behaviors.maxlink != FSAL_INIT_FS_DEFAULT) ||
00317      (fs_common_info->behaviors.maxnamelen != FSAL_INIT_FS_DEFAULT) ||
00318      (fs_common_info->behaviors.maxpathlen != FSAL_INIT_FS_DEFAULT) ||
00319      (fs_common_info->behaviors.no_trunc != FSAL_INIT_FS_DEFAULT) ||
00320      (fs_common_info->behaviors.case_insensitive != FSAL_INIT_FS_DEFAULT) ||
00321      (fs_common_info->behaviors.case_preserving != FSAL_INIT_FS_DEFAULT) ||
00322      (fs_common_info->behaviors.named_attr != FSAL_INIT_FS_DEFAULT) ||
00323      (fs_common_info->behaviors.lease_time != FSAL_INIT_FS_DEFAULT) ||
00324      (fs_common_info->behaviors.supported_attrs != FSAL_INIT_FS_DEFAULT) ||
00325      (fs_common_info->behaviors.homogenous != FSAL_INIT_FS_DEFAULT))
00326     ReturnCode(ERR_FSAL_NOTSUPP, 0);
00327 
00328   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, symlink_support);
00329   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, link_support);
00330   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support);
00331   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_owner);
00332   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_async_block);
00333   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, cansettime);
00334 
00335   SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxread);
00336   SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxwrite);
00337 
00338   SET_BITMAP_PARAM(global_fs_info, fs_common_info, umask);
00339 
00340   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, auth_exportpath_xdev);
00341 
00342   SET_BITMAP_PARAM(global_fs_info, fs_common_info, xattr_access_rights);
00343 
00344   LogFullDebug(COMPONENT_FSAL,
00345                     "Supported attributes constant = 0x%llX.",
00346                     VFS_SUPPORTED_ATTRIBUTES);
00347 
00348   LogFullDebug(COMPONENT_FSAL,
00349                     "Supported attributes default = 0x%llX.",
00350                     default_posix_info.supported_attrs);
00351 
00352   LogDebug(COMPONENT_FSAL,
00353                     "FSAL INIT: Supported attributes mask = 0x%llX.",
00354                     global_fs_info.supported_attrs);
00355 
00356   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00357 }
00358 
00359 fsal_status_t fsal_internal_handle2fd(fsal_op_context_t * p_context,
00360                                       fsal_handle_t * p_handle, int *pfd, int oflags)
00361 {
00362   int rc = 0;
00363   int errsv;
00364 
00365 
00366   if(!p_handle || !pfd || !p_context)
00367     ReturnCode(ERR_FSAL_FAULT, 0);
00368 
00369 #if 0
00370   {
00371   char str[1024] ;
00372   sprint_mem( str, phandle->data.vfs_handle.handle, phandle->data.vfs_handle.handle_bytes ) ;
00373   printf( "=====> fsal_internal_handle2fd: type=%u bytes=%u|%s\n",
00374           phandle->data.vfs_handle.handle_type, phandle->data.vfs_handle.handle_bytes, str ) ;
00375   }
00376 #endif
00377 
00378 
00379   rc =  vfs_open_by_handle( ((vfsfsal_op_context_t *)p_context)->export_context->mount_root_fd,
00380                             &((vfsfsal_handle_t *)p_handle)->data.vfs_handle,
00381                             oflags ) ;
00382   if(rc == -1)
00383     {
00384       errsv = errno;
00385 
00386       ReturnCode(posix2fsal_error(errsv), errsv);
00387     }
00388 
00389   *pfd = rc;
00390 
00391   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00392 }                               /* fsal_internal_handle2fd */
00393 
00394 fsal_status_t fsal_internal_fd2handle( fsal_op_context_t *p_context,
00395                                        int fd, 
00396                                        fsal_handle_t *p_handle)
00397 {
00398   int rc = 0;
00399   int errsv; 
00400   int mnt_id = 0;
00401 
00402   memset(p_handle, 0, sizeof(vfsfsal_handle_t));
00403 
00404   ((vfsfsal_handle_t *)p_handle)->data.vfs_handle.handle_bytes = VFS_HANDLE_LEN ;
00405   if( ( rc = vfs_fd_to_handle( fd,
00406                                &((vfsfsal_handle_t *)p_handle)->data.vfs_handle,
00407                                &mnt_id ) ) )
00408     {
00409       errsv = errno;
00410       ReturnCode(posix2fsal_error(errsv), errsv);
00411     }
00412 
00413 #if 0
00414   {
00415     char str[1024] ;
00416     sprint_mem( str, p_handle->data.vfs_handle.handle, p_handle->data.vfs_handle.handle_bytes ) ;
00417     printf( "=====> fsal_internal_fd2handle: type=%u bytes=%u|%s\n",  
00418             p_handle->data.vfs_handle.handle_type, p_handle->data.vfs_handle.handle_bytes, str ) ;
00419   }
00420 #endif
00421 
00422   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00423 }                               /* fsal_internal_fd2handle */
00424 
00425 fsal_status_t fsal_internal_Path2Handle(fsal_op_context_t * p_context,       /* IN */
00426                                         fsal_path_t * p_fsalpath,       /* IN */
00427                                         fsal_handle_t * p_handle /* OUT */ )
00428 {
00429   int objectfd;
00430   fsal_status_t st;
00431 
00432   if(!p_context || !p_handle || !p_fsalpath)
00433     ReturnCode(ERR_FSAL_FAULT, 0);
00434 
00435   LogFullDebug(COMPONENT_FSAL, "Lookup handle for %s", p_fsalpath->path);
00436 
00437   if((objectfd = open(p_fsalpath->path, O_RDONLY, 0600)) < 0)
00438     ReturnCode(posix2fsal_error(errno), errno);
00439 
00440   st = fsal_internal_fd2handle(p_context, objectfd, p_handle);
00441   close(objectfd);
00442   return st;
00443 }                               /* fsal_internal_Path2Handle */
00444 
00445 
00460 fsal_status_t fsal_internal_get_handle_at(int dfd,      /* IN */
00461                                           const char *name,     /* IN */
00462                                           fsal_handle_t *p_handle      /* OUT
00463                                                                          */ )
00464 {
00465   int errsrv = 0 ;
00466 
00467   if( !name || !p_handle )
00468     ReturnCode(ERR_FSAL_FAULT, 0);
00469 
00470   memset(p_handle, 0, sizeof(vfsfsal_handle_t));
00471 
00472   LogFullDebug(COMPONENT_FSAL, "get handle at for %s", name);
00473 
00474   ((vfsfsal_handle_t *)p_handle)->data.vfs_handle.handle_bytes = VFS_HANDLE_LEN ;
00475   if( vfs_name_by_handle_at( dfd, name, &((vfsfsal_handle_t *)p_handle)->data.vfs_handle ) != 0 )
00476    {
00477       errsrv = errno;
00478       ReturnCode(posix2fsal_error(errsrv), errsrv);
00479    }
00480 
00481   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00482 } /* fsal_internal_get_handle_at */
00483 
00484 fsal_status_t fsal_internal_setattrs_symlink(fsal_handle_t * p_filehandle,   /* IN */
00485                                              fsal_op_context_t * p_context,  /* IN */
00486                                              fsal_attrib_list_t * p_attrib_set, /* IN */
00487                                              fsal_attrib_list_t * p_object_attributes)
00488 {
00489   if(!p_filehandle || !p_context || !p_attrib_set)
00490     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);
00491 
00492   *p_object_attributes = *p_attrib_set;
00493 
00494   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00495 }                               /* fsal_internal_setattrs_symlink */
00496 
00497