nfs-ganesha 1.4
|
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 }