nfs-ganesha 1.4

fsal_create.c

Go to the documentation of this file.
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 }