nfs-ganesha 1.4

fsal_internal.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 
00015 #define FSAL_INTERNAL_C
00016 #ifdef HAVE_CONFIG_H
00017 #include "config.h"
00018 #endif
00019 
00020 #include "fsal_internal.h"
00021 #include "SemN.h"
00022 #include "fsal_convert.h"
00023 #include <libgen.h>             /* used for 'dirname' */
00024 
00025 #include <pthread.h>
00026 #include <string.h>
00027 #include "abstract_mem.h"
00028 
00029 /* credential lifetime (1h) */
00030 fsal_uint_t CredentialLifetime = 3600;
00031 
00032 /* static filesystem info.
00033  * The access is thread-safe because
00034  * it is read-only, except during initialization.
00035  */
00036 fsal_staticfsinfo_t global_fs_info;
00037 
00038 /* filesystem info for HPSS */
00039 static fsal_staticfsinfo_t default_posix_info = {
00040   0xFFFFFFFFFFFFFFFFLL,         /* max file size (64bits) */
00041   _POSIX_LINK_MAX,              /* max links */
00042   FSAL_MAX_NAME_LEN,            /* max filename */
00043   FSAL_MAX_PATH_LEN,            /* max pathlen */
00044   TRUE,                         /* no_trunc */
00045   TRUE,                         /* chown restricted */
00046   FALSE,                        /* case insensitivity */
00047   TRUE,                         /* case preserving */
00048   FSAL_EXPTYPE_PERSISTENT,      /* FH expire type */
00049   TRUE,                         /* hard link support */
00050   TRUE,                         /* symlink support */
00051   TRUE,                         /* lock management */
00052   FALSE,                        /* lock owners */
00053   FALSE,                        /* async blocking locks */
00054   TRUE,                         /* named attributes */
00055   TRUE,                         /* handles are unique and persistent */
00056   {10, 0},                      /* Duration of lease at FS in seconds */
00057   FSAL_ACLSUPPORT_ALLOW,        /* ACL support */
00058   TRUE,                         /* can change times */
00059   TRUE,                         /* homogenous */
00060   POSIX_SUPPORTED_ATTRIBUTES,   /* supported attributes */
00061   0,                            /* maxread size */
00062   0,                            /* maxwrite size */
00063   0,                            /* default umask */
00064   0,                            /* cross junctions */
00065   0400,                         /* default access rights for xattrs: root=RW, owner=R */
00066   0,                            /* default access check support in FSAL */
00067   0,                            /* default share reservation support in FSAL */
00068   0                             /* default share reservation support with open owners in FSAL */
00069 };
00070 
00071 
00072 
00073 /* variables for limiting the calls to the filesystem */
00074 static int limit_calls = FALSE;
00075 semaphore_t sem_fs_calls;
00076 
00077 /* threads keys for stats */
00078 static pthread_key_t key_stats;
00079 static pthread_once_t once_key = PTHREAD_ONCE_INIT;
00080 
00081 /* init keys */
00082 static void init_keys(void)
00083 {
00084   if(pthread_key_create(&key_stats, NULL) == -1)
00085     LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_KEY_CREATE, errno);
00086 
00087   return;
00088 }                               /* init_keys */
00089 
00101 void fsal_increment_nbcall(int function_index, fsal_status_t status)
00102 {
00103 
00104   fsal_statistics_t *bythread_stat = NULL;
00105 
00106   /* verify index */
00107 
00108   if(function_index >= FSAL_NB_FUNC)
00109     return;
00110 
00111   /* first, we init the keys if this is the first time */
00112 
00113   if(pthread_once(&once_key, init_keys) != 0)
00114     {
00115       LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_ONCE, errno);
00116       return;
00117     }
00118 
00119   /* we get the specific value */
00120 
00121   bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats);
00122 
00123   /* we allocate stats if this is the first time */
00124 
00125   if(bythread_stat == NULL)
00126     {
00127       int i;
00128 
00129       bythread_stat = gsh_malloc(sizeof(fsal_statistics_t));
00130 
00131       if(bythread_stat == NULL)
00132         {
00133           LogError(COMPONENT_FSAL, ERR_SYS, ERR_MALLOC, ENOMEM);
00134         }
00135 
00136       /* inits the struct */
00137 
00138       for(i = 0; i < FSAL_NB_FUNC; i++)
00139         {
00140           bythread_stat->func_stats.nb_call[i] = 0;
00141           bythread_stat->func_stats.nb_success[i] = 0;
00142           bythread_stat->func_stats.nb_err_retryable[i] = 0;
00143           bythread_stat->func_stats.nb_err_unrecover[i] = 0;
00144         }
00145 
00146       /* set the specific value */
00147       pthread_setspecific(key_stats, (void *)bythread_stat);
00148 
00149     }
00150 
00151   /* we increment the values */
00152 
00153   if(bythread_stat)
00154     {
00155       bythread_stat->func_stats.nb_call[function_index]++;
00156 
00157       if(!FSAL_IS_ERROR(status))
00158         bythread_stat->func_stats.nb_success[function_index]++;
00159       else if(status.major == ERR_FSAL_DELAY)   /* Error is retryable */
00160         bythread_stat->func_stats.nb_err_retryable[function_index]++;
00161       else
00162         bythread_stat->func_stats.nb_err_unrecover[function_index]++;
00163     }
00164 
00165   return;
00166 }
00167 
00178 void fsal_internal_getstats(fsal_statistics_t * output_stats)
00179 {
00180 
00181   fsal_statistics_t *bythread_stat = NULL;
00182 
00183   /* first, we init the keys if this is the first time */
00184   if(pthread_once(&once_key, init_keys) != 0)
00185     {
00186       LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_ONCE, errno);
00187       return;
00188     }
00189 
00190   /* we get the specific value */
00191   bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats);
00192 
00193   /* we allocate stats if this is the first time */
00194   if(bythread_stat == NULL)
00195     {
00196       int i;
00197 
00198       if((bythread_stat =
00199           gsh_malloc(sizeof(fsal_statistics_t))) == NULL)
00200         LogError(COMPONENT_FSAL, ERR_SYS, ERR_MALLOC, ENOMEM);
00201 
00202       /* inits the struct */
00203       for(i = 0; i < FSAL_NB_FUNC; i++)
00204         {
00205           bythread_stat->func_stats.nb_call[i] = 0;
00206           bythread_stat->func_stats.nb_success[i] = 0;
00207           bythread_stat->func_stats.nb_err_retryable[i] = 0;
00208           bythread_stat->func_stats.nb_err_unrecover[i] = 0;
00209         }
00210 
00211       /* set the specific value */
00212       pthread_setspecific(key_stats, (void *)bythread_stat);
00213 
00214     }
00215 
00216   if(output_stats)
00217     (*output_stats) = (*bythread_stat);
00218 
00219   return;
00220 
00221 }
00222 
00233 void fsal_internal_SetCredentialLifetime(fsal_uint_t lifetime_in)
00234 {
00235   CredentialLifetime = lifetime_in;
00236 }
00237 
00241 void TakeTokenFSCall()
00242 {
00243   /* no limits */
00244   if(limit_calls == FALSE)
00245     return;
00246 
00247   /* there is a limit */
00248   semaphore_P(&sem_fs_calls);
00249 
00250 }
00251 
00252 void ReleaseTokenFSCall()
00253 {
00254   /* no limits */
00255   if(limit_calls == FALSE)
00256     return;
00257 
00258   /* there is a limit */
00259   semaphore_V(&sem_fs_calls);
00260 
00261 }
00262 
00263 /*
00264  *  This function initializes shared variables of the fsal.
00265  */
00266 fsal_status_t fsal_internal_init_global(fsal_init_info_t * fsal_info,
00267                                         fs_common_initinfo_t * fs_common_info,
00268                                         fs_specific_initinfo_t * fs_specific_info)
00269 {
00270 
00271   /* sanity check */
00272   if(!fsal_info || !fs_common_info || !fs_specific_info)
00273     ReturnCode(ERR_FSAL_FAULT, 0);
00274 
00275 
00276   /* inits FS call semaphore */
00277   if(fsal_info->max_fs_calls > 0)
00278     {
00279       int rc;
00280 
00281       limit_calls = TRUE;
00282 
00283       rc = semaphore_init(&sem_fs_calls, fsal_info->max_fs_calls);
00284 
00285       if(rc != 0)
00286         ReturnCode(ERR_FSAL_SERVERFAULT, rc);
00287 
00288       LogDebug(COMPONENT_FSAL,
00289                         "FSAL INIT: Max simultaneous calls to filesystem is limited to %u.",
00290                         fsal_info->max_fs_calls);
00291 
00292     }
00293   else
00294     {
00295       LogDebug(COMPONENT_FSAL,
00296                         "FSAL INIT: Max simultaneous calls to filesystem is unlimited.");
00297     }
00298 
00299   /* setting default values. */
00300   global_fs_info = default_posix_info;
00301 
00302   if (isFullDebug(COMPONENT_FSAL))
00303     {
00304       display_fsinfo(&default_posix_info);
00305     }
00306 
00307   /* Analyzing fs_common_info struct */
00308 
00309   if((fs_common_info->behaviors.maxfilesize != FSAL_INIT_FS_DEFAULT) ||
00310      (fs_common_info->behaviors.maxlink != FSAL_INIT_FS_DEFAULT) ||
00311      (fs_common_info->behaviors.maxnamelen != FSAL_INIT_FS_DEFAULT) ||
00312      (fs_common_info->behaviors.maxpathlen != FSAL_INIT_FS_DEFAULT) ||
00313      (fs_common_info->behaviors.no_trunc != FSAL_INIT_FS_DEFAULT) ||
00314      (fs_common_info->behaviors.case_insensitive != FSAL_INIT_FS_DEFAULT) ||
00315      (fs_common_info->behaviors.case_preserving != FSAL_INIT_FS_DEFAULT) ||
00316      (fs_common_info->behaviors.named_attr != FSAL_INIT_FS_DEFAULT) ||
00317      (fs_common_info->behaviors.lease_time != FSAL_INIT_FS_DEFAULT) ||
00318      (fs_common_info->behaviors.supported_attrs != FSAL_INIT_FS_DEFAULT) ||
00319      (fs_common_info->behaviors.homogenous != FSAL_INIT_FS_DEFAULT))
00320     ReturnCode(ERR_FSAL_NOTSUPP, 0);
00321 
00322   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, symlink_support);
00323   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, link_support);
00324   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support);
00325   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_owner);
00326   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_async_block);
00327   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, cansettime);
00328 
00329   SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxread);
00330   SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxwrite);
00331 
00332   SET_BITMAP_PARAM(global_fs_info, fs_common_info, umask);
00333 
00334   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, auth_exportpath_xdev);
00335 
00336   SET_BITMAP_PARAM(global_fs_info, fs_common_info, xattr_access_rights);
00337 
00338   LogFullDebug(COMPONENT_FSAL,
00339                     "Supported attributes constant = 0x%llX.",
00340                     POSIX_SUPPORTED_ATTRIBUTES);
00341 
00342   LogFullDebug(COMPONENT_FSAL,
00343                     "Supported attributes default = 0x%llX.",
00344                     default_posix_info.supported_attrs);
00345 
00346   LogDebug(COMPONENT_FSAL,
00347                     "FSAL INIT: Supported attributes mask = 0x%llX.",
00348                     global_fs_info.supported_attrs);
00349 
00350   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00351 }
00352 
00361 fsal_status_t fsal_internal_appendNameToPath(fsal_path_t * p_path,
00362                                              const fsal_name_t * p_name)
00363 {
00364   char *end;
00365   if(!p_path || !p_name)
00366     ReturnCode(ERR_FSAL_FAULT, 0);
00367 
00368   end = p_path->path + p_path->len - 1;
00369   if(*end != '/')
00370     {
00371       if(p_path->len + 1 + p_name->len > FSAL_MAX_PATH_LEN)
00372         ReturnCode(ERR_FSAL_NAMETOOLONG, 0);
00373       p_path->len += p_name->len + 1;
00374       end++;
00375       *end = '/';
00376       end++;
00377       strcpy(end, p_name->name);
00378     }
00379   else
00380     {
00381       if(p_path->len + p_name->len > FSAL_MAX_PATH_LEN)
00382         ReturnCode(ERR_FSAL_NAMETOOLONG, 0);
00383       p_path->len += p_name->len;
00384       end++;
00385       strcpy(end, p_name->name);
00386     }
00387 
00388   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00389 }
00390 
00391 #define FIDDIR      ".lustre/fid"
00392 #define FIDDIRLEN   11
00393 
00397 fsal_status_t fsal_internal_Handle2FidPath(fsal_op_context_t *context, /* IN */
00398                                            fsal_handle_t * p_handle,    /* IN */
00399                                            fsal_path_t * p_fsalpath /* OUT */ )
00400 {
00401   char *curr = p_fsalpath->path;
00402   lustrefsal_op_context_t * p_context = (lustrefsal_op_context_t *)context;
00403 
00404   if(!p_context || !p_context->export_context || !p_handle || !p_fsalpath)
00405     ReturnCode(ERR_FSAL_FAULT, 0);
00406 
00407   /* filesystem root */
00408   strcpy(p_fsalpath->path, p_context->export_context->mount_point);
00409   curr += p_context->export_context->mnt_len;
00410 
00411   /* fid directory */
00412   strcpy(curr, "/" FIDDIR "/");
00413   curr += FIDDIRLEN + 2;
00414 
00415   /* add fid string */
00416   curr += sprintf(curr, DFID_NOBRACE, PFID(&((lustrefsal_handle_t *)p_handle)->data.fid));
00417 
00418   p_fsalpath->len = (curr - p_fsalpath->path);
00419 
00420   LogFullDebug(COMPONENT_FSAL, "FidPath=%s (len %u)", p_fsalpath->path,
00421                   p_fsalpath->len);
00422 
00423   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00424 }
00425 
00429 fsal_status_t fsal_internal_Path2Handle(fsal_op_context_t * p_context,    /* IN */
00430                                         fsal_path_t * p_fsalpath,       /* IN */
00431                                         fsal_handle_t *handle /* OUT */ )
00432 {
00433   int rc;
00434   struct stat ino;
00435   lustre_fid fid;
00436   lustrefsal_handle_t * p_handle = (lustrefsal_handle_t *)handle;
00437 
00438   if(!p_context || !p_handle || !p_fsalpath)
00439     ReturnCode(ERR_FSAL_FAULT, 0);
00440 
00441   memset(p_handle, 0, sizeof(lustrefsal_handle_t));
00442 
00443   LogFullDebug(COMPONENT_FSAL, "Lookup handle for %s", p_fsalpath->path);
00444 
00445   rc = llapi_path2fid(p_fsalpath->path, &fid);
00446 
00447   LogFullDebug(COMPONENT_FSAL, "llapi_path2fid(%s): status=%d, fid=" DFID_NOBRACE,
00448                   p_fsalpath->path, rc, PFID(&fid));
00449 
00450   if(rc)
00451     ReturnCode(posix2fsal_error(-rc), -rc);
00452 
00453   p_handle->data.fid = fid;
00454 
00455   /* retrieve inode */
00456   rc = lstat(p_fsalpath->path, &ino);
00457 
00458   if(rc)
00459     LogFullDebug(COMPONENT_FSAL, "lstat(%s)=%d, errno=%d", p_fsalpath->path, rc,
00460                     errno);
00461   if(rc)
00462     ReturnCode(posix2fsal_error(errno), errno);
00463 
00464   p_handle->data.inode = ino.st_ino;
00465 
00466   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00467 }
00468 
00469 /*
00470    Check the access from an existing fsal_attrib_list_t or struct stat
00471 */
00472 /* XXX : ACL */
00473 fsal_status_t fsal_internal_testAccess(fsal_op_context_t * p_context,     /* IN */
00474                                        fsal_accessflags_t access_type,  /* IN */
00475                                        struct stat *p_buffstat, /* IN */
00476                                        fsal_attrib_list_t * p_object_attributes /* IN */ )
00477 {
00478   fsal_accessflags_t missing_access;
00479   unsigned int is_grp, i;
00480   fsal_uid_t uid;
00481   fsal_gid_t gid;
00482   fsal_accessmode_t mode;
00483 
00484   /* sanity checks. */
00485 
00486   if((!p_object_attributes && !p_buffstat) || !p_context)
00487     ReturnCode(ERR_FSAL_FAULT, 0);
00488 
00489   /* If the FSAL_F_OK flag is set, returns ERR INVAL */
00490 
00491   if(access_type & FSAL_F_OK)
00492     ReturnCode(ERR_FSAL_INVAL, 0);
00493 
00494   /* test root access */
00495 
00496   if(p_context->credential.user == 0)
00497     ReturnCode(ERR_FSAL_NO_ERROR, 0);
00498 
00499   /* unsatisfied flags */
00500 
00501   missing_access = FSAL_MODE_MASK(access_type); /* only modes, no ACLs here */
00502 
00503 
00504   if(p_object_attributes)
00505     {
00506       uid = p_object_attributes->owner;
00507       gid = p_object_attributes->group;
00508       mode = p_object_attributes->mode;
00509     }
00510   else
00511     {
00512       uid = p_buffstat->st_uid;
00513       gid = p_buffstat->st_gid;
00514       mode = unix2fsal_mode(p_buffstat->st_mode);
00515     }
00516 
00517   /* Test if file belongs to user. */
00518 
00519   if(p_context->credential.user == uid)
00520     {
00521       LogFullDebug(COMPONENT_FSAL, "File belongs to user %d", uid);
00522 
00523       if(mode & FSAL_MODE_RUSR)
00524         missing_access &= ~FSAL_R_OK;
00525 
00526       if(mode & FSAL_MODE_WUSR)
00527         missing_access &= ~FSAL_W_OK;
00528 
00529       if(mode & FSAL_MODE_XUSR)
00530         missing_access &= ~FSAL_X_OK;
00531 
00532       if(missing_access == 0)
00533         ReturnCode(ERR_FSAL_NO_ERROR, 0);
00534       else
00535         {
00536           LogFullDebug(COMPONENT_FSAL,
00537                             "Mode=%#o, Access=%#o, Rights missing: %#o", mode,
00538                             access_type, missing_access);
00539           ReturnCode(ERR_FSAL_ACCESS, 0);
00540         }
00541 
00542     }
00543 
00544   /* Test if the file belongs to user's group. */
00545 
00546   is_grp = (p_context->credential.group == gid);
00547 
00548   if(is_grp)
00549     LogFullDebug(COMPONENT_FSAL, "File belongs to user's group %d",
00550                       p_context->credential.group);
00551 
00552   /* Test if file belongs to alt user's groups */
00553 
00554   if(!is_grp)
00555     {
00556       for(i = 0; i < p_context->credential.nbgroups; i++)
00557         {
00558           is_grp = (p_context->credential.alt_groups[i] == gid);
00559 
00560           if(is_grp)
00561             LogFullDebug(COMPONENT_FSAL,
00562                               "File belongs to user's alt group %d",
00563                               p_context->credential.alt_groups[i]);
00564 
00565           // exits loop if found
00566           if(is_grp)
00567             break;
00568         }
00569     }
00570 
00571   /* finally apply group rights */
00572 
00573   if(is_grp)
00574     {
00575       if(mode & FSAL_MODE_RGRP)
00576         missing_access &= ~FSAL_R_OK;
00577 
00578       if(mode & FSAL_MODE_WGRP)
00579         missing_access &= ~FSAL_W_OK;
00580 
00581       if(mode & FSAL_MODE_XGRP)
00582         missing_access &= ~FSAL_X_OK;
00583 
00584       if(missing_access == 0)
00585         ReturnCode(ERR_FSAL_NO_ERROR, 0);
00586       else
00587         ReturnCode(ERR_FSAL_ACCESS, 0);
00588 
00589     }
00590 
00591   /* test other perms */
00592 
00593   if(mode & FSAL_MODE_ROTH)
00594     missing_access &= ~FSAL_R_OK;
00595 
00596   if(mode & FSAL_MODE_WOTH)
00597     missing_access &= ~FSAL_W_OK;
00598 
00599   if(mode & FSAL_MODE_XOTH)
00600     missing_access &= ~FSAL_X_OK;
00601 
00602   /* XXX ACLs. */
00603 
00604   if(missing_access == 0)
00605     ReturnCode(ERR_FSAL_NO_ERROR, 0);
00606   else
00607     ReturnCode(ERR_FSAL_ACCESS, 0);
00608 
00609 }