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