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_convert.h"
00041 #include <sys/fsuid.h>
00042 
00082 fsal_status_t GPFSFSAL_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 GPFSFSAL_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 * file_desc,        /* OUT */
00136                         fsal_attrib_list_t * p_file_attributes  /* [ IN/OUT ] */
00137     )
00138 {
00139 
00140   int rc;
00141   fsal_status_t status;
00142 
00143   int fd;
00144   int posix_flags = 0;
00145   gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc;
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   p_file_descriptor->fd = fd;
00166   ReleaseTokenFSCall();
00167 
00168   if(FSAL_IS_ERROR(status))
00169     {
00170       p_file_descriptor->fd = 0;
00171       ReturnStatus(status, INDEX_FSAL_open);
00172     }
00173 
00174   /* output attributes */
00175   if(p_file_attributes)
00176     {
00177 
00178       p_file_attributes->asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
00179       status = GPFSFSAL_getattrs(p_filehandle, p_context, p_file_attributes);
00180       if(FSAL_IS_ERROR(status))
00181         {
00182           p_file_descriptor->fd = 0;
00183           close(fd);
00184           ReturnStatus(status, INDEX_FSAL_open);
00185         }
00186     }
00187 
00188   /* set the read-only flag of the file descriptor */
00189   p_file_descriptor->ro = openflags & FSAL_O_RDONLY;
00190 
00191   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open);
00192 
00193 }
00194 
00219 fsal_status_t GPFSFSAL_read(fsal_file_t * file_desc,        /* IN */
00220                         fsal_seek_t * p_seek_descriptor,        /* [IN] */
00221                         fsal_size_t buffer_size,        /* IN */
00222                         caddr_t buffer, /* OUT */
00223                         fsal_size_t * p_read_amount,    /* OUT */
00224                         fsal_boolean_t * p_end_of_file  /* OUT */
00225     )
00226 {
00227 
00228   size_t i_size;
00229   ssize_t nb_read;
00230   int rc = 0, errsv = 0;
00231   int pcall = FALSE;
00232   gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc;
00233 
00234   /* sanity checks. */
00235 
00236   if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
00237     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00238 
00240   i_size = (size_t) buffer_size;
00241 
00242   /* positioning */
00243 
00244   if(p_seek_descriptor)
00245     {
00246 
00247       switch (p_seek_descriptor->whence)
00248         {
00249         case FSAL_SEEK_CUR:
00250           /* set position plus offset */
00251           pcall = FALSE;
00252           TakeTokenFSCall();
00253           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
00254           errsv = errno;
00255           ReleaseTokenFSCall();
00256           break;
00257 
00258         case FSAL_SEEK_SET:
00259           /* use pread/pwrite call */
00260           pcall = TRUE;
00261           rc = 0;
00262           break;
00263 
00264         case FSAL_SEEK_END:
00265           /* set end of file plus offset */
00266           pcall = FALSE;
00267 
00268           TakeTokenFSCall();
00269           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
00270           errsv = errno;
00271           ReleaseTokenFSCall();
00272 
00273           break;
00274         }
00275 
00276       if(rc)
00277         {
00278           LogFullDebug(COMPONENT_FSAL,
00279                        "Error in posix fseek operation (whence=%s, offset=%lld)",
00280                        format_seek_whence(p_seek_descriptor->whence),
00281                        (long long) p_seek_descriptor->offset);
00282 
00283           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00284         }
00285 
00286     }
00287 
00288   /* read operation */
00289 
00290   TakeTokenFSCall();
00291 
00292   if(pcall)
00293     nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
00294   else
00295     nb_read = read(p_file_descriptor->fd, buffer, i_size);
00296   errsv = errno;
00297   ReleaseTokenFSCall();
00298 
00301   if(nb_read == -1)
00302     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00303   else if(nb_read == 0)
00304     *p_end_of_file = 1;
00305 
00306   *p_read_amount = nb_read;
00307 
00308   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00309 
00310 }
00311 
00335 fsal_status_t GPFSFSAL_write(fsal_file_t * file_desc,       /* IN */
00336                          fsal_op_context_t * p_context,     /* IN */
00337                          fsal_seek_t * p_seek_descriptor,       /* IN */
00338                          fsal_size_t buffer_size,       /* IN */
00339                          caddr_t buffer,        /* IN */
00340                          fsal_size_t * p_write_amount   /* OUT */
00341     )
00342 {
00343 
00344   ssize_t nb_written;
00345   size_t i_size;
00346   int rc = 0, errsv = 0;
00347   int pcall = FALSE, fsuid, fsgid;
00348   gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc;
00349 
00350   /* sanity checks. */
00351   if(!p_file_descriptor || !buffer || !p_write_amount)
00352     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);
00353 
00354   if(p_file_descriptor->ro)
00355     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);
00356 
00358   i_size = (size_t) buffer_size;
00359 
00360   *p_write_amount = 0;
00361 
00362   /* positioning */
00363 
00364   if(p_seek_descriptor)
00365     {
00366 
00367       switch (p_seek_descriptor->whence)
00368         {
00369         case FSAL_SEEK_CUR:
00370           /* set position plus offset */
00371           pcall = FALSE;
00372 
00373           TakeTokenFSCall();
00374           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
00375           errsv = errno;
00376           ReleaseTokenFSCall();
00377           break;
00378 
00379         case FSAL_SEEK_SET:
00380           /* set absolute position to offset */
00381           pcall = TRUE;
00382           rc = 0;
00383           break;
00384 
00385         case FSAL_SEEK_END:
00386           /* set end of file plus offset */
00387           pcall = FALSE;
00388 
00389           TakeTokenFSCall();
00390           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
00391           errsv = errno;
00392           ReleaseTokenFSCall();
00393 
00394           break;
00395         }
00396 
00397       if(rc)
00398         {
00399           LogFullDebug(COMPONENT_FSAL,
00400                        "Error in posix fseek operation (whence=%s, offset=%lld)",
00401                        format_seek_whence(p_seek_descriptor->whence),
00402                        (long long) p_seek_descriptor->offset);
00403 
00404           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00405 
00406         }
00407 
00408       LogFullDebug(COMPONENT_FSAL,
00409                    "Write operation (whence=%s, offset=%lld, size=%zd)",
00410                    format_seek_whence(p_seek_descriptor->whence),
00411                    (long long) p_seek_descriptor->offset, buffer_size);
00412 
00413     }
00414 
00415   /* write operation */
00416 
00417   TakeTokenFSCall();
00418 
00419   fsuid = setfsuid(p_context->credential.user);
00420   fsgid = setfsgid(p_context->credential.group);
00421   if(pcall)
00422     nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
00423   else
00424     nb_written = write(p_file_descriptor->fd, buffer, i_size);
00425   errsv = errno;
00426 
00427   setfsuid(fsuid);
00428   setfsgid(fsgid);
00429   ReleaseTokenFSCall();
00430 
00432   if(nb_written <= 0)
00433     {
00434       if (p_seek_descriptor)
00435         LogDebug(COMPONENT_FSAL,
00436                  "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.",
00437                  (unsigned long long) i_size,
00438                  (long long) p_seek_descriptor->offset,
00439                  p_file_descriptor->fd,
00440                  errsv);
00441       else
00442         LogDebug(COMPONENT_FSAL,
00443                  "Write operation of size %llu at offset 0. fd=%d, errno=%d.",
00444                  (unsigned long long) i_size,
00445                  p_file_descriptor->fd,
00446                  errsv);
00447 
00448       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00449     }
00450 
00451   /* set output vars */
00452 
00453   *p_write_amount = (fsal_size_t) nb_written;
00454 
00455   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00456 
00457 }
00458 
00471 fsal_status_t GPFSFSAL_close(fsal_file_t * p_file_descriptor        /* IN */
00472     )
00473 {
00474 
00475   int rc, errsv;
00476 
00477   /* sanity checks. */
00478   if(!p_file_descriptor)
00479     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);
00480 
00481   /* call to close */
00482 
00483   TakeTokenFSCall();
00484 
00485   rc = close(((gpfsfsal_file_t *)p_file_descriptor)->fd);
00486   errsv = errno;
00487 
00488   ReleaseTokenFSCall();
00489 
00490   if(rc)
00491     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close);
00492 
00493   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00494 
00495 }
00496 
00497 unsigned int GPFSFSAL_GetFileno(fsal_file_t * pfile)
00498 {
00499         return ((gpfsfsal_file_t *)pfile)->fd;
00500 }
00501 
00519 fsal_status_t GPFSFSAL_commit( fsal_file_t * p_file_descriptor, 
00520                              fsal_off_t    offset, 
00521                              fsal_size_t   length )
00522 {
00523   int rc, errsv;
00524 
00525   /* sanity checks. */
00526   if(!p_file_descriptor)
00527     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit);
00528 
00529   /* Flush data. */
00530   TakeTokenFSCall();
00531   rc = fsync(((gpfsfsal_file_t *)p_file_descriptor)->fd);
00532   errsv = errno;
00533   ReleaseTokenFSCall();
00534 
00535   if(rc)
00536     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit);
00537 
00538   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00539 }