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