nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include "fsal.h" 00019 #include "fsal_internal.h" 00020 #include "fsal_convert.h" 00021 #include "fsal_common.h" 00022 #include "namespace.h" 00023 00024 #include <string.h> 00025 00062 fsal_status_t FUSEFSAL_create(fsal_handle_t * parent_handle, /* IN */ 00063 fsal_name_t * p_filename, /* IN */ 00064 fsal_op_context_t * p_context, /* IN */ 00065 fsal_accessmode_t accessmode, /* IN */ 00066 fsal_handle_t * obj_handle, /* OUT */ 00067 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ 00068 ) 00069 { 00070 00071 int rc; 00072 char parent_path[FSAL_MAX_PATH_LEN]; 00073 char child_path[FSAL_MAX_PATH_LEN]; 00074 struct stat buffstat; 00075 mode_t mode; 00076 struct fuse_file_info dummy; 00077 fusefsal_handle_t * parent_directory_handle = (fusefsal_handle_t *)parent_handle; 00078 fusefsal_handle_t * object_handle = (fusefsal_handle_t *)obj_handle; 00079 00080 /* sanity checks. 00081 * note : object_attributes is optional. 00082 */ 00083 if(!parent_directory_handle || !p_context || !object_handle || !p_filename) 00084 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); 00085 00086 /* convert arguments */ 00087 mode = fsal2unix_mode(accessmode); 00088 00089 /* Apply umask */ 00090 mode = mode & ~global_fs_info.umask; 00091 00092 /* get the full path for parent inode */ 00093 rc = NamespacePath(parent_directory_handle->data.inode, 00094 parent_directory_handle->data.device, 00095 parent_directory_handle->data.validator, parent_path); 00096 if(rc) 00097 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_create); 00098 00099 /* append child name to parent path */ 00100 FSAL_internal_append_path(child_path, parent_path, p_filename->name); 00101 00102 /* set context for the next operation, so it can be retrieved by FS thread */ 00103 fsal_set_thread_context(p_context); 00104 00105 /* Call create + close, if implemented. 00106 * else, try with mknod. 00107 */ 00108 if(p_fs_ops->create) 00109 { 00110 /* initialize dummy file info */ 00111 memset(&dummy, 0, sizeof(struct fuse_file_info)); 00112 00113 dummy.flags = O_CREAT | O_EXCL; 00114 00115 LogFullDebug(COMPONENT_FSAL, "Call to create( %s, %#o, %#X )", child_path, mode, dummy.flags); 00116 00117 TakeTokenFSCall(); 00118 rc = p_fs_ops->create(child_path, mode, &dummy); 00119 ReleaseTokenFSCall(); 00120 00121 if(rc) 00122 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_create); 00123 00124 if(p_fs_ops->release) 00125 { 00126 /* don't worry about release return code, 00127 * since the object was created */ 00128 TakeTokenFSCall(); 00129 p_fs_ops->release(child_path, &dummy); 00130 ReleaseTokenFSCall(); 00131 } 00132 00133 } 00134 else if(p_fs_ops->mknod) 00135 { 00136 /* prepare mode including IFREG mask */ 00137 mode |= S_IFREG; 00138 00139 TakeTokenFSCall(); 00140 rc = p_fs_ops->mknod(child_path, mode, 0); 00141 ReleaseTokenFSCall(); 00142 00143 if(rc) 00144 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_create); 00145 00146 } 00147 else 00148 { 00149 /* operation not supported */ 00150 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_create); 00151 } 00152 00153 /* set the owner for the newly created entry */ 00154 00155 if(p_fs_ops->chown) 00156 { 00157 TakeTokenFSCall(); 00158 rc = p_fs_ops->chown(child_path, p_context->credential.user, 00159 p_context->credential.group); 00160 ReleaseTokenFSCall(); 00161 00162 LogFullDebug(COMPONENT_FSAL, "chown: status = %d", rc); 00163 00164 if(rc) 00165 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_create); 00166 } 00167 00168 /* lookup for the newly created entry */ 00169 00170 TakeTokenFSCall(); 00171 rc = p_fs_ops->getattr(child_path, &buffstat); 00172 ReleaseTokenFSCall(); 00173 00174 if(rc) 00175 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_create); 00176 00177 object_handle->data.validator = buffstat.st_ctime; 00178 00179 /* add handle to namespace */ 00180 NamespaceAdd(parent_directory_handle->data.inode, 00181 parent_directory_handle->data.device, 00182 parent_directory_handle->data.validator, 00183 p_filename->name, 00184 buffstat.st_ino, buffstat.st_dev, &object_handle->data.validator); 00185 00186 /* set output handle */ 00187 object_handle->data.inode = buffstat.st_ino; 00188 object_handle->data.device = buffstat.st_dev; 00189 00190 if(object_attributes) 00191 { 00192 fsal_status_t status = posix2fsal_attributes(&buffstat, object_attributes); 00193 00194 if(FSAL_IS_ERROR(status)) 00195 { 00196 FSAL_CLEAR_MASK(object_attributes->asked_attributes); 00197 FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00198 } 00199 } 00200 00201 /* OK */ 00202 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create); 00203 00204 } 00205 00243 fsal_status_t FUSEFSAL_mkdir(fsal_handle_t * parent_handle, /* IN */ 00244 fsal_name_t * p_dirname, /* IN */ 00245 fsal_op_context_t * p_context, /* IN */ 00246 fsal_accessmode_t accessmode, /* IN */ 00247 fsal_handle_t * obj_handle, /* OUT */ 00248 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ 00249 ) 00250 { 00251 00252 int rc; 00253 char parent_path[FSAL_MAX_PATH_LEN]; 00254 char child_path[FSAL_MAX_PATH_LEN]; 00255 struct stat buffstat; 00256 mode_t mode; 00257 fusefsal_handle_t * parent_directory_handle = (fusefsal_handle_t *)parent_handle; 00258 fusefsal_handle_t * object_handle = (fusefsal_handle_t *)obj_handle; 00259 00260 /* sanity checks. 00261 * note : object_attributes is optional. 00262 */ 00263 if(!parent_directory_handle || !p_context || !object_handle || !p_dirname) 00264 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir); 00265 00266 /* Test if mkdir is allowed */ 00267 if(!p_fs_ops->mkdir) 00268 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_mkdir); 00269 00270 /* convert arguments */ 00271 mode = fsal2unix_mode(accessmode); 00272 00273 /* Apply umask */ 00274 mode = mode & ~global_fs_info.umask; 00275 00276 /* get the full path for parent inode */ 00277 rc = NamespacePath(parent_directory_handle->data.inode, 00278 parent_directory_handle->data.device, 00279 parent_directory_handle->data.validator, parent_path); 00280 if(rc) 00281 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_mkdir); 00282 00283 /* append child name to parent path */ 00284 FSAL_internal_append_path(child_path, parent_path, p_dirname->name); 00285 00286 /* set context for the next operation, so it can be retrieved by FS thread */ 00287 fsal_set_thread_context(p_context); 00288 00289 TakeTokenFSCall(); 00290 rc = p_fs_ops->mkdir(child_path, mode); 00291 ReleaseTokenFSCall(); 00292 00293 if(rc) 00294 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_mkdir); 00295 00296 /* set the owner for the newly created entry */ 00297 00298 if(p_fs_ops->chown) 00299 { 00300 TakeTokenFSCall(); 00301 rc = p_fs_ops->chown(child_path, p_context->credential.user, 00302 p_context->credential.group); 00303 ReleaseTokenFSCall(); 00304 00305 LogFullDebug(COMPONENT_FSAL, "chown: status = %d", rc); 00306 00307 if(rc) 00308 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_mkdir); 00309 } 00310 00311 TakeTokenFSCall(); 00312 rc = p_fs_ops->getattr(child_path, &buffstat); 00313 ReleaseTokenFSCall(); 00314 00315 if(rc) 00316 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_mkdir); 00317 00318 object_handle->data.validator = buffstat.st_ctime; 00319 00320 /* add handle to namespace */ 00321 NamespaceAdd(parent_directory_handle->data.inode, 00322 parent_directory_handle->data.device, 00323 parent_directory_handle->data.validator, 00324 p_dirname->name, 00325 buffstat.st_ino, buffstat.st_dev, &object_handle->data.validator); 00326 00327 /* set output handle */ 00328 object_handle->data.inode = buffstat.st_ino; 00329 object_handle->data.device = buffstat.st_dev; 00330 00331 if(object_attributes) 00332 { 00333 fsal_status_t status = posix2fsal_attributes(&buffstat, object_attributes); 00334 00335 if(FSAL_IS_ERROR(status)) 00336 { 00337 FSAL_CLEAR_MASK(object_attributes->asked_attributes); 00338 FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00339 } 00340 } 00341 00342 /* OK */ 00343 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mkdir); 00344 00345 } 00346 00384 fsal_status_t FUSEFSAL_link(fsal_handle_t * target, /* IN */ 00385 fsal_handle_t * dir_hdl, /* IN */ 00386 fsal_name_t * p_link_name, /* IN */ 00387 fsal_op_context_t * p_context, /* IN */ 00388 fsal_attrib_list_t * attributes /* [ IN/OUT ] */ 00389 ) 00390 { 00391 00392 int rc; 00393 char parent_path[FSAL_MAX_PATH_LEN]; 00394 char child_path[FSAL_MAX_PATH_LEN]; 00395 char target_path[FSAL_MAX_PATH_LEN]; 00396 unsigned int new_validator; 00397 fusefsal_handle_t * dir_handle = (fusefsal_handle_t *)dir_hdl; 00398 fusefsal_handle_t * target_handle = (fusefsal_handle_t *)target; 00399 00400 /* sanity checks. 00401 * note : attributes is optional. 00402 */ 00403 if(!target_handle || !dir_handle || !p_context || !p_link_name) 00404 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link); 00405 00406 /* Tests if hardlinking is allowed by configuration. */ 00407 00408 if(!global_fs_info.link_support || !p_fs_ops->link) 00409 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link); 00410 00411 LogFullDebug(COMPONENT_FSAL, "linking %lX.%lu/%s to %lX.%lu", 00412 dir_handle->data.device, dir_handle->data.inode, p_link_name->name, 00413 target_handle->data.device, target_handle->data.inode); 00414 00415 /* get target inode path */ 00416 rc = NamespacePath(target_handle->data.inode, 00417 target_handle->data.device, target_handle->data.validator, target_path); 00418 if(rc) 00419 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_link); 00420 00421 /* get new directory path */ 00422 rc = NamespacePath(dir_handle->data.inode, 00423 dir_handle->data.device, dir_handle->data.validator, parent_path); 00424 if(rc) 00425 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_link); 00426 00427 /* append child name to parent path */ 00428 FSAL_internal_append_path(child_path, parent_path, p_link_name->name); 00429 00430 /* set context for the next operation, so it can be retrieved by FS thread */ 00431 fsal_set_thread_context(p_context); 00432 00433 TakeTokenFSCall(); 00434 rc = p_fs_ops->link(target_path, child_path); 00435 ReleaseTokenFSCall(); 00436 00437 if(rc) 00438 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_link); 00439 00440 new_validator = target_handle->data.validator; 00441 00442 /* add this hardlink to namespace */ 00443 NamespaceAdd(dir_handle->data.inode, 00444 dir_handle->data.device, 00445 dir_handle->data.validator, 00446 p_link_name->name, 00447 target_handle->data.inode, target_handle->data.device, &new_validator); 00448 00449 if(new_validator != target_handle->data.validator) 00450 { 00451 LogMajor(COMPONENT_FSAL, 00452 "A wrong behaviour has been detected is FSAL_link: An object and its hardlink don't have the same generation id"); 00453 } 00454 00455 if(attributes) 00456 { 00457 fsal_status_t st; 00458 00459 st = FUSEFSAL_getattrs(target_handle, p_context, attributes); 00460 00461 /* On error, we set a flag in the returned attributes */ 00462 00463 if(FSAL_IS_ERROR(st)) 00464 { 00465 FSAL_CLEAR_MASK(attributes->asked_attributes); 00466 FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00467 } 00468 } 00469 00470 /* OK */ 00471 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); 00472 00473 } 00474 00482 fsal_status_t FUSEFSAL_mknode(fsal_handle_t * parentdir_handle, /* IN */ 00483 fsal_name_t * p_node_name, /* IN */ 00484 fsal_op_context_t * p_context, /* IN */ 00485 fsal_accessmode_t accessmode, /* IN */ 00486 fsal_nodetype_t nodetype, /* IN */ 00487 fsal_dev_t * dev, /* IN */ 00488 fsal_handle_t * p_object_handle, /* OUT (handle to the created node) */ 00489 fsal_attrib_list_t * node_attributes /* [ IN/OUT ] */ 00490 ) 00491 { 00492 00493 /* sanity checks. 00494 * note : link_attributes is optional. 00495 */ 00496 if(!parentdir_handle || !p_context || !nodetype || !dev || !p_node_name) 00497 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); 00498 00499 /* Not implemented */ 00500 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_mknode); 00501 00502 }