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 XFSFSAL_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   xfsfsal_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 =
00096       XFSFSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes);
00097   if(FSAL_IS_ERROR(fsal_status))
00098     return fsal_status;
00099 
00100   return XFSFSAL_open(&filehandle, p_context, openflags, file_descriptor,
00101                       file_attributes);
00102 }
00103 
00134 fsal_status_t XFSFSAL_open(fsal_handle_t * p_filehandle,     /* IN */
00135                            fsal_op_context_t * p_context,    /* IN */
00136                            fsal_openflags_t openflags,  /* IN */
00137                            fsal_file_t * p_file_descriptor,  /* OUT */
00138                            fsal_attrib_list_t * p_file_attributes       /* [ IN/OUT ] */
00139     )
00140 {
00141 
00142   int rc, errsv;
00143   fsal_status_t status;
00144 
00145   int fd = 0 ;
00146   struct stat buffstat;
00147   int posix_flags = 0;
00148 
00149   /* sanity checks.
00150    * note : file_attributes is optional.
00151    */
00152   if(!p_filehandle || !p_context || !p_file_descriptor)
00153     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open);
00154 
00155   /* convert fsal open flags to posix open flags */
00156   rc = fsal2posix_openflags(openflags, &posix_flags);
00157 
00158   /* flags conflicts. */
00159   if(rc)
00160     {
00161       LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X",
00162                         openflags);
00163       Return(rc, 0, INDEX_FSAL_open);
00164     }
00165 
00166   TakeTokenFSCall();
00167   status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags);
00168   ReleaseTokenFSCall();
00169 
00170   if(FSAL_IS_ERROR(status))
00171     ReturnStatus(status, INDEX_FSAL_open);
00172 
00173   /* retrieve file attributes for checking access rights */
00174 
00175   TakeTokenFSCall();
00176   rc = fstat(fd, &buffstat);
00177   errsv = errno;
00178   ReleaseTokenFSCall();
00179 
00180   if(rc)
00181     {
00182       close(fd);
00183 
00184       if(errsv == ENOENT)
00185         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open);
00186       else
00187         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open);
00188     }
00189 
00190 #if 0
00191   /* No required, the open would have failed if not permitted */
00192   status =
00193       fsal_check_access(p_context,
00194                                openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK,
00195                                &buffstat, NULL);
00196   if(FSAL_IS_ERROR(status))
00197     {
00198       close(fd);
00199       ReturnStatus(status, INDEX_FSAL_open);
00200     }
00201 #endif
00202 
00203   TakeTokenFSCall();
00204   ((xfsfsal_file_t *)p_file_descriptor)->fd = fd;
00205   errsv = errno;
00206   ReleaseTokenFSCall();
00207 
00208   /* set the read-only flag of the file descriptor */
00209   ((xfsfsal_file_t *)p_file_descriptor)->ro = openflags & FSAL_O_RDONLY;
00210 
00211   /* output attributes */
00212   if(p_file_attributes)
00213     {
00214 
00215       status = posix2fsal_attributes(&buffstat, p_file_attributes);
00216 
00217       if(FSAL_IS_ERROR(status))
00218         {
00219           FSAL_CLEAR_MASK(p_file_attributes->asked_attributes);
00220           FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00221         }
00222     }
00223 
00224   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open);
00225 
00226 }
00227 
00252 fsal_status_t XFSFSAL_read(fsal_file_t * p_file_descriptor,  /* IN */
00253                            fsal_seek_t * p_seek_descriptor,     /* [IN] */
00254                            fsal_size_t buffer_size,     /* IN */
00255                            caddr_t buffer,      /* OUT */
00256                            fsal_size_t * p_read_amount, /* OUT */
00257                            fsal_boolean_t * p_end_of_file       /* OUT */
00258     )
00259 {
00260 
00261   size_t i_size;
00262   ssize_t nb_read;
00263   int rc, errsv;
00264   int pcall = FALSE;
00265 
00266   /* sanity checks. */
00267 
00268   if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
00269     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00270 
00272   i_size = (size_t) buffer_size;
00273 
00274   /* positioning */
00275 
00276   if(p_seek_descriptor)
00277     {
00278 
00279       switch (p_seek_descriptor->whence)
00280         {
00281         case FSAL_SEEK_CUR:
00282           /* set position plus offset */
00283           pcall = FALSE;
00284           TakeTokenFSCall();
00285           rc = lseek(((xfsfsal_file_t *)p_file_descriptor)->fd,
00286                      p_seek_descriptor->offset, SEEK_CUR);
00287           errsv = errno;
00288           ReleaseTokenFSCall();
00289           break;
00290 
00291         case FSAL_SEEK_SET:
00292           /* use pread/pwrite call */
00293           pcall = TRUE;
00294           rc = 0;
00295           errsv = 0;
00296           break;
00297 
00298         case FSAL_SEEK_END:
00299           /* set end of file plus offset */
00300           pcall = FALSE;
00301 
00302           TakeTokenFSCall();
00303           rc = lseek(((xfsfsal_file_t *)p_file_descriptor)->fd,
00304                      p_seek_descriptor->offset, SEEK_END);
00305           errsv = errno;
00306           ReleaseTokenFSCall();
00307 
00308         default:
00309           rc = -1;
00310           errsv = EINVAL;
00311 
00312           break;
00313         }
00314 
00315       if(rc)
00316         {
00317           LogEvent(COMPONENT_FSAL,
00318                             "Error in posix fseek operation (whence=%s, offset=%"PRId64")",
00319                             (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00320                              (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00321                               (p_seek_descriptor->whence ==
00322                                FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00323                             p_seek_descriptor->offset);
00324 
00325           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00326         }
00327 
00328     }
00329 
00330   /* read operation */
00331 
00332   TakeTokenFSCall();
00333 
00334   if(pcall)
00335     nb_read = pread(((xfsfsal_file_t *)p_file_descriptor)->fd, buffer,
00336                     i_size, p_seek_descriptor->offset);
00337   else
00338     nb_read = read(((xfsfsal_file_t *)p_file_descriptor)->fd, buffer, i_size);
00339   errsv = errno;
00340   ReleaseTokenFSCall();
00341 
00344   if(nb_read == -1)
00345     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00346   else if(nb_read == 0)
00347     *p_end_of_file = 1;
00348 
00349   *p_read_amount = nb_read;
00350 
00351   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00352 
00353 }
00354 
00378 fsal_status_t XFSFSAL_write(fsal_file_t * p_file_descriptor, /* IN */
00379                             fsal_op_context_t * p_context,   /* IN */
00380                             fsal_seek_t * p_seek_descriptor,    /* IN */
00381                             fsal_size_t buffer_size,    /* IN */
00382                             caddr_t buffer,     /* IN */
00383                             fsal_size_t * p_write_amount        /* OUT */
00384     )
00385 {
00386 
00387   ssize_t nb_written;
00388   size_t i_size;
00389   int rc, errsv;
00390   int pcall = FALSE;
00391 
00392   /* sanity checks. */
00393   if(!p_file_descriptor || !buffer || !p_write_amount)
00394     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);
00395 
00396   if(((xfsfsal_file_t *)p_file_descriptor)->ro)
00397     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);
00398 
00400   i_size = (size_t) buffer_size;
00401 
00402   *p_write_amount = 0;
00403 
00404   /* positioning */
00405 
00406   if(p_seek_descriptor)
00407     {
00408 
00409       switch (p_seek_descriptor->whence)
00410         {
00411         case FSAL_SEEK_CUR:
00412           /* set position plus offset */
00413           pcall = FALSE;
00414 
00415           TakeTokenFSCall();
00416           rc = lseek(((xfsfsal_file_t *)p_file_descriptor)->fd, p_seek_descriptor->offset, SEEK_CUR);
00417           errsv = errno;
00418           ReleaseTokenFSCall();
00419           break;
00420 
00421         case FSAL_SEEK_SET:
00422           /* set absolute position to offset */
00423           pcall = TRUE;
00424           rc = 0;
00425           errsv = 0;
00426           break;
00427 
00428         case FSAL_SEEK_END:
00429           /* set end of file plus offset */
00430           pcall = FALSE;
00431 
00432           TakeTokenFSCall();
00433           rc = lseek(((xfsfsal_file_t *)p_file_descriptor)->fd, p_seek_descriptor->offset, SEEK_END);
00434           errsv = errno;
00435           ReleaseTokenFSCall();
00436 
00437           break;
00438         default:
00439           rc = -1;
00440           errsv = EINVAL;
00441           break;
00442         }
00443 
00444       if(rc)
00445         {
00446           LogEvent(COMPONENT_FSAL,
00447                             "Error in posix fseek operation (whence=%s, offset=%"PRId64")",
00448                             (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00449                              (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00450                               (p_seek_descriptor->whence ==
00451                                FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00452                             p_seek_descriptor->offset);
00453 
00454           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00455 
00456         }
00457 
00458       LogFullDebug(COMPONENT_FSAL,
00459                         "Write operation (whence=%s, offset=%"PRId64", size=%zu)",
00460                         (p_seek_descriptor->whence ==
00461                          FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence ==
00462                                                        FSAL_SEEK_SET ? "SEEK_SET"
00463                                                        : (p_seek_descriptor->whence ==
00464                                                           FSAL_SEEK_END ? "SEEK_END" :
00465                                                           "ERROR"))),
00466                         p_seek_descriptor->offset, buffer_size);
00467 
00468     }
00469 
00470   /* write operation */
00471 
00472   TakeTokenFSCall();
00473 
00474   if(pcall)
00475     nb_written = pwrite(((xfsfsal_file_t *)p_file_descriptor)->fd,
00476                         buffer, i_size, p_seek_descriptor->offset);
00477   else
00478     nb_written = write(((xfsfsal_file_t *)p_file_descriptor)->fd, buffer, i_size);
00479   errsv = errno;
00480 
00481   ReleaseTokenFSCall();
00482 
00484   if(nb_written <= 0)
00485     {
00486       LogDebug(COMPONENT_FSAL,
00487                "Write operation of size %zu at offset %"PRId64" failed. fd=%d, errno=%d.",
00488                i_size, p_seek_descriptor->offset,
00489                ((xfsfsal_file_t *)p_file_descriptor)->fd, errsv);
00490       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00491     }
00492 
00493   /* set output vars */
00494 
00495   *p_write_amount = (fsal_size_t) nb_written;
00496 
00497   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00498 
00499 }
00500 
00513 fsal_status_t XFSFSAL_close(fsal_file_t * p_file_descriptor  /* IN */
00514     )
00515 {
00516 
00517   int rc, errsv;
00518 
00519   /* sanity checks. */
00520   if(!p_file_descriptor)
00521     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);
00522 
00523   if(((xfsfsal_file_t *)p_file_descriptor)->fd == 0 )
00524        Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00525 
00526   /* call to close */
00527 
00528   TakeTokenFSCall();
00529 
00530   rc = close(((xfsfsal_file_t *)p_file_descriptor)->fd);
00531   errsv = errno;
00532 
00533   ReleaseTokenFSCall();
00534 
00535   if(rc)
00536     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close);
00537 
00538   ((xfsfsal_file_t *)p_file_descriptor)->fd = 0 ;
00539 
00540   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00541 
00542 }
00543 
00544 unsigned int XFSFSAL_GetFileno(fsal_file_t * pfile)
00545 {
00546   return ((xfsfsal_file_t *) pfile)->fd;
00547 }
00548 
00566 fsal_status_t XFSFSAL_commit( fsal_file_t * p_file_descriptor,
00567                             fsal_off_t    offset, 
00568                             fsal_size_t   length )
00569 {
00570   int rc, errsv;
00571 
00572   /* sanity checks. */
00573   if(!p_file_descriptor)
00574     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit);
00575 
00576   if(((xfsfsal_file_t *)p_file_descriptor)->fd == 0 )
00577     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); /* Nothing to sync, the file is not opened */
00578 
00579   /* Flush data. */
00580   TakeTokenFSCall();
00581   rc = fsync(((xfsfsal_file_t *)p_file_descriptor)->fd);
00582   errsv = errno;
00583   ReleaseTokenFSCall();
00584 
00585   if(rc)
00586     {
00587       LogEvent(COMPONENT_FSAL, "Error in fsync operation");
00588       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit);
00589     }
00590 
00591   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00592 }
00593