nfs-ganesha 1.4

fsal_fileop.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  */
00004 
00013 #ifdef HAVE_CONFIG_H
00014 #include "config.h"
00015 #endif
00016 
00017 #include "fsal.h"
00018 #include "fsal_internal.h"
00019 #include "fsal_convert.h"
00020 #include "namespace.h"
00021 #include <string.h>
00022 
00059 fsal_status_t FUSEFSAL_open(fsal_handle_t * file_hdl,     /* IN */
00060                             fsal_op_context_t * p_context,  /* IN */
00061                             fsal_openflags_t openflags, /* IN */
00062                             fsal_file_t * file_desc,  /* OUT */
00063                             fsal_attrib_list_t * file_attributes        /* [ IN/OUT ] */
00064     )
00065 {
00066 
00067   int rc = 0;
00068   char object_path[FSAL_MAX_PATH_LEN];
00069   int file_info_provided = FALSE;
00070   fusefsal_handle_t * filehandle = (fusefsal_handle_t *)file_hdl;
00071   fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;
00072 
00073   /* sanity checks.
00074    * note : file_attributes is optional.
00075    */
00076   if(!filehandle || !p_context || !file_descriptor)
00077     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open);
00078 
00079   /* get the full path for this file */
00080   rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator,
00081                      object_path);
00082   if(rc)
00083     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_open);
00084 
00085   memset(file_descriptor, 0, sizeof(fusefsal_file_t));
00086 
00087   /* set access mode flags */
00088 
00089   file_descriptor->file_info.flags = 0;
00090 
00091   if(openflags & FSAL_O_RDONLY)
00092     file_descriptor->file_info.flags |= O_RDONLY;
00093   if(openflags & FSAL_O_WRONLY)
00094     file_descriptor->file_info.flags |= O_WRONLY;
00095   if(openflags & FSAL_O_RDWR)
00096     file_descriptor->file_info.flags |= O_RDWR;
00097 
00098   /* set context for the next operation, so it can be retrieved by FS thread */
00099   fsal_set_thread_context(p_context);
00100 
00101   /* check open call */
00102 
00103   if(p_fs_ops->open)
00104     {
00105       LogFullDebug(COMPONENT_FSAL, "Call to open( %s, %#X )", object_path, file_descriptor->file_info.flags);
00106 
00107       TakeTokenFSCall();
00108       rc = p_fs_ops->open(object_path, &(file_descriptor->file_info));
00109       ReleaseTokenFSCall();
00110 
00111       if(rc)
00112         Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);
00113 
00114       file_info_provided = TRUE;
00115 
00116     }
00117   else
00118     {
00119       LogFullDebug(COMPONENT_FSAL, "no open command provided");
00120 
00121       /* ignoring open */
00122       memset(&(file_descriptor->file_info), 0, sizeof(struct ganefuse_file_info));
00123     }
00124 
00125   /* check open flags (only FSAL_O_TRUNC and FSAL_O_APPEND are used for FUSE filesystems) */
00126 
00127   if(openflags & FSAL_O_TRUNC)
00128     {
00129       if(file_info_provided && p_fs_ops->ftruncate)
00130         {
00131           LogFullDebug(COMPONENT_FSAL, "call to ftruncate on file since FSAL_O_TRUNC was set");
00132 
00133           /* ftruncate the file */
00134           TakeTokenFSCall();
00135           rc = p_fs_ops->ftruncate(object_path, 0, &(file_descriptor->file_info));
00136           ReleaseTokenFSCall();
00137 
00138           if(rc)
00139             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);
00140         }
00141       else if(p_fs_ops->truncate)
00142         {
00143           LogFullDebug(COMPONENT_FSAL, "call to truncate on file since FSAL_O_TRUNC was set");
00144 
00145           /* truncate the file */
00146           TakeTokenFSCall();
00147           rc = p_fs_ops->truncate(object_path, 0);
00148           ReleaseTokenFSCall();
00149 
00150           if(rc)
00151             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);
00152         }
00153       /* else: ignoring flag */
00154     }
00155 
00156   if(openflags & FSAL_O_APPEND)
00157     {
00158       struct stat stbuf;
00159 
00160       /* In this case, this only solution is to get file attributes */
00161 
00162       if(file_info_provided && p_fs_ops->fgetattr)
00163         {
00164           rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info));
00165         }
00166       else
00167         {
00168           rc = p_fs_ops->getattr(object_path, &stbuf);
00169         }
00170 
00171       if(rc)
00172         Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);
00173 
00174       file_descriptor->current_offset = stbuf.st_size;
00175     }
00176   else
00177     {
00178       file_descriptor->current_offset = 0;
00179     }
00180 
00181   /* fill the file descriptor structure */
00182   file_descriptor->file_handle = *filehandle;
00183 
00184   /* backup context */
00185   file_descriptor->context = *(fusefsal_op_context_t *)p_context;
00186 
00187   if(file_info_provided)
00188     LogFullDebug(COMPONENT_FSAL, "FSAL_open: FH=%"PRId64, file_descriptor->file_info.fh);
00189 
00190   if(file_attributes)
00191     {
00192       fsal_status_t status;
00193 
00194       status = FUSEFSAL_getattrs((fsal_handle_t *)filehandle, p_context, file_attributes);
00195 
00196       /* on error, we set a special bit in the mask. */
00197       if(FSAL_IS_ERROR(status))
00198         {
00199           FSAL_CLEAR_MASK(file_attributes->asked_attributes);
00200           FSAL_SET_MASK(file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00201         }
00202     }
00203 
00204   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open);
00205 
00206 }
00207 
00247 fsal_status_t FUSEFSAL_open_by_name(fsal_handle_t * dirhandle,      /* IN */
00248                                     fsal_name_t * filename,     /* IN */
00249                                     fsal_op_context_t * p_context,  /* IN */
00250                                     fsal_openflags_t openflags, /* IN */
00251                                     fsal_file_t * file_descriptor,  /* OUT */
00252                                     fsal_attrib_list_t *
00253                                     file_attributes /* [ IN/OUT ] */ )
00254 {
00255   fsal_status_t fsal_status;
00256   fsal_handle_t filehandle;
00257 
00258   if(!dirhandle || !filename || !p_context || !file_descriptor)
00259     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name);
00260 
00261   fsal_status =
00262       FUSEFSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes);
00263   if(FSAL_IS_ERROR(fsal_status))
00264     return fsal_status;
00265 
00266   return FUSEFSAL_open(&filehandle, p_context, openflags, file_descriptor,
00267                        file_attributes);
00268 }
00269 
00298 fsal_status_t FUSEFSAL_read(fsal_file_t * file_desc,  /* IN */
00299                             fsal_seek_t * seek_descriptor,      /* [IN] */
00300                             fsal_size_t buffer_size,    /* IN */
00301                             caddr_t buffer,     /* OUT */
00302                             fsal_size_t * read_amount,  /* OUT */
00303                             fsal_boolean_t * end_of_file        /* OUT */
00304     )
00305 {
00306   size_t req_size;
00307   int rc;
00308   off_t seekoffset = 0;
00309   struct stat stbuf;
00310   char object_path[FSAL_MAX_PATH_LEN];
00311   fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;
00312 
00313   /* sanity checks. */
00314 
00315   if(!file_descriptor || !buffer || !read_amount || !end_of_file)
00316     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00317 
00318   if(!p_fs_ops->read)
00319     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_read);
00320 
00321   /* initialize returned values */
00322 
00323   *read_amount = 0;
00324   *end_of_file = 0;
00325 
00326   req_size = (size_t) buffer_size;
00327 
00328   /* get file's full path */
00329   rc = NamespacePath(file_descriptor->file_handle.data.inode,
00330                      file_descriptor->file_handle.data.device,
00331                      file_descriptor->file_handle.data.validator, object_path);
00332   if(rc)
00333     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_read);
00334 
00335   /* set context so it can be retrieved by FS */
00336   fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context);
00337 
00338   LogFullDebug(COMPONENT_FSAL, "FSAL_read: FH=%"PRId64, file_descriptor->file_info.fh);
00339 
00340   if(seek_descriptor)
00341     {
00342 
00343       switch (seek_descriptor->whence)
00344         {
00345         case FSAL_SEEK_SET:
00346           /* set absolute position to offset */
00347           seekoffset = seek_descriptor->offset;
00348           break;
00349 
00350         case FSAL_SEEK_CUR:
00351           /* current position + offset */
00352           seekoffset = file_descriptor->current_offset + seek_descriptor->offset;
00353           break;
00354 
00355         case FSAL_SEEK_END:
00356           /* set end of file + offset */
00357           /* in this case, the only solution is to get entry attributes */
00358 
00359           if(p_fs_ops->fgetattr)
00360             {
00361               rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info));
00362             }
00363           else
00364             {
00365               rc = p_fs_ops->getattr(object_path, &stbuf);
00366             }
00367 
00368           if(rc)
00369             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_read);
00370 
00371           seekoffset = (off_t) stbuf.st_size + seek_descriptor->offset;
00372 
00373           break;
00374 
00375         default:
00376           LogCrit(COMPONENT_FSAL, "FSAL_read: Invalid seek parameter: whence=%d",
00377                   seek_descriptor->whence);
00378           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_read);
00379         }
00380     }
00381   else
00382     {
00383       seekoffset = file_descriptor->current_offset;
00384     }
00385 
00386   /* If the call does not fill all the buffer, the rest of the data must be
00387    * substituted with zeroes. */
00388   memset(buffer, 0, req_size);
00389 
00390   TakeTokenFSCall();
00391   rc = p_fs_ops->read(object_path, buffer, req_size, seekoffset,
00392                       &(file_descriptor->file_info));
00393   ReleaseTokenFSCall();
00394 
00395   if(rc < 0)
00396     Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_read);
00397 
00398   /* rc >= 0 */
00399 
00400   *read_amount = (fsal_size_t) rc;
00401   *end_of_file = (rc < (off_t) req_size);
00402   file_descriptor->current_offset = seekoffset + (off_t) rc;
00403 
00404   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00405 
00406 }
00407 
00435 fsal_status_t FUSEFSAL_write(fsal_file_t * file_desc, /* IN */
00436                              fsal_op_context_t * p_context,     /* IN */
00437                              fsal_seek_t * seek_descriptor,     /* IN */
00438                              fsal_size_t buffer_size,   /* IN */
00439                              caddr_t buffer,    /* IN */
00440                              fsal_size_t * write_amount /* OUT */
00441     )
00442 {
00443   size_t req_size;
00444   int rc;
00445   off_t seekoffset = 0;
00446   struct stat stbuf;
00447   char object_path[FSAL_MAX_PATH_LEN];
00448   fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;
00449 
00450   /* sanity checks. */
00451   if(!file_descriptor || !buffer || !write_amount)
00452     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);
00453 
00454   if(!p_fs_ops->write)
00455     Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_write);
00456 
00457   /* initialize returned values */
00458 
00459   *write_amount = 0;
00460 
00461   req_size = (size_t) buffer_size;
00462 
00463   /* set context so it can be retrieved by FS */
00464   fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context);
00465 
00466   LogFullDebug(COMPONENT_FSAL, "FSAL_write: FH=%"PRId64, file_descriptor->file_info.fh);
00467 
00468   /* get file's full path */
00469   rc = NamespacePath(file_descriptor->file_handle.data.inode,
00470                      file_descriptor->file_handle.data.device,
00471                      file_descriptor->file_handle.data.validator, object_path);
00472   if(rc)
00473     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_write);
00474 
00475   if(seek_descriptor)
00476     {
00477 
00478       switch (seek_descriptor->whence)
00479         {
00480         case FSAL_SEEK_SET:
00481           /* set absolute position to offset */
00482           seekoffset = seek_descriptor->offset;
00483           break;
00484 
00485         case FSAL_SEEK_CUR:
00486           /* current position + offset */
00487           seekoffset = file_descriptor->current_offset + seek_descriptor->offset;
00488           break;
00489 
00490         case FSAL_SEEK_END:
00491           /* set end of file + offset */
00492           /* in this case, the only solution is to get entry attributes */
00493 
00494           if(p_fs_ops->fgetattr)
00495             {
00496               rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info));
00497             }
00498           else
00499             {
00500               rc = p_fs_ops->getattr(object_path, &stbuf);
00501             }
00502 
00503           if(rc)
00504             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write);
00505 
00506           seekoffset = (off_t) stbuf.st_size + seek_descriptor->offset;
00507 
00508           break;
00509 
00510         default:
00511           LogCrit(COMPONENT_FSAL, "FSAL_write: Invalid seek parameter: whence=%d",
00512                   seek_descriptor->whence);
00513           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_write);
00514         }
00515     }
00516   else
00517     {
00518       seekoffset = file_descriptor->current_offset;
00519     }
00520 
00521   TakeTokenFSCall();
00522   rc = p_fs_ops->write(object_path, buffer, req_size, seekoffset,
00523                        &(file_descriptor->file_info));
00524   ReleaseTokenFSCall();
00525 
00526   if(rc < 0)
00527     Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write);
00528 
00529   file_descriptor->current_offset = seekoffset + (off_t) rc;
00530 
00531   *write_amount = (fsal_size_t) rc;
00532 
00533   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00534 }
00535 
00550 fsal_status_t FUSEFSAL_close(fsal_file_t * file_desc  /* IN */
00551     )
00552 {
00553 
00554   int rc;
00555   char file_path[FSAL_MAX_PATH_LEN];
00556   fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;
00557 
00558   /* sanity checks. */
00559   if(!file_descriptor)
00560     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);
00561 
00562   /* get the full path for file inode */
00563   rc = NamespacePath(file_descriptor->file_handle.data.inode,
00564                      file_descriptor->file_handle.data.device,
00565                      file_descriptor->file_handle.data.validator, file_path);
00566   if(rc)
00567     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_close);
00568 
00569   if(!p_fs_ops->release)
00570     /* ignore this call */
00571     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00572 
00573   /* set context so it can be retrieved by FS */
00574   fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context);
00575 
00576   LogFullDebug(COMPONENT_FSAL, "FSAL_close: FH=%"PRId64, file_descriptor->file_info.fh);
00577 
00578   TakeTokenFSCall();
00579 
00580   rc = p_fs_ops->release(file_path, &file_descriptor->file_info);
00581 
00582   ReleaseTokenFSCall();
00583 
00584   if(rc)
00585     Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_close);
00586 
00587   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00588 
00589 }
00590 
00608 fsal_status_t FUSEFSAL_commit( fsal_file_t * p_file_descriptor,
00609                              fsal_off_t    offset, 
00610                              fsal_size_t   length )
00611 {
00612   /* sanity checks. */
00613   if(!p_file_descriptor)
00614     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit);
00615 
00616   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00617 }
00618 
00619 unsigned int FUSEFSAL_GetFileno(fsal_file_t * pfile)
00620 {
00621         return ((fusefsal_file_t *)pfile)->file_info.fh;
00622 }