nfs-ganesha 1.4

fsal_fileop.c

Go to the documentation of this file.
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 
00034 #ifdef HAVE_CONFIG_H
00035 #include "config.h"
00036 #endif
00037 
00038 #include "fsal.h"
00039 #include "fsal_internal.h"
00040 #include "FSAL/access_check.h"
00041 #include "fsal_convert.h"
00042 
00082 fsal_status_t VFSFSAL_open_by_name(fsal_handle_t * dirhandle,      /* IN */
00083                                 fsal_name_t * filename, /* IN */
00084                                 fsal_op_context_t * p_context,  /* IN */
00085                                 fsal_openflags_t openflags,     /* IN */
00086                                 fsal_file_t * file_descriptor,  /* OUT */
00087                                 fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ )
00088 {
00089   fsal_status_t fsal_status;
00090   fsal_handle_t filehandle;
00091 
00092   if(!dirhandle || !filename || !p_context || !file_descriptor)
00093     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name);
00094 
00095   fsal_status = FSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes);
00096   if(FSAL_IS_ERROR(fsal_status))
00097     return fsal_status;
00098 
00099   return FSAL_open(&filehandle, p_context, openflags, file_descriptor, file_attributes);
00100 }
00101 
00132 fsal_status_t VFSFSAL_open(fsal_handle_t * p_filehandle,   /* IN */
00133                         fsal_op_context_t * p_context,  /* IN */
00134                         fsal_openflags_t openflags,     /* IN */
00135                         fsal_file_t * p_file_descriptor,        /* OUT */
00136                         fsal_attrib_list_t * p_file_attributes  /* [ IN/OUT ] */
00137     )
00138 {
00139 
00140   int rc, errsv;
00141   fsal_status_t status;
00142 
00143   int fd;
00144   struct stat buffstat;
00145   int posix_flags = 0;
00146 
00147   /* sanity checks.
00148    * note : file_attributes is optional.
00149    */
00150   if(!p_filehandle || !p_context || !p_file_descriptor)
00151     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open);
00152 
00153   /* convert fsal open flags to posix open flags */
00154   rc = fsal2posix_openflags(openflags, &posix_flags);
00155 
00156   /* flags conflicts. */
00157   if(rc)
00158     {
00159       LogWarn(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags);
00160       Return(rc, 0, INDEX_FSAL_open);
00161     }
00162 
00163   TakeTokenFSCall();
00164   status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags);
00165   ReleaseTokenFSCall();
00166 
00167   if(FSAL_IS_ERROR(status))
00168     ReturnStatus(status, INDEX_FSAL_open);
00169 
00170   /* retrieve file attributes for checking access rights */
00171 
00172   TakeTokenFSCall();
00173   rc = fstat(fd, &buffstat);
00174   errsv = errno;
00175   ReleaseTokenFSCall();
00176 
00177   if(rc)
00178     {
00179       close(fd);
00180 
00181       if(errsv == ENOENT)
00182         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open);
00183       else
00184         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open);
00185     }
00186 
00187   status =
00188       fsal_check_access(p_context,
00189                                (openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK) |
00190                                FSAL_OWNER_OK, &buffstat, NULL);
00191   if(FSAL_IS_ERROR(status))
00192     {
00193       close(fd);
00194       ReturnStatus(status, INDEX_FSAL_open);
00195     }
00196 
00197   TakeTokenFSCall();
00198   ((vfsfsal_file_t *)p_file_descriptor)->fd = fd;
00199   errsv = errno;
00200   ReleaseTokenFSCall();
00201 
00202   /* set the read-only flag of the file descriptor */
00203   ((vfsfsal_file_t *)p_file_descriptor)->ro = openflags & FSAL_O_RDONLY;
00204 
00205   /* output attributes */
00206   if(p_file_attributes)
00207     {
00208 
00209       status = posix2fsal_attributes(&buffstat, p_file_attributes);
00210 
00211       if(FSAL_IS_ERROR(status))
00212         {
00213           FSAL_CLEAR_MASK(p_file_attributes->asked_attributes);
00214           FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00215         }
00216     }
00217 
00218   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open);
00219 
00220 }
00221 
00246 fsal_status_t VFSFSAL_read(fsal_file_t * file_desc,        /* IN */
00247                         fsal_seek_t * p_seek_descriptor,        /* [IN] */
00248                         fsal_size_t buffer_size,        /* IN */
00249                         caddr_t buffer, /* OUT */
00250                         fsal_size_t * p_read_amount,    /* OUT */
00251                         fsal_boolean_t * p_end_of_file  /* OUT */
00252     )
00253 {
00254   vfsfsal_file_t * p_file_descriptor = (vfsfsal_file_t *) file_desc;
00255   size_t i_size;
00256   ssize_t nb_read;
00257   int rc = 0, errsv = 0;
00258   int pcall = FALSE;
00259 
00260   /* sanity checks. */
00261 
00262   if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
00263     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00264 
00266   i_size = (size_t) buffer_size;
00267 
00268   /* positioning */
00269 
00270   if(p_seek_descriptor)
00271     {
00272       switch (p_seek_descriptor->whence)
00273         {
00274         case FSAL_SEEK_CUR:
00275           /* set position plus offset */
00276           pcall = FALSE;
00277           TakeTokenFSCall();
00278           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
00279           errsv = errno;
00280           ReleaseTokenFSCall();
00281           break;
00282 
00283         case FSAL_SEEK_SET:
00284           /* use pread/pwrite call */
00285           pcall = TRUE;
00286           rc = 0;
00287           errsv = 0;
00288           break;
00289 
00290         case FSAL_SEEK_END:
00291           /* set end of file plus offset */
00292           pcall = FALSE;
00293 
00294           TakeTokenFSCall();
00295           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
00296           errsv = errno;
00297           ReleaseTokenFSCall();
00298           break;
00299         }
00300 
00301       if(rc)
00302         {
00303           LogFullDebug(COMPONENT_FSAL,
00304                        "Error in posix fseek operation (whence=%s, offset=%lld)",
00305                        (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00306                         (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00307                          (p_seek_descriptor->whence ==
00308                           FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00309                        (long long) p_seek_descriptor->offset);
00310 
00311           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00312         }
00313 
00314     }
00315 
00316   /* read operation */
00317 
00318   TakeTokenFSCall();
00319 
00320   if(pcall)
00321     nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
00322   else
00323     nb_read = read(p_file_descriptor->fd, buffer, i_size);
00324   errsv = errno;
00325   ReleaseTokenFSCall();
00326 
00329   if(nb_read == -1)
00330     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00331   else if(nb_read == 0)
00332     *p_end_of_file = 1;
00333 
00334   *p_read_amount = nb_read;
00335 
00336   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00337 
00338 }
00339 
00363 fsal_status_t VFSFSAL_write(fsal_file_t * file_desc,       /* IN */
00364                          fsal_op_context_t * p_context,    /* IN */
00365                          fsal_seek_t * p_seek_descriptor,       /* IN */
00366                          fsal_size_t buffer_size,       /* IN */
00367                          caddr_t buffer,        /* IN */
00368                          fsal_size_t * p_write_amount   /* OUT */
00369     )
00370 {
00371   vfsfsal_file_t * p_file_descriptor = (vfsfsal_file_t *) file_desc;
00372   ssize_t nb_written;
00373   size_t i_size;
00374   int rc = 0, errsv = 0;
00375   int pcall = FALSE;
00376 
00377   /* sanity checks. */
00378   if(!p_file_descriptor || !buffer || !p_write_amount)
00379     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);
00380 
00381   if(p_file_descriptor->ro)
00382     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);
00383 
00385   i_size = (size_t) buffer_size;
00386 
00387   *p_write_amount = 0;
00388 
00389   /* positioning */
00390 
00391   if(p_seek_descriptor)
00392     {
00393 
00394       switch (p_seek_descriptor->whence)
00395         {
00396         case FSAL_SEEK_CUR:
00397           /* set position plus offset */
00398           pcall = FALSE;
00399 
00400           TakeTokenFSCall();
00401           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
00402           errsv = errno;
00403           ReleaseTokenFSCall();
00404           break;
00405 
00406         case FSAL_SEEK_SET:
00407           /* set absolute position to offset */
00408           pcall = TRUE;
00409           rc = 0;
00410           errsv = 0;
00411           break;
00412 
00413         case FSAL_SEEK_END:
00414           /* set end of file plus offset */
00415           pcall = FALSE;
00416 
00417           TakeTokenFSCall();
00418           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
00419           errsv = errno;
00420           ReleaseTokenFSCall();
00421           break;
00422         }
00423 
00424       if(rc)
00425         {
00426           LogFullDebug(COMPONENT_FSAL,
00427                        "Error in posix fseek operation (whence=%s, offset=%lld)",
00428                        (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00429                         (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00430                          (p_seek_descriptor->whence ==
00431                           FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00432                        (long long) p_seek_descriptor->offset);
00433 
00434           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00435 
00436         }
00437 
00438       LogFullDebug(COMPONENT_FSAL,
00439                    "Write operation (whence=%s, offset=%lld, size=%zd)",
00440                    (p_seek_descriptor->whence ==
00441                     FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence ==
00442                                                   FSAL_SEEK_SET ? "SEEK_SET"
00443                                                   : (p_seek_descriptor->whence ==
00444                                                      FSAL_SEEK_END ? "SEEK_END" :
00445                                                      "ERROR"))),
00446                    (long long) p_seek_descriptor->offset, buffer_size);
00447 
00448     }
00449 
00450   /* write operation */
00451 
00452   TakeTokenFSCall();
00453 
00454   if(pcall)
00455     nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
00456   else
00457     nb_written = write(p_file_descriptor->fd, buffer, i_size);
00458   errsv = errno;
00459 
00460   ReleaseTokenFSCall();
00461 
00463   if(nb_written <= 0)
00464     {
00465       if (p_seek_descriptor)
00466         LogDebug(COMPONENT_FSAL,
00467                  "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.",
00468                  (unsigned long long) i_size,
00469                  (long long) p_seek_descriptor->offset,
00470                  p_file_descriptor->fd,
00471                  errsv);
00472       else
00473         LogDebug(COMPONENT_FSAL,
00474                  "Write operation of size %llu at offset 0. fd=%d, errno=%d.",
00475                  (unsigned long long) i_size,
00476                  p_file_descriptor->fd,
00477                  errsv);
00478 
00479       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00480     }
00481 
00482   /* set output vars */
00483 
00484   *p_write_amount = (fsal_size_t) nb_written;
00485 
00486   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00487 
00488 }
00489 
00502 fsal_status_t VFSFSAL_close(fsal_file_t * p_file_descriptor        /* IN */
00503     )
00504 {
00505 
00506   int rc, errsv;
00507 
00508   /* sanity checks. */
00509   if(!p_file_descriptor)
00510     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);
00511 
00512   if(((vfsfsal_file_t *)p_file_descriptor)->fd == 0 )
00513        Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00514 
00515   /* call to close */
00516   TakeTokenFSCall();
00517 
00518   rc = close(((vfsfsal_file_t *)p_file_descriptor)->fd);
00519   errsv = errno;
00520 
00521   ReleaseTokenFSCall();
00522 
00523   if(rc)
00524     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close);
00525 
00526   ((vfsfsal_file_t *)p_file_descriptor)->fd = 0 ;
00527 
00528   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00529 
00530 }
00531 
00532 unsigned int VFSFSAL_GetFileno(fsal_file_t * pfile)
00533 {
00534         return ((vfsfsal_file_t *)pfile)->fd;
00535 }
00536 
00554 fsal_status_t VFSFSAL_commit(fsal_file_t * p_file_descriptor,
00555                            fsal_off_t    offset, 
00556                            fsal_size_t   length )
00557 {
00558   int rc, errsv;
00559 
00560   /* sanity checks. */
00561   if(!p_file_descriptor)
00562     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit);
00563 
00564   if(((vfsfsal_file_t *)p_file_descriptor)->fd == 0 )
00565     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); /* Nothing to sync, the fd is not opened */
00566 
00567   /* Flush data. */
00568   TakeTokenFSCall();
00569   rc = fsync(((vfsfsal_file_t *)p_file_descriptor)->fd);
00570   errsv = errno;
00571   ReleaseTokenFSCall();
00572 
00573 
00574   if(rc)
00575     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit);
00576 
00577   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00578 }