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 <sys/ioctl.h>
00042 #include  "fsal.h"
00043 #include "fsal_internal.h"
00044 #include "SemN.h"
00045 #include "fsal_convert.h"
00046 #include <libgen.h>             /* used for 'dirname' */
00047 #include "abstract_mem.h"
00048 
00049 #include <pthread.h>
00050 #include <string.h>
00051 #include <sys/fsuid.h>
00052 
00053 //#include "gpfs_nfs.h"
00054 #include "gpfs.h"
00055 
00056 #ifdef _USE_NFS4_ACL
00057 #define ACL_DEBUG_BUF_SIZE 256
00058 #endif                          /* _USE_NFS4_ACL */
00059 
00060 /* credential lifetime (1h) */
00061 fsal_uint_t CredentialLifetime = 3600;
00062 
00063 /* static filesystem info.
00064  * The access is thread-safe because
00065  * it is read-only, except during initialization.
00066  */
00067 fsal_staticfsinfo_t global_fs_info;
00068 
00069 /* filesystem info for HPSS */
00070 static fsal_staticfsinfo_t default_gpfs_info = {
00071   0xFFFFFFFFFFFFFFFFLL,         /* max file size (64bits) */
00072   _POSIX_LINK_MAX,              /* max links */
00073   FSAL_MAX_NAME_LEN,            /* max filename */
00074   FSAL_MAX_PATH_LEN,            /* max pathlen */
00075   TRUE,                         /* no_trunc */
00076   TRUE,                         /* chown restricted */
00077   FALSE,                        /* case insensitivity */
00078   TRUE,                         /* case preserving */
00079   FSAL_EXPTYPE_PERSISTENT,      /* FH expire type */
00080   TRUE,                         /* hard link support */
00081   TRUE,                         /* symlink support */
00082   TRUE,                         /* lock management */
00083   TRUE,                         /* lock owners */
00084   TRUE,                         /* async blocking locks */
00085   TRUE,                         /* named attributes */
00086   TRUE,                         /* handles are unique and persistent */
00087   {10, 0},                      /* Duration of lease at FS in seconds */
00088   FSAL_ACLSUPPORT_ALLOW,        /* ACL support */
00089   TRUE,                         /* can change times */
00090   TRUE,                         /* homogenous */
00091   GPFS_SUPPORTED_ATTRIBUTES,    /* supported attributes */
00092   1048576,                      /* maxread size DONT USE 0 */
00093   1048576,                      /* maxwrite size DONT USE 0 */
00094   0,                            /* default umask */
00095   0,                            /* cross junctions */
00096   0400,                         /* default access rights for xattrs: root=RW, owner=R */
00097   0,                            /* default access check support in FSAL */
00098   1,                            /* default share reservation support in FSAL */
00099   0                             /* default share reservation support with open owners in FSAL */
00100 };
00101 
00102 /* variables for limiting the calls to the filesystem */
00103 static int limit_calls = FALSE;
00104 semaphore_t sem_fs_calls;
00105 
00106 /* threads keys for stats */
00107 static pthread_key_t key_stats;
00108 static pthread_once_t once_key = PTHREAD_ONCE_INIT;
00109 
00110 #ifdef _USE_NFS4_ACL
00111 static fsal_status_t fsal_internal_testAccess_acl(fsal_op_context_t * p_context,   /* IN */
00112                                                   fsal_aceperm_t v4mask,  /* IN */
00113                                                   fsal_attrib_list_t * p_object_attributes   /* IN */ );
00114 
00115 static fsal_status_t fsal_check_access_by_handle(fsal_op_context_t * p_context,   /* IN */
00116                                                  fsal_handle_t * p_handle   /* IN */,
00117                                                  fsal_accessmode_t mode,   /* IN */
00118                                                  fsal_accessflags_t v4mask,   /* IN */
00119                                                  fsal_attrib_list_t * p_object_attributes   /* IN */ );
00120 
00121 extern fsal_status_t fsal_cred_2_gpfs_cred(struct user_credentials *p_fsalcred,
00122                                            struct xstat_cred_t *p_gpfscred);
00123 
00124 extern fsal_status_t fsal_mode_2_gpfs_mode(fsal_accessmode_t fsal_mode,
00125                                            fsal_accessflags_t v4mask,
00126                                            unsigned int *p_gpfsmode,
00127                                            fsal_boolean_t is_dir);
00128 #endif                          /* _USE_NFS4_ACL */
00129 
00130 static fsal_status_t fsal_internal_testAccess_no_acl(fsal_op_context_t * p_context,   /* IN */
00131                                                      fsal_accessflags_t access_type,  /* IN */
00132                                                      struct stat *p_buffstat, /* IN */
00133                                                      fsal_attrib_list_t * p_object_attributes /* IN */ );
00134 
00135 static void free_pthread_specific_stats(void *buff)
00136 {
00137   gsh_free(buff);
00138 }
00139 
00140 /* init keys */
00141 static void init_keys(void)
00142 {
00143   if(pthread_key_create(&key_stats, free_pthread_specific_stats) == -1)
00144     LogMajor(COMPONENT_FSAL,
00145              "Could not create thread specific stats (pthread_key_create) err %d (%s)",
00146              errno, strerror(errno));
00147 
00148   return;
00149 }                               /* init_keys */
00150 
00162 void fsal_increment_nbcall(int function_index, fsal_status_t status)
00163 {
00164 
00165   fsal_statistics_t *bythread_stat = NULL;
00166 
00167   /* verify index */
00168 
00169   if(function_index >= FSAL_NB_FUNC)
00170     return;
00171 
00172   /* first, we init the keys if this is the first time */
00173 
00174   if(pthread_once(&once_key, init_keys) != 0)
00175     {
00176       LogMajor(COMPONENT_FSAL,
00177                "Could not create thread specific stats (pthread_once) err %d (%s)",
00178                errno, strerror(errno));
00179       return;
00180     }
00181 
00182   /* we get the specific value */
00183 
00184   bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats);
00185 
00186   /* we allocate stats if this is the first time */
00187 
00188   if(bythread_stat == NULL)
00189     {
00190       int i;
00191 
00192       bythread_stat = gsh_malloc(sizeof(fsal_statistics_t));
00193 
00194       if(bythread_stat == NULL)
00195         {
00196           LogCrit(COMPONENT_FSAL,
00197                   "Could not allocate memory for FSAL statistics err %d (%s)",
00198                   ENOMEM, strerror(ENOMEM));
00199           /* we don't have real memory, bail */
00200           return;
00201         }
00202 
00203       /* inits the struct */
00204 
00205       for(i = 0; i < FSAL_NB_FUNC; i++)
00206         {
00207           bythread_stat->func_stats.nb_call[i] = 0;
00208           bythread_stat->func_stats.nb_success[i] = 0;
00209           bythread_stat->func_stats.nb_err_retryable[i] = 0;
00210           bythread_stat->func_stats.nb_err_unrecover[i] = 0;
00211         }
00212 
00213       /* set the specific value */
00214       pthread_setspecific(key_stats, (void *)bythread_stat);
00215 
00216     }
00217 
00218   /* we increment the values */
00219 
00220   if(bythread_stat)
00221     {
00222       bythread_stat->func_stats.nb_call[function_index]++;
00223 
00224       if(!FSAL_IS_ERROR(status))
00225         bythread_stat->func_stats.nb_success[function_index]++;
00226       else if(fsal_is_retryable(status))
00227         bythread_stat->func_stats.nb_err_retryable[function_index]++;
00228       else
00229         bythread_stat->func_stats.nb_err_unrecover[function_index]++;
00230     }
00231 
00232   return;
00233 }
00234 
00245 void fsal_internal_getstats(fsal_statistics_t * output_stats)
00246 {
00247 
00248   fsal_statistics_t *bythread_stat = NULL;
00249 
00250   /* first, we init the keys if this is the first time */
00251   if(pthread_once(&once_key, init_keys) != 0)
00252     {
00253       LogMajor(COMPONENT_FSAL,
00254                "Could not create thread specific stats (pthread_once) err %d (%s)",
00255                errno, strerror(errno));
00256       return;
00257     }
00258 
00259   /* we get the specific value */
00260   bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats);
00261 
00262   /* we allocate stats if this is the first time */
00263   if(bythread_stat == NULL)
00264     {
00265       int i;
00266 
00267       if((bythread_stat =
00268           gsh_malloc(sizeof(fsal_statistics_t))) == NULL)
00269       {
00270         /* we don't have working memory, bail */
00271         LogCrit(COMPONENT_FSAL,
00272                 "Could not allocate memory for FSAL statistics");
00273         return;
00274       }
00275 
00276       /* inits the struct */
00277       for(i = 0; i < FSAL_NB_FUNC; i++)
00278         {
00279           bythread_stat->func_stats.nb_call[i] = 0;
00280           bythread_stat->func_stats.nb_success[i] = 0;
00281           bythread_stat->func_stats.nb_err_retryable[i] = 0;
00282           bythread_stat->func_stats.nb_err_unrecover[i] = 0;
00283         }
00284 
00285       /* set the specific value */
00286       pthread_setspecific(key_stats, (void *)bythread_stat);
00287 
00288     }
00289 
00290   if(output_stats)
00291     (*output_stats) = (*bythread_stat);
00292 
00293   return;
00294 
00295 }
00296 
00307 void fsal_internal_SetCredentialLifetime(fsal_uint_t lifetime_in)
00308 {
00309   CredentialLifetime = lifetime_in;
00310 }
00311 
00315 void TakeTokenFSCall()
00316 {
00317   /* no limits */
00318   if(limit_calls == FALSE)
00319     return;
00320 
00321   /* there is a limit */
00322   semaphore_P(&sem_fs_calls);
00323 
00324 }
00325 
00326 void ReleaseTokenFSCall()
00327 {
00328   /* no limits */
00329   if(limit_calls == FALSE)
00330     return;
00331 
00332   /* there is a limit */
00333   semaphore_V(&sem_fs_calls);
00334 
00335 }
00336 
00337 /*
00338  *  This function initializes shared variables of the fsal.
00339  */
00340 fsal_status_t fsal_internal_init_global(fsal_init_info_t * fsal_info,
00341                                         fs_common_initinfo_t * fs_common_info,
00342                                         fs_specific_initinfo_t * fs_specific_info)
00343 {
00344 
00345   /* sanity check */
00346   if(!fsal_info || !fs_common_info || !fs_specific_info)
00347     ReturnCode(ERR_FSAL_FAULT, 0);
00348 
00349   /* inits FS call semaphore */
00350   if(fsal_info->max_fs_calls > 0)
00351     {
00352       int rc;
00353 
00354       limit_calls = TRUE;
00355 
00356       rc = semaphore_init(&sem_fs_calls, fsal_info->max_fs_calls);
00357 
00358       if(rc != 0)
00359         ReturnCode(ERR_FSAL_SERVERFAULT, rc);
00360 
00361       LogDebug(COMPONENT_FSAL,
00362                "FSAL INIT: Max simultaneous calls to filesystem is limited to %u.",
00363                fsal_info->max_fs_calls);
00364     }
00365   else
00366     {
00367       LogDebug(COMPONENT_FSAL,
00368                "FSAL INIT: Max simultaneous calls to filesystem is unlimited.");
00369     }
00370 
00371   /* setting default values. */
00372   global_fs_info = default_gpfs_info;
00373 
00374   if(isFullDebug(COMPONENT_FSAL))
00375     {
00376       display_fsinfo(&default_gpfs_info);
00377     }
00378 
00379   /* Analyzing fs_common_info struct */
00380 
00381   if((fs_common_info->behaviors.maxfilesize != FSAL_INIT_FS_DEFAULT) ||
00382      (fs_common_info->behaviors.maxlink != FSAL_INIT_FS_DEFAULT) ||
00383      (fs_common_info->behaviors.maxnamelen != FSAL_INIT_FS_DEFAULT) ||
00384      (fs_common_info->behaviors.maxpathlen != FSAL_INIT_FS_DEFAULT) ||
00385      (fs_common_info->behaviors.no_trunc != FSAL_INIT_FS_DEFAULT) ||
00386      (fs_common_info->behaviors.case_insensitive != FSAL_INIT_FS_DEFAULT) ||
00387      (fs_common_info->behaviors.case_preserving != FSAL_INIT_FS_DEFAULT) ||
00388      (fs_common_info->behaviors.named_attr != FSAL_INIT_FS_DEFAULT) ||
00389      (fs_common_info->behaviors.lease_time != FSAL_INIT_FS_DEFAULT) ||
00390      (fs_common_info->behaviors.supported_attrs != FSAL_INIT_FS_DEFAULT) ||
00391      (fs_common_info->behaviors.homogenous != FSAL_INIT_FS_DEFAULT))
00392     ReturnCode(ERR_FSAL_NOTSUPP, 0);
00393 
00394   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, symlink_support);
00395   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, link_support);
00396   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support);
00397   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_owner);
00398   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_async_block);
00399   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, cansettime);
00400 
00401   SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxread);
00402   SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxwrite);
00403 
00404   SET_BITMAP_PARAM(global_fs_info, fs_common_info, umask);
00405 
00406   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, auth_exportpath_xdev);
00407 
00408   SET_BITMAP_PARAM(global_fs_info, fs_common_info, xattr_access_rights);
00409 
00410   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, accesscheck_support);
00411   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, share_support);
00412   SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, share_support_owner);
00413 
00414   LogFullDebug(COMPONENT_FSAL,
00415                "Supported attributes constant = 0x%llX.",
00416                GPFS_SUPPORTED_ATTRIBUTES);
00417 
00418   LogFullDebug(COMPONENT_FSAL,
00419                "Supported attributes default = 0x%llX.",
00420                default_gpfs_info.supported_attrs);
00421 
00422   LogFullDebug(COMPONENT_FSAL,
00423                "FSAL INIT: Supported attributes mask = 0x%llX.",
00424                global_fs_info.supported_attrs);
00425 
00426   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00427 }
00428 
00429 /*********************************************************************
00430  *
00431  *  GPFS FSAL char device driver interaces
00432  *
00433  ********************************************************************/
00434 
00451 fsal_status_t fsal_internal_handle2fd(fsal_op_context_t * p_context,
00452                                       fsal_handle_t * phandle, int *pfd, int oflags)
00453 {
00454   int dirfd = 0;
00455   fsal_status_t status;
00456 
00457   if(!phandle || !pfd || !p_context || !p_context->export_context)
00458     ReturnCode(ERR_FSAL_FAULT, 0);
00459 
00460   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00461 
00462   status = fsal_internal_handle2fd_at(dirfd, phandle, pfd, oflags);
00463 
00464   if(FSAL_IS_ERROR(status))
00465     ReturnStatus(status, INDEX_FSAL_open);
00466 
00467   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00468 }
00469 
00486 fsal_status_t fsal_internal_handle2fd_at(int dirfd,
00487                                          fsal_handle_t * phandle, int *pfd, int oflags)
00488 {
00489   int rc = 0;
00490   struct open_arg oarg;
00491 
00492   if(!phandle || !pfd)
00493     ReturnCode(ERR_FSAL_FAULT, 0);
00494 
00495   oarg.mountdirfd = dirfd;
00496   oarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)phandle)->data.handle;
00497   oarg.flags = oflags;
00498 
00499   rc = gpfs_ganesha(OPENHANDLE_OPEN_BY_HANDLE, &oarg);
00500 
00501   LogFullDebug(COMPONENT_FSAL, "OPENHANDLE_OPEN_BY_HANDLE returned: rc %d", rc);
00502 
00503   if(rc < 0)
00504     ReturnCode(posix2fsal_error(errno), errno);
00505 
00506   *pfd = rc;
00507 
00508   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00509 }
00510 
00524 fsal_status_t fsal_internal_get_handle(fsal_op_context_t * p_context,   /* IN */
00525                                        fsal_path_t * p_fsalpath,        /* IN */
00526                                        fsal_handle_t * p_handle /* OUT */ )
00527 {
00528   int rc;
00529   gpfsfsal_handle_t *p_gpfs_handle = (gpfsfsal_handle_t *)p_handle;
00530   struct name_handle_arg harg;
00531 
00532   if(!p_context || !p_handle || !p_fsalpath)
00533     ReturnCode(ERR_FSAL_FAULT, 0);
00534 
00535   harg.handle = (struct gpfs_file_handle *) &p_gpfs_handle->data.handle;
00536   harg.handle->handle_size = OPENHANDLE_HANDLE_LEN;
00537   harg.handle->handle_key_size = OPENHANDLE_KEY_LEN;
00538   harg.handle->handle_version = OPENHANDLE_VERSION;
00539   harg.name = p_fsalpath->path;
00540   harg.dfd = AT_FDCWD;
00541   harg.flag = 0;
00542 
00543   LogFullDebug(COMPONENT_FSAL,
00544                "Lookup handle for %s",
00545                p_fsalpath->path);
00546 
00547   rc = gpfs_ganesha(OPENHANDLE_NAME_TO_HANDLE, &harg);
00548 
00549   if(rc < 0)
00550     ReturnCode(posix2fsal_error(errno), errno);
00551 
00552   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00553 }
00554 
00569 fsal_status_t fsal_internal_get_handle_at(int dfd,      /* IN */
00570                                           fsal_name_t * p_fsalname,     /* IN */
00571                                           fsal_handle_t * p_handle      /* OUT
00572                                                                          */ )
00573 {
00574   int rc;
00575   gpfsfsal_handle_t *p_gpfs_handle = (gpfsfsal_handle_t *)p_handle;
00576   struct name_handle_arg harg;
00577 
00578   if(!p_handle || !p_fsalname)
00579     ReturnCode(ERR_FSAL_FAULT, 0);
00580 
00581   harg.handle = (struct gpfs_file_handle *) &p_gpfs_handle->data.handle;
00582   harg.handle->handle_size = OPENHANDLE_HANDLE_LEN;
00583   harg.handle->handle_version = OPENHANDLE_VERSION;
00584   harg.handle->handle_key_size = OPENHANDLE_KEY_LEN;
00585   harg.name = p_fsalname->name;
00586   harg.dfd = dfd;
00587   harg.flag = 0;
00588 
00589   LogFullDebug(COMPONENT_FSAL,
00590                "Lookup handle at for %s",
00591                p_fsalname->name);
00592 
00593   rc = gpfs_ganesha(OPENHANDLE_NAME_TO_HANDLE, &harg);
00594 
00595   if(rc < 0)
00596     ReturnCode(posix2fsal_error(errno), errno);
00597 
00598   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00599 }
00600 
00616  fsal_status_t fsal_internal_get_fh(fsal_op_context_t * p_context, /* IN  */
00617                                     fsal_handle_t * p_dir_fh,      /* IN  */
00618                                     fsal_name_t * p_fsalname,      /* IN  */
00619                                     fsal_handle_t * p_out_fh)      /* OUT */
00620 {
00621   int dirfd, rc;
00622   struct get_handle_arg harg;
00623   gpfsfsal_handle_t *p_gpfs_dir_fh = (gpfsfsal_handle_t *)p_dir_fh;
00624   gpfsfsal_handle_t *p_gpfs_out_fh = (gpfsfsal_handle_t *)p_out_fh;
00625 
00626   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00627 
00628   if(!p_out_fh || !p_dir_fh || !p_fsalname)
00629     ReturnCode(ERR_FSAL_FAULT, 0);
00630 
00631   harg.mountdirfd = dirfd;
00632   harg.dir_fh = (struct gpfs_file_handle *) &p_gpfs_dir_fh->data.handle;
00633   harg.out_fh = (struct gpfs_file_handle *) &p_gpfs_out_fh->data.handle;
00634   harg.out_fh->handle_size = OPENHANDLE_HANDLE_LEN;
00635   harg.out_fh->handle_version = OPENHANDLE_VERSION;
00636   harg.out_fh->handle_key_size = OPENHANDLE_KEY_LEN;
00637   harg.len = p_fsalname->len;
00638   harg.name = p_fsalname->name;
00639 
00640   LogFullDebug(COMPONENT_FSAL,
00641                "Lookup handle for %s",
00642                p_fsalname->name);
00643 
00644   rc = gpfs_ganesha(OPENHANDLE_GET_HANDLE, &harg);
00645 
00646   if(rc < 0)
00647     ReturnCode(posix2fsal_error(errno), errno);
00648 
00649   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00650 }
00651 
00663 fsal_status_t fsal_internal_fd2handle(int fd, fsal_handle_t * handle)
00664 {
00665   int rc;
00666   struct name_handle_arg harg;
00667   gpfsfsal_handle_t * p_handle = (gpfsfsal_handle_t *)handle;
00668 
00669   if(!p_handle || !&p_handle->data.handle)
00670     ReturnCode(ERR_FSAL_FAULT, 0);
00671 
00672   harg.handle = (struct gpfs_file_handle *) &p_handle->data.handle;
00673   harg.handle->handle_size = OPENHANDLE_HANDLE_LEN;
00674   harg.handle->handle_key_size = OPENHANDLE_KEY_LEN;
00675   harg.handle->handle_version = OPENHANDLE_VERSION;
00676   harg.name = NULL;
00677   harg.dfd = fd;
00678   harg.flag = 0;
00679 
00680   LogFullDebug(COMPONENT_FSAL,
00681                "Lookup handle by fd for %d",
00682                fd);
00683 
00684   rc = gpfs_ganesha(OPENHANDLE_NAME_TO_HANDLE, &harg);
00685 
00686   if(rc < 0)
00687     ReturnCode(posix2fsal_error(errno), errno);
00688 
00689   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00690 }
00691 
00705 fsal_status_t fsal_internal_link_at(int srcfd, int dirfd, char *name)
00706 {
00707   int rc;
00708   struct link_arg linkarg;
00709 
00710   if(!name)
00711     ReturnCode(ERR_FSAL_FAULT, 0);
00712 
00713   linkarg.dir_fd = dirfd;
00714   linkarg.file_fd = srcfd;
00715   linkarg.name = name;
00716 
00717   rc = gpfs_ganesha(OPENHANDLE_LINK_BY_FD, &linkarg);
00718 
00719   if(rc < 0)
00720     ReturnCode(posix2fsal_error(errno), errno);
00721 
00722   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00723 
00724 }
00725 
00741 fsal_status_t fsal_internal_link_fh(fsal_op_context_t * p_context,
00742                                     fsal_handle_t * p_target_handle,
00743                                     fsal_handle_t * p_dir_handle,
00744                                     fsal_name_t * p_link_name)
00745 {
00746   int rc;
00747   int dirfd = 0;
00748   struct link_fh_arg linkarg;
00749 
00750   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00751 
00752   if(!p_link_name->name)
00753     ReturnCode(ERR_FSAL_FAULT, 0);
00754 
00755   linkarg.mountdirfd = dirfd;
00756   linkarg.len = p_link_name->len;
00757   linkarg.name = p_link_name->name;
00758   linkarg.dir_fh = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_dir_handle)->data.handle;
00759   linkarg.dst_fh = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_target_handle)->data.handle;
00760 
00761   rc = gpfs_ganesha(OPENHANDLE_LINK_BY_FH, &linkarg);
00762 
00763   if(rc < 0)
00764     ReturnCode(posix2fsal_error(errno), errno);
00765 
00766   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00767 
00768 }
00769 
00783 fsal_status_t fsal_internal_stat_name(fsal_op_context_t * p_context,
00784                                     fsal_handle_t * p_dir_handle,
00785                                     fsal_name_t * p_stat_name,
00786                                     struct stat *buf)
00787 {
00788   int rc;
00789   int dirfd = 0;
00790   struct stat_name_arg statarg;
00791 
00792   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00793 
00794   if(!p_stat_name->name)
00795     ReturnCode(ERR_FSAL_FAULT, 0);
00796 
00797   statarg.mountdirfd = dirfd;
00798   statarg.len = p_stat_name->len;
00799   statarg.name = p_stat_name->name;
00800   statarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_dir_handle)->data.handle;
00801   statarg.buf = buf;
00802 
00803   rc = gpfs_ganesha(OPENHANDLE_STAT_BY_NAME, &statarg);
00804 
00805   if(rc < 0)
00806     ReturnCode(posix2fsal_error(errno), errno);
00807 
00808   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00809 
00810 }
00811 
00825 fsal_status_t fsal_internal_unlink(fsal_op_context_t * p_context,
00826                                    fsal_handle_t * p_dir_handle,
00827                                    fsal_name_t * p_stat_name,
00828                                    struct stat *buf)
00829 {
00830   int rc;
00831   int dirfd = 0;
00832   struct stat_name_arg statarg;
00833 
00834   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00835 
00836   if(!p_stat_name->name)
00837     ReturnCode(ERR_FSAL_FAULT, 0);
00838 
00839   statarg.mountdirfd = dirfd;
00840   statarg.len = p_stat_name->len;
00841   statarg.name = p_stat_name->name;
00842   statarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_dir_handle)->data.handle;
00843   statarg.buf = buf;
00844 
00845   rc = gpfs_ganesha(OPENHANDLE_UNLINK_BY_NAME, &statarg);
00846 
00847   if(rc < 0)
00848     ReturnCode(posix2fsal_error(errno), errno);
00849 
00850   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00851 
00852 }
00853 
00871 fsal_status_t fsal_internal_create(fsal_op_context_t * p_context,
00872                                    fsal_handle_t * p_dir_handle,
00873                                    fsal_name_t * p_stat_name,
00874                                    mode_t mode, dev_t dev,
00875                                    fsal_handle_t * p_new_handle,
00876                                    struct stat *buf)
00877 {
00878   int rc;
00879   int dirfd = 0;
00880   struct create_name_arg crarg;
00881 
00882   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00883 
00884   if(!p_stat_name->name)
00885     ReturnCode(ERR_FSAL_FAULT, 0);
00886 
00887   crarg.mountdirfd = dirfd;
00888   crarg.mode = mode;
00889   crarg.dev = dev;
00890   crarg.len = p_stat_name->len;
00891   crarg.name = p_stat_name->name;
00892   crarg.dir_fh = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_dir_handle)->data.handle;
00893   crarg.new_fh = (struct gpfs_file_handle *) &p_new_handle->data.handle;
00894   crarg.new_fh->handle_size = OPENHANDLE_HANDLE_LEN;
00895   crarg.new_fh->handle_key_size = OPENHANDLE_KEY_LEN;
00896   crarg.new_fh->handle_version = OPENHANDLE_VERSION;
00897   crarg.buf = buf;
00898 
00899   rc = gpfs_ganesha(OPENHANDLE_CREATE_BY_NAME, &crarg);
00900 
00901   if(rc < 0)
00902     ReturnCode(posix2fsal_error(errno), errno);
00903 
00904   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00905 }
00906 
00924 fsal_status_t fsal_internal_rename_fh(fsal_op_context_t * p_context,
00925                                     fsal_handle_t * p_old_handle,
00926                                     fsal_handle_t * p_new_handle,
00927                                     fsal_name_t * p_old_name,
00928                                     fsal_name_t * p_new_name)
00929 {
00930   int rc;
00931   int dirfd = 0;
00932   struct rename_fh_arg renamearg;
00933 
00934   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00935 
00936   if(!p_old_name->name)
00937     ReturnCode(ERR_FSAL_FAULT, 0);
00938 
00939   if(!p_new_name->name)
00940     ReturnCode(ERR_FSAL_FAULT, 0);
00941 
00942   renamearg.mountdirfd = dirfd;
00943   renamearg.old_len = p_old_name->len;
00944   renamearg.old_name = p_old_name->name;
00945   renamearg.new_len = p_new_name->len;
00946   renamearg.new_name = p_new_name->name;
00947   renamearg.old_fh = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_old_handle)->data.handle;
00948   renamearg.new_fh = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_new_handle)->data.handle;
00949 
00950   rc = gpfs_ganesha(OPENHANDLE_RENAME_BY_FH, &renamearg);
00951 
00952   if(rc < 0)
00953     ReturnCode(posix2fsal_error(errno), errno);
00954 
00955   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00956 
00957 }
00958 
00967 fsal_status_t fsal_readlink_by_handle(fsal_op_context_t * p_context,
00968                                       fsal_handle_t * p_handle, char *__buf, int maxlen)
00969 {
00970   int rc;
00971   int dirfd = 0;
00972   struct readlink_fh_arg readlinkarg;
00973   gpfsfsal_handle_t *p_gpfs_fh = (gpfsfsal_handle_t *)p_handle;
00974 
00975   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
00976 
00977   readlinkarg.mountdirfd = dirfd;
00978   readlinkarg.handle = (struct gpfs_file_handle *) &p_gpfs_fh->data.handle;
00979   readlinkarg.buffer = __buf;
00980   readlinkarg.size = maxlen;
00981 
00982   rc = gpfs_ganesha(OPENHANDLE_READLINK_BY_FH, &readlinkarg);
00983 
00984   if(rc < 0)
00985       Return(rc, 0, INDEX_FSAL_readlink);
00986 
00987   if(rc < maxlen)
00988     __buf[rc] = '\0';
00989 
00990   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00991 }
00992 
00993 /* Check the access by using NFS4 ACL if it exists. Otherwise, use mode. */
00994 fsal_status_t fsal_internal_testAccess(fsal_op_context_t * p_context,   /* IN */
00995                                        fsal_accessflags_t access_type,  /* IN */
00996                                        struct stat *p_buffstat, /* IN */
00997                                        fsal_attrib_list_t * p_object_attributes /* IN */ )
00998 {
00999   /* sanity checks. */
01000   if((!p_object_attributes && !p_buffstat) || !p_context)
01001     ReturnCode(ERR_FSAL_FAULT, 0);
01002 
01003   /* The root user ignores the mode/uid/gid of the file */
01004   if(p_context->credential.user == 0)
01005     ReturnCode(ERR_FSAL_NO_ERROR, 0);
01006 
01007 #ifdef _USE_NFS4_ACL
01008   /* If ACL exists and given access type is ace4 mask, use ACL to check access. */
01009   LogDebug(COMPONENT_FSAL, "pattr=%p, pacl=%p, is_ace4_mask=%d",
01010            p_object_attributes, p_object_attributes ? p_object_attributes->acl : 0,
01011            IS_FSAL_ACE4_MASK_VALID(access_type));
01012 
01013   if(p_object_attributes && p_object_attributes->acl &&
01014      IS_FSAL_ACE4_MASK_VALID(access_type))
01015     {
01016       return fsal_internal_testAccess_acl(p_context, FSAL_ACE4_MASK(access_type),
01017                                           p_object_attributes);
01018     }
01019 #endif
01020 
01021   /* Use mode to check access. */
01022   return fsal_internal_testAccess_no_acl(p_context, FSAL_MODE_MASK(access_type),
01023                                            p_buffstat, p_object_attributes);
01024 
01025   LogDebug(COMPONENT_FSAL, "invalid access_type = 0X%x",
01026            access_type);
01027 
01028   ReturnCode(ERR_FSAL_ACCESS, 0);
01029 }
01030 
01031 /* Check the access at the file system. It is called when Use_Test_Access = 0. */
01032 fsal_status_t fsal_internal_access(fsal_op_context_t * p_context,   /* IN */
01033                                    fsal_handle_t * p_handle,   /* IN */
01034                                    fsal_accessflags_t access_type,  /* IN */
01035                                    fsal_attrib_list_t * p_object_attributes /* IN */ )
01036 {
01037   fsal_status_t status;
01038   fsal_accessflags_t v4mask = 0;
01039   fsal_accessmode_t mode = 0;
01040 
01041   /* sanity checks. */
01042   if(!p_context || !p_handle)
01043     ReturnCode(ERR_FSAL_FAULT, 0);
01044 
01045   if(IS_FSAL_ACE4_MASK_VALID(access_type))
01046     v4mask = FSAL_ACE4_MASK(access_type);
01047 
01048   if(IS_FSAL_MODE_MASK_VALID(access_type))
01049     mode = FSAL_MODE_MASK(access_type);
01050 
01051   LogDebug(COMPONENT_FSAL, "requested v4mask=0x%x, mode=0x%x", v4mask, mode);
01052 
01053 #ifdef _USE_NFS4_ACL
01054   status = fsal_check_access_by_handle(p_context, p_handle, mode, v4mask,
01055                                        p_object_attributes);
01056 
01057   if(isFullDebug(COMPONENT_FSAL))
01058   {
01059     fsal_status_t status2;
01060         status2 = fsal_internal_testAccess(p_context, access_type, NULL,
01061                                            p_object_attributes);
01062         if(status2.major != status.major)
01063         {
01064           LogFullDebug(COMPONENT_FSAL,
01065                        "access error: access result major %d, test_access result major %d",
01066                    status.major, status2.major);
01067         }
01068         else
01069           LogFullDebug(COMPONENT_FSAL,
01070                        "access ok: access and test_access produced the same result");
01071   }
01072 #else
01073   status = fsal_internal_testAccess(p_context, access_type, NULL,
01074                                     p_object_attributes);
01075 #endif
01076 
01077   return status;
01078 }
01079 
01088 fsal_status_t fsal_stat_by_handle(fsal_op_context_t * p_context,
01089                                   fsal_handle_t * p_handle, struct stat *buf)
01090 {
01091   int rc;
01092   int dirfd = 0;
01093   struct stat_arg statarg;
01094 
01095   if(!p_handle || !p_context || !p_context->export_context)
01096       ReturnCode(ERR_FSAL_FAULT, 0);
01097 
01098   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
01099 
01100   statarg.mountdirfd = dirfd;
01101 
01102   statarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_handle)->data.handle;
01103   statarg.buf = buf;
01104 
01105   rc = gpfs_ganesha(OPENHANDLE_STAT_BY_HANDLE, &statarg);
01106 
01107   if(rc < 0)
01108     ReturnCode(posix2fsal_error(errno), errno);
01109 
01110   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01111 }
01112 
01113 /* Get NFS4 ACL as well as stat. For now, get stat only until NFS4 ACL
01114  * support is enabled. */
01115 fsal_status_t fsal_get_xstat_by_handle(fsal_op_context_t * p_context,
01116                                        fsal_handle_t * p_handle, gpfsfsal_xstat_t *p_buffxstat)
01117 {
01118   int rc;
01119   int dirfd = 0;
01120   struct xstat_arg xstatarg;
01121 #ifdef _USE_NFS4_ACL
01122   gpfs_acl_t *pacl_gpfs;
01123 #endif                          /* _USE_NFS4_ACL */
01124 
01125   if(!p_handle || !p_context || !p_context->export_context || !p_buffxstat)
01126       ReturnCode(ERR_FSAL_FAULT, 0);
01127 
01128   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
01129 
01130 #ifdef _USE_NFS4_ACL
01131   /* Initialize acl header so that GPFS knows what we want. */
01132   pacl_gpfs = (gpfs_acl_t *) p_buffxstat->buffacl;
01133   pacl_gpfs->acl_level = 0;
01134   pacl_gpfs->acl_version = GPFS_ACL_VERSION_NFS4;
01135   pacl_gpfs->acl_type = GPFS_ACL_TYPE_NFS4;
01136   pacl_gpfs->acl_len = GPFS_ACL_BUF_SIZE;
01137 #endif                          /* _USE_NFS4_ACL */
01138 
01139 #ifdef _USE_NFS4_ACL
01140   xstatarg.attr_valid = XATTR_STAT | XATTR_ACL;
01141 #else
01142 xstatarg.attr_valid = XATTR_STAT;
01143 #endif
01144   xstatarg.mountdirfd = dirfd;
01145   xstatarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_handle)->data.handle;
01146 #ifdef _USE_NFS4_ACL
01147   xstatarg.acl = pacl_gpfs;
01148 #else
01149   xstatarg.acl = NULL;
01150 #endif
01151   xstatarg.attr_changed = 0;
01152   xstatarg.buf = &p_buffxstat->buffstat;
01153 
01154   rc = gpfs_ganesha(OPENHANDLE_GET_XSTAT, &xstatarg);
01155   LogDebug(COMPONENT_FSAL, "gpfs_ganesha: GET_XSTAT returned, rc = %d", rc);
01156 
01157   if(rc < 0)
01158     {
01159       if(errno == ENODATA)
01160         {
01161           /* For the special file that do not have ACL, GPFS returns ENODATA.
01162            * In this case, return okay with stat. */
01163           p_buffxstat->attr_valid = XATTR_STAT;
01164           LogFullDebug(COMPONENT_FSAL, "retrieved only stat, not acl");
01165           ReturnCode(ERR_FSAL_NO_ERROR, 0);
01166         }
01167       else
01168         {
01169           /* Handle other errors. */
01170           LogFullDebug(COMPONENT_FSAL, "fsal_get_xstat_by_handle returned errno:%d -- %s",
01171                        errno, strerror(errno));
01172           ReturnCode(posix2fsal_error(errno), errno);
01173         }
01174     }
01175 
01176 #ifdef _USE_NFS4_ACL
01177   p_buffxstat->attr_valid = XATTR_STAT | XATTR_ACL;
01178 #else
01179   p_buffxstat->attr_valid = XATTR_STAT;
01180 #endif
01181 
01182   ReturnCode(ERR_FSAL_NO_ERROR, 0);  
01183 }
01184 
01185 /* Set NFS4 ACL as well as stat. For now, set stat only until NFS4 ACL
01186  * support is enabled. */
01187 fsal_status_t fsal_set_xstat_by_handle(fsal_op_context_t * p_context,
01188                                        fsal_handle_t * p_handle, int attr_valid,
01189                                        int attr_changed, gpfsfsal_xstat_t *p_buffxstat)
01190 {
01191   int rc, errsv;
01192   int dirfd = 0;
01193   struct xstat_arg xstatarg;
01194   int fsuid, fsgid;
01195 
01196   if(!p_handle || !p_context || !p_context->export_context || !p_buffxstat)
01197       ReturnCode(ERR_FSAL_FAULT, 0);
01198 
01199   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
01200 
01201   xstatarg.attr_valid = attr_valid;
01202   xstatarg.mountdirfd = dirfd;
01203   xstatarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_handle)->data.handle;
01204   xstatarg.acl = (gpfs_acl_t *) p_buffxstat->buffacl;
01205   xstatarg.attr_changed = attr_changed;
01206   xstatarg.buf = &p_buffxstat->buffstat;
01207 
01208   fsuid = setfsuid(p_context->credential.user);
01209   fsgid = setfsgid(p_context->credential.group);
01210   rc = gpfs_ganesha(OPENHANDLE_SET_XSTAT, &xstatarg);
01211   errsv = errno;
01212   setfsuid(fsuid);
01213   setfsgid(fsgid);
01214 
01215   LogDebug(COMPONENT_FSAL, "gpfs_ganesha: SET_XSTAT returned, rc = %d", rc);
01216 
01217   if(rc < 0)
01218     ReturnCode(posix2fsal_error(errsv), errsv);
01219 
01220   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01221 }
01222 
01223 /* trucate by handle */
01224 fsal_status_t fsal_trucate_by_handle(fsal_op_context_t * p_context,
01225                                      fsal_handle_t * p_handle,
01226                                      u_int64_t size)
01227 {
01228   int attr_valid;
01229   int attr_changed;
01230   gpfsfsal_xstat_t buffxstat;
01231 
01232   if(!p_handle || !p_context || !p_context->export_context)
01233       ReturnCode(ERR_FSAL_FAULT, 0);
01234 
01235   attr_valid = XATTR_STAT;
01236   attr_changed = XATTR_SIZE;
01237   buffxstat.buffstat.st_size = size;
01238 
01239   return fsal_set_xstat_by_handle(p_context, p_handle, attr_valid,
01240                                  attr_changed, &buffxstat);
01241 }
01242 
01243 /* Access check function that accepts stat64. */
01244 fsal_status_t fsal_check_access_by_mode(fsal_op_context_t * p_context,   /* IN */
01245                                         fsal_accessflags_t access_type,  /* IN */
01246                                         struct stat *p_buffstat /* IN */)
01247 {
01248   struct stat buffstat;
01249 
01250   if(!p_context || !p_buffstat)
01251     ReturnCode(ERR_FSAL_FAULT, 0);
01252 
01253   /* Convert to stat. We only need uid, gid, and mode. */
01254   buffstat.st_uid = p_buffstat->st_uid;
01255   buffstat.st_gid = p_buffstat->st_gid;
01256   buffstat.st_mode = p_buffstat->st_mode;
01257 
01258   return fsal_internal_testAccess(p_context, access_type, &buffstat, NULL);
01259 }
01260 
01261 #ifdef _USE_NFS4_ACL
01262 static fsal_boolean_t fsal_check_ace_owner(fsal_uid_t uid, fsal_op_context_t *p_context)
01263 {
01264   return (p_context->credential.user == uid);
01265 }
01266 
01267 static fsal_boolean_t fsal_check_ace_group(fsal_gid_t gid, fsal_op_context_t *p_context)
01268 {
01269   int i;
01270 
01271   if(p_context->credential.group == gid)
01272     return TRUE;
01273 
01274   for(i = 0; i < p_context->credential.nbgroups; i++)
01275     {
01276       if(p_context->credential.alt_groups[i] == gid)
01277         return TRUE;
01278     }
01279 
01280   return FALSE;
01281 }
01282 
01283 static fsal_boolean_t fsal_check_ace_matches(fsal_ace_t *pace,
01284                                              fsal_op_context_t *p_context,
01285                                              fsal_boolean_t is_owner,
01286                                              fsal_boolean_t is_group)
01287 {
01288   fsal_boolean_t result = FALSE;
01289   char *cause = "";
01290 
01291   if (IS_FSAL_ACE_SPECIAL_ID(*pace))
01292     switch(pace->who.uid)
01293       {
01294         case FSAL_ACE_SPECIAL_OWNER:
01295           if(is_owner)
01296             {
01297               result = TRUE;
01298               cause = "special owner";
01299             }
01300         break;
01301 
01302         case FSAL_ACE_SPECIAL_GROUP:
01303           if(is_group)
01304             {
01305               result = TRUE;
01306               cause = "special group";
01307             }
01308         break;
01309 
01310         case FSAL_ACE_SPECIAL_EVERYONE:
01311           result = TRUE;
01312           cause = "special everyone";
01313         break;
01314 
01315         default:
01316         break;
01317       }
01318   else if (IS_FSAL_ACE_GROUP_ID(*pace))
01319     {
01320       if(fsal_check_ace_group(pace->who.gid, p_context))
01321         {
01322           result = TRUE;
01323           cause = "group";
01324         }
01325     }
01326   else
01327     {
01328       if(fsal_check_ace_owner(pace->who.uid, p_context))
01329         {
01330           result = TRUE;
01331           cause = "owner";
01332         }
01333     }
01334 
01335   LogDebug(COMPONENT_FSAL,
01336            "result: %d, cause: %s, flag: 0x%X, who: %d",
01337            result, cause, pace->flag, GET_FSAL_ACE_WHO(*pace));
01338 
01339   return result;
01340 }
01341 
01342 static fsal_boolean_t fsal_check_ace_applicable(fsal_ace_t *pace,
01343                                                 fsal_op_context_t *p_context,
01344                                                 fsal_boolean_t is_dir,
01345                                                 fsal_boolean_t is_owner,
01346                                                 fsal_boolean_t is_group)
01347 {
01348   fsal_boolean_t is_applicable = FALSE;
01349   fsal_boolean_t is_file = !is_dir;
01350 
01351   /* To be applicable, the entry should not be INHERIT_ONLY. */
01352   if (IS_FSAL_ACE_INHERIT_ONLY(*pace))
01353     {
01354       LogDebug(COMPONENT_FSAL, "Not applicable, "
01355                "inherit only");
01356       return FALSE;
01357     }
01358 
01359   /* Use GPFS internal flag to further check the entry is applicable to this
01360    * object type. */
01361   if(is_file)
01362     {
01363       if(!IS_FSAL_FILE_APPLICABLE(*pace))
01364         {
01365           LogDebug(COMPONENT_FSAL, "Not applicable to file");
01366           return FALSE;
01367         }
01368     }
01369   else  /* directory */
01370     {
01371       if(!IS_FSAL_DIR_APPLICABLE(*pace))
01372         {
01373           LogDebug(COMPONENT_FSAL, "Not applicable to dir");
01374           return FALSE;
01375         }
01376     }
01377 
01378   /* The user should match who value. */
01379   is_applicable = fsal_check_ace_matches(pace, p_context, is_owner, is_group);
01380   if(is_applicable)
01381     LogDebug(COMPONENT_FSAL, "Applicable, flag=0X%x",
01382              pace->flag);
01383   else
01384     LogDebug(COMPONENT_FSAL, "Not applicable to given user");
01385 
01386   return is_applicable;
01387 }
01388 
01389 static void fsal_print_inherit_flags(fsal_ace_t *pace, char *p_buf)
01390 {
01391   if(!pace || !p_buf)
01392     return;
01393 
01394   memset(p_buf, 0, ACL_DEBUG_BUF_SIZE);
01395 
01396   sprintf(p_buf, "Inherit:%s,%s,%s,%s",
01397           IS_FSAL_ACE_FILE_INHERIT(*pace)? "file":"",
01398           IS_FSAL_ACE_DIR_INHERIT(*pace) ? "dir":"",
01399           IS_FSAL_ACE_INHERIT_ONLY(*pace)? "inherit_only":"",
01400           IS_FSAL_ACE_NO_PROPAGATE(*pace)? "no_propagate":"");
01401 }
01402 
01403 static void fsal_print_ace(int ace_number, fsal_ace_t *pace)
01404 {
01405   char inherit_flags[ACL_DEBUG_BUF_SIZE];
01406   char ace_buf[ACL_DEBUG_BUF_SIZE];
01407 
01408   if(!pace)
01409     return;
01410 
01411   memset(inherit_flags, 0, ACL_DEBUG_BUF_SIZE);
01412   memset(ace_buf, 0, ACL_DEBUG_BUF_SIZE);
01413 
01414   /* Get inherit flags if any. */
01415   fsal_print_inherit_flags(pace, inherit_flags);
01416 
01417   /* Print the entire ACE. */
01418   sprintf(ace_buf, "ACE %d %s %s %s %d %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s %s",
01419           ace_number,
01420           /* ACE type. */
01421           IS_FSAL_ACE_ALLOW(*pace)? "allow":
01422           IS_FSAL_ACE_DENY(*pace) ? "deny":
01423           IS_FSAL_ACE_AUDIT(*pace)? "audit": "?",
01424           /* ACE who and its type. */
01425           (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_OWNER(*pace))    ? "owner@":
01426           (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_GROUP(*pace))    ? "group@":
01427           (IS_FSAL_ACE_SPECIAL_ID(*pace) && IS_FSAL_ACE_SPECIAL_EVERYONE(*pace)) ? "everyone@":"",
01428           IS_FSAL_ACE_SPECIAL_ID(*pace)                                          ? "specialid":
01429           IS_FSAL_ACE_GROUP_ID(*pace)                                            ? "gid": "uid",
01430           GET_FSAL_ACE_WHO(*pace),
01431           /* ACE mask. */
01432           IS_FSAL_ACE_READ_DATA(*pace)           ? "read":"",
01433           IS_FSAL_ACE_WRITE_DATA(*pace)          ? "write":"",
01434           IS_FSAL_ACE_EXECUTE(*pace)             ? "execute":"",
01435           IS_FSAL_ACE_ADD_SUBDIRECTORY(*pace)    ? "append":"",
01436           IS_FSAL_ACE_READ_NAMED_ATTR(*pace)     ? "read_named_attr":"",
01437           IS_FSAL_ACE_WRITE_NAMED_ATTR(*pace)    ? "write_named_attr":"",
01438           IS_FSAL_ACE_DELETE_CHILD(*pace)        ? "delete_child":"",
01439           IS_FSAL_ACE_READ_ATTR(*pace)           ? "read_attr":"",
01440           IS_FSAL_ACE_WRITE_ATTR(*pace)          ? "write_attr":"",
01441           IS_FSAL_ACE_DELETE(*pace)              ? "delete":"",
01442           IS_FSAL_ACE_READ_ACL(*pace)            ? "read_acl":"",
01443           IS_FSAL_ACE_WRITE_ACL(*pace)           ? "write_acl":"",
01444           IS_FSAL_ACE_WRITE_OWNER(*pace)         ? "write_owner":"",
01445           IS_FSAL_ACE_SYNCHRONIZE(*pace)         ? "synchronize":"",
01446           /* ACE Inherit flags. */
01447           IS_FSAL_ACE_INHERIT(*pace)? inherit_flags: "");
01448   LogDebug(COMPONENT_FSAL, "%s", ace_buf);
01449 }
01450 
01451 static void fsal_print_v4mask(fsal_aceperm_t v4mask)
01452 {
01453   fsal_ace_t ace;
01454   fsal_ace_t *pace = &ace;
01455   char v4mask_buf[ACL_DEBUG_BUF_SIZE];
01456 
01457   pace->perm = v4mask;
01458   memset(v4mask_buf, 0, ACL_DEBUG_BUF_SIZE);
01459 
01460   sprintf(v4mask_buf, "v4mask %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
01461           IS_FSAL_ACE_READ_DATA(*pace)           ? "read":"",
01462           IS_FSAL_ACE_WRITE_DATA(*pace)          ? "write":"",
01463           IS_FSAL_ACE_EXECUTE(*pace)             ? "execute":"",
01464           IS_FSAL_ACE_ADD_SUBDIRECTORY(*pace)    ? "append":"",
01465           IS_FSAL_ACE_READ_NAMED_ATTR(*pace)     ? "read_named_attr":"",
01466           IS_FSAL_ACE_WRITE_NAMED_ATTR(*pace)    ? "write_named_attr":"",
01467           IS_FSAL_ACE_DELETE_CHILD(*pace)        ? "delete_child":"",
01468           IS_FSAL_ACE_READ_ATTR(*pace)           ? "read_attr":"",
01469           IS_FSAL_ACE_WRITE_ATTR(*pace)          ? "write_attr":"",
01470           IS_FSAL_ACE_DELETE(*pace)              ? "delete":"",
01471           IS_FSAL_ACE_READ_ACL(*pace)            ? "read_acl":"",
01472           IS_FSAL_ACE_WRITE_ACL(*pace)           ? "write_acl":"",
01473           IS_FSAL_ACE_WRITE_OWNER(*pace)         ? "write_owner":"",
01474           IS_FSAL_ACE_SYNCHRONIZE(*pace)         ? "synchronize":"");
01475   LogDebug(COMPONENT_FSAL, "%s", v4mask_buf);
01476 }
01477 
01478 static fsal_status_t fsal_internal_testAccess_acl(fsal_op_context_t * p_context,   /* IN */
01479                                                   fsal_aceperm_t v4mask,  /* IN */
01480                                                   fsal_attrib_list_t * p_object_attributes   /* IN */ )
01481 {
01482   fsal_aceperm_t missing_access;
01483   fsal_uid_t uid;
01484   fsal_gid_t gid;
01485   fsal_acl_t *pacl = NULL;
01486   fsal_ace_t *pace = NULL;
01487   int ace_number = 0;
01488   fsal_boolean_t is_dir = FALSE;
01489   fsal_boolean_t is_owner = FALSE;
01490   fsal_boolean_t is_group = FALSE;
01491 
01492   /* unsatisfied flags */
01493   missing_access = v4mask;
01494   if(!missing_access)
01495     {
01496       LogDebug(COMPONENT_FSAL, "Nothing was requested");
01497       ReturnCode(ERR_FSAL_NO_ERROR, 0);
01498     }
01499 
01500   /* Get file ownership information. */
01501   uid = p_object_attributes->owner;
01502   gid = p_object_attributes->group;
01503   pacl = p_object_attributes->acl;
01504   is_dir = (p_object_attributes->type == FSAL_TYPE_DIR);
01505 
01506   LogDebug(COMPONENT_FSAL,
01507            "file acl=%p, file uid=%d, file gid= %d",
01508            pacl,uid, gid);
01509   LogDebug(COMPONENT_FSAL,
01510            "user uid=%d, user gid= %d, v4mask=0x%X",
01511            p_context->credential.user,
01512            p_context->credential.group,
01513            v4mask);
01514 
01515   if(isFullDebug(COMPONENT_FSAL))
01516     fsal_print_v4mask(v4mask);
01517 
01518   is_owner = fsal_check_ace_owner(uid, p_context);
01519   is_group = fsal_check_ace_group(gid, p_context);
01520 
01521   /* Always grant READ_ACL, WRITE_ACL and READ_ATTR, WRITE_ATTR to the file
01522    * owner. */
01523   if(is_owner)
01524     {
01525       missing_access &= ~(FSAL_ACE_PERM_WRITE_ACL | FSAL_ACE_PERM_READ_ACL);
01526       missing_access &= ~(FSAL_ACE_PERM_WRITE_ATTR | FSAL_ACE_PERM_READ_ATTR);
01527       if(!missing_access)
01528         {
01529           LogDebug(COMPONENT_FSAL, "Met owner privileges");
01530           ReturnCode(ERR_FSAL_NO_ERROR, 0);
01531         }
01532     }
01533 
01534   // TODO: Even if user is admin, audit/alarm checks should be done.
01535 
01536   for(pace = pacl->aces; pace < pacl->aces + pacl->naces; pace++)
01537     {
01538       LogDebug(COMPONENT_FSAL,
01539                "ace type 0x%X perm 0x%X flag 0x%X who %d",
01540                pace->type, pace->perm, pace->flag, GET_FSAL_ACE_WHO(*pace));
01541 
01542       ace_number += 1;
01543 
01544       /* Process Allow and Deny entries. */
01545       if(IS_FSAL_ACE_ALLOW(*pace) || IS_FSAL_ACE_DENY(*pace))
01546         {
01547           LogDebug(COMPONENT_FSAL, "allow or deny");
01548 
01549           /* Check if this ACE is applicable. */
01550           if(fsal_check_ace_applicable(pace, p_context, is_dir, is_owner, is_group))
01551             {
01552               if(IS_FSAL_ACE_ALLOW(*pace))
01553                 {
01554                   LogDebug(COMPONENT_FSAL,
01555                            "allow perm 0x%X remainingPerms 0x%X",
01556                            pace->perm, missing_access);
01557 
01558                   missing_access &= ~(pace->perm & missing_access);
01559                   if(!missing_access)
01560                     {
01561                       LogDebug(COMPONENT_FSAL, "access granted");
01562                       if(isFullDebug(COMPONENT_FSAL))
01563                         {
01564                           if(pacl->naces != ace_number)
01565                             fsal_print_ace(ace_number, pace);
01566                         }
01567                       ReturnCode(ERR_FSAL_NO_ERROR, 0);
01568                     }
01569                 }
01570              else if(pace->perm & missing_access)
01571                {
01572                  LogDebug(COMPONENT_FSAL, "access denied");
01573                  if(isFullDebug(COMPONENT_FSAL))
01574                    {
01575                      if(pacl->naces != ace_number)
01576                        fsal_print_ace(ace_number, pace);
01577                    }
01578                  ReturnCode(ERR_FSAL_ACCESS, 0);
01579                }
01580             }
01581         }
01582     }
01583 
01584   if(missing_access)
01585     {
01586       LogDebug(COMPONENT_FSAL, "access denied");
01587       ReturnCode(ERR_FSAL_ACCESS, 0);
01588     }
01589   else
01590     {
01591       LogDebug(COMPONENT_FSAL, "access granted");
01592       ReturnCode(ERR_FSAL_NO_ERROR, 0);
01593     }
01594 
01595   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01596 }
01597 
01598 static fsal_status_t fsal_check_access_by_handle(fsal_op_context_t * p_context,   /* IN */
01599                                                  fsal_handle_t * p_handle   /* IN */,
01600                                                  fsal_accessmode_t mode,   /* IN */
01601                                                  fsal_accessflags_t v4mask,   /* IN */
01602                                                  fsal_attrib_list_t * p_object_attributes  /* IN */)
01603 
01604 {
01605   int rc;
01606   int dirfd = 0;
01607   struct xstat_cred_t gpfscred;
01608   fsal_status_t status;
01609   struct xstat_access_arg accessarg;
01610   unsigned int supported;
01611   unsigned int gpfs_mode = 0;
01612   fsal_boolean_t is_dir = FALSE;
01613 
01614   if(!p_handle || !p_context || !p_context->export_context)
01615     ReturnCode(ERR_FSAL_FAULT, 0);
01616 
01617   dirfd = ((gpfsfsal_op_context_t *)p_context)->export_context->mount_root_fd;
01618   is_dir = (p_object_attributes->type == FSAL_TYPE_DIR);
01619 
01620   /* Convert fsal credential to gpfs credential. */
01621   status = fsal_cred_2_gpfs_cred(&p_context->credential, &gpfscred);
01622   if(FSAL_IS_ERROR(status))
01623     ReturnCode(ERR_FSAL_FAULT, 0);
01624 
01625   /* Convert fsal mode to gpfs mode. */
01626   status = fsal_mode_2_gpfs_mode(mode, v4mask, &gpfs_mode, is_dir);
01627   if(FSAL_IS_ERROR(status))
01628     ReturnCode(ERR_FSAL_FAULT, 0);
01629 
01630   accessarg.mountdirfd = dirfd;
01631   accessarg.handle = (struct gpfs_file_handle *) &((gpfsfsal_handle_t *)p_handle)->data.handle;
01632   accessarg.acl = NULL;  /* Not used. */
01633   accessarg.cred = (struct xstat_cred_t *) &gpfscred;
01634   accessarg.posix_mode = gpfs_mode;
01635   accessarg.access = v4mask;
01636   accessarg.supported = &supported;
01637 
01638   LogDebug(COMPONENT_FSAL,
01639            "v4mask=0x%X, mode=0x%X, uid=%d, gid=%d",
01640            v4mask, gpfs_mode, gpfscred.principal, gpfscred.group);
01641 
01642   if(isFullDebug(COMPONENT_FSAL))
01643     fsal_print_v4mask(v4mask);
01644 
01645   rc = gpfs_ganesha(OPENHANDLE_CHECK_ACCESS, &accessarg);
01646   LogDebug(COMPONENT_FSAL, "gpfs_ganesha: CHECK_ACCESS returned, rc = %d", rc);
01647 
01648   if(rc < 0)
01649   {
01650     LogDebug(COMPONENT_FSAL, "access denied");
01651     ReturnCode(posix2fsal_error(errno), errno);
01652   }
01653 
01654   LogDebug(COMPONENT_FSAL, "access granted");
01655 
01656   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01657 }
01658 #endif                          /* _USE_NFS4_ACL */
01659 
01660 static fsal_status_t fsal_internal_testAccess_no_acl(fsal_op_context_t * p_context,   /* IN */
01661                                                      fsal_accessflags_t access_type,  /* IN */
01662                                                      struct stat *p_buffstat, /* IN */
01663                                                      fsal_attrib_list_t * p_object_attributes /* IN */ )
01664 {
01665   fsal_accessflags_t missing_access;
01666   unsigned int is_grp, i;
01667   fsal_uid_t uid;
01668   fsal_gid_t gid;
01669   fsal_accessmode_t mode;
01670 
01671   /* If the FSAL_F_OK flag is set, returns ERR INVAL */
01672 
01673   if(access_type & FSAL_F_OK)
01674     ReturnCode(ERR_FSAL_INVAL, 0);
01675 
01676   /* unsatisfied flags */
01677   missing_access = access_type;
01678   if(!missing_access)
01679     {
01680       LogDebug(COMPONENT_FSAL, "Nothing was requested");
01681       ReturnCode(ERR_FSAL_NO_ERROR, 0);
01682     }
01683 
01684   if(p_object_attributes)
01685     {
01686       uid = p_object_attributes->owner;
01687       gid = p_object_attributes->group;
01688       mode = p_object_attributes->mode;
01689 
01690     }
01691   else
01692     {
01693       uid = p_buffstat->st_uid;
01694       gid = p_buffstat->st_gid;
01695       mode = unix2fsal_mode(p_buffstat->st_mode);
01696     }
01697 
01698   LogDebug(COMPONENT_FSAL,
01699                "file Mode=%#o, file uid=%d, file gid= %d",
01700                mode,uid, gid);
01701   LogDebug(COMPONENT_FSAL,
01702                "user uid=%d, user gid= %d, access_type=0X%x",
01703                p_context->credential.user,
01704                p_context->credential.group,
01705                access_type);
01706 
01707   /* If the uid of the file matches the uid of the user,
01708    * then the uid mode bits take precedence. */
01709   if(p_context->credential.user == uid)
01710     {
01711 
01712       LogDebug(COMPONENT_FSAL,
01713                    "File belongs to user %d", uid);
01714 
01715       if(mode & FSAL_MODE_RUSR)
01716         missing_access &= ~FSAL_R_OK;
01717 
01718       if(mode & FSAL_MODE_WUSR)
01719         missing_access &= ~FSAL_W_OK;
01720 
01721       if(mode & FSAL_MODE_XUSR)
01722         missing_access &= ~FSAL_X_OK;
01723 
01724       /* handle the creation of a new 500 file correctly */
01725       if((missing_access & FSAL_OWNER_OK) != 0)
01726         missing_access = 0;
01727 
01728       if(missing_access == 0)
01729         ReturnCode(ERR_FSAL_NO_ERROR, 0);
01730       else
01731         {
01732           LogDebug(COMPONENT_FSAL,
01733                        "Mode=%#o, Access=0X%x, Rights missing: 0X%x",
01734                        mode, access_type, missing_access);
01735           ReturnCode(ERR_FSAL_ACCESS, 0);
01736         }
01737 
01738     }
01739 
01740   /* missing_access will be nonzero triggering a failure
01741    * even though FSAL_OWNER_OK is not even a real posix file
01742    * permission */
01743   missing_access &= ~FSAL_OWNER_OK;
01744 
01745   /* Test if the file belongs to user's group. */
01746   is_grp = (p_context->credential.group == gid);
01747   if(is_grp)
01748     LogDebug(COMPONENT_FSAL,
01749                  "File belongs to user's group %d",
01750                  p_context->credential.group);
01751 
01752   /* Test if file belongs to alt user's groups */
01753   if(!is_grp)
01754     for(i = 0; i < p_context->credential.nbgroups; i++)
01755       {
01756         is_grp = (p_context->credential.alt_groups[i] == gid);
01757         if(is_grp)
01758           LogDebug(COMPONENT_FSAL,
01759                        "File belongs to user's alt group %d",
01760                        p_context->credential.alt_groups[i]);
01761         if(is_grp)
01762           break;
01763       }
01764 
01765   /* If the gid of the file matches the gid of the user or
01766    * one of the alternatve gids of the user, then the uid mode
01767    * bits take precedence. */
01768   if(is_grp)
01769     {
01770       if(mode & FSAL_MODE_RGRP)
01771         missing_access &= ~FSAL_R_OK;
01772 
01773       if(mode & FSAL_MODE_WGRP)
01774         missing_access &= ~FSAL_W_OK;
01775 
01776       if(mode & FSAL_MODE_XGRP)
01777         missing_access &= ~FSAL_X_OK;
01778 
01779       if(missing_access == 0)
01780         ReturnCode(ERR_FSAL_NO_ERROR, 0);
01781       else
01782         ReturnCode(ERR_FSAL_ACCESS, 0);
01783 
01784     }
01785 
01786   /* If the user uid is not 0, the uid does not match the file's, and
01787    * the user's gids do not match the file's gid, we apply the "other"
01788    * mode bits to the user. */
01789   if(mode & FSAL_MODE_ROTH)
01790     missing_access &= ~FSAL_R_OK;
01791 
01792   if(mode & FSAL_MODE_WOTH)
01793     missing_access &= ~FSAL_W_OK;
01794 
01795   if(mode & FSAL_MODE_XOTH)
01796     missing_access &= ~FSAL_X_OK;
01797 
01798   if(missing_access == 0)
01799     ReturnCode(ERR_FSAL_NO_ERROR, 0);
01800   else {
01801     LogDebug(COMPONENT_FSAL,
01802                  "Mode=%#o, Access=0X%x, Rights missing: 0X%x",
01803                  mode, access_type, missing_access);
01804     ReturnCode(ERR_FSAL_ACCESS, 0);
01805   }
01806 
01807 }