nfs-ganesha 1.4

fsal_fileop.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
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 
00021 #ifdef _SHOOK
00022 #include "shook_svr.h"
00023 #endif
00024 
00025 
00065 fsal_status_t LUSTREFSAL_open_by_name(fsal_handle_t * dirhandle,  /* IN */
00066                                       fsal_name_t * filename,   /* IN */
00067                                       fsal_op_context_t * p_context,      /* IN */
00068                                       fsal_openflags_t openflags,       /* IN */
00069                                       fsal_file_t * file_descriptor,      /* OUT */
00070                                       fsal_attrib_list_t *
00071                                       file_attributes /* [ IN/OUT ] */ )
00072 {
00073   fsal_status_t fsal_status;
00074   fsal_handle_t filehandle;
00075 
00076   if(!dirhandle || !filename || !p_context || !file_descriptor)
00077     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name);
00078 
00079   fsal_status =
00080       LUSTREFSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes);
00081   if(FSAL_IS_ERROR(fsal_status))
00082     return fsal_status;
00083 
00084   return LUSTREFSAL_open(&filehandle, p_context, openflags, file_descriptor,
00085                          file_attributes);
00086 }
00087 
00118 fsal_status_t LUSTREFSAL_open(fsal_handle_t * p_filehandle,       /* IN */
00119                               fsal_op_context_t * p_context,      /* IN */
00120                               fsal_openflags_t openflags,       /* IN */
00121                               fsal_file_t *file_desc,    /* OUT */
00122                               fsal_attrib_list_t * p_file_attributes    /* [ IN/OUT ] */
00123     )
00124 {
00125   int rc, errsv;
00126   fsal_status_t status;
00127   lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)file_desc;
00128   fsal_path_t fsalpath;
00129   struct stat buffstat;
00130   int posix_flags = 0;
00131 
00132   /* sanity checks.
00133    * note : file_attributes is optional.
00134    */
00135   if(!p_filehandle || !p_context || !p_file_descriptor)
00136     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open);
00137 
00138   status = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath);
00139   if(FSAL_IS_ERROR(status))
00140     ReturnStatus(status, INDEX_FSAL_open);
00141 
00142   /* retrieve file attributes for checking access rights */
00143 
00144   TakeTokenFSCall();
00145   rc = lstat(fsalpath.path, &buffstat);
00146   errsv = errno;
00147   ReleaseTokenFSCall();
00148 
00149   if(rc)
00150     {
00151       if(errsv == ENOENT)
00152         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open);
00153       else
00154         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open);
00155     }
00156 
00157 #if 0
00158   status =
00159       fsal_internal_testAccess(p_context,
00160                                openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK,
00161                                &buffstat, NULL);
00162   if(FSAL_IS_ERROR(status))
00163     ReturnStatus(status, INDEX_FSAL_open);
00164 #endif
00165 
00166   /* convert fsal open flags to posix open flags */
00167   rc = fsal2posix_openflags(openflags, &posix_flags);
00168 
00169   /* flags conflicts. */
00170   if(rc)
00171     {
00172       LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X",
00173                         openflags);
00174       Return(rc, 0, INDEX_FSAL_open);
00175     }
00176 
00177   /* @TODO  For HSM systems, trigger file asynchronous restore
00178    * if the file in offline, to avoid freezing current thread.
00179    * In this case, return EAGAIN to the upper layers.
00180    */
00181 #ifdef _LUSTRE_HSM
00182     /* call "lfs hsm_restore" if file is released */
00183     /* @TODO */
00184 #endif
00185 #ifdef _SHOOK
00186     /* call "shook restore" if file is not online
00187      * or "shook restore_trunc" if file is not online and openflag
00188      * includes O_TRUNC
00189      */
00190     shook_state state;
00191     rc = shook_get_status(fsalpath.path, &state, 0);
00192     if (rc)
00193     {
00194         LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s",
00195                  fsalpath.path, strerror(-rc));
00196         Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open);
00197     }
00198     else if (state != SS_ONLINE)
00199     {
00200         LogInfo(COMPONENT_FSAL, "File is offline: triggering shook restore");
00201 
00202         if (posix_flags & O_TRUNC)
00203         {
00204             TakeTokenFSCall();
00205             rc = truncate(fsalpath.path, 0);
00206             errsv = errno;
00207             ReleaseTokenFSCall();
00208 
00209             if (rc == 0)
00210             {
00211                 /* use a short timeout of 2s */
00212                 rc = shook_server_call(SA_RESTORE_TRUNC, ((lustrefsal_op_context_t *)p_context)->export_context->fsname,
00213                                        &((lustrefsal_handle_t *)p_filehandle)->data.fid, 2);
00214                 if (rc)
00215                     Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open);
00216                 else {
00217                     /* check that file is online, else operation is still
00218                      * in progress: return err jukebox */
00219                     rc = shook_get_status(fsalpath.path, &state, FALSE);
00220                     if (rc)
00221                     {
00222                         LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s",
00223                                  fsalpath.path, strerror(-rc));
00224                         if (rc)
00225                             Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open);
00226                     }
00227                     else if (state != SS_ONLINE)
00228                         Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_open);
00229                     /* else: OK */
00230                 }
00231             }
00232             else
00233             {
00234                   if(errsv == ENOENT)
00235                     Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open);
00236                   else
00237                     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open);
00238             }
00239             /* continue to open */
00240 
00241         } else {
00242             /* trigger restore. Give it a chance to retrieve the file in less than a second.
00243              * Else, it returns ETIME that is converted in ERR_DELAY */
00244             rc = shook_server_call(SA_RESTORE, ((lustrefsal_op_context_t*)p_context)->export_context->fsname,
00245                                    &((lustrefsal_handle_t *)p_filehandle)->data.fid, 1);
00246             if (rc)
00247                 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open);
00248             else {
00249                 /* check that file is online, else operation is still
00250                  * in progress: return err jukebox */
00251                 rc = shook_get_status(fsalpath.path, &state, FALSE);
00252                 if (rc)
00253                 {
00254                     LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s",
00255                              fsalpath.path, strerror(-rc));
00256                     if (rc)
00257                         Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open);
00258                 }
00259                 else if (state != SS_ONLINE)
00260                     Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_open);
00261                 /* else: OK */
00262             }
00263 
00264             /* if rc = 0, file can be opened */
00265         }
00266     }
00267     /* else: we can open file directly */
00268 #endif
00269 
00270   TakeTokenFSCall();
00271   p_file_descriptor->fd = open(fsalpath.path, posix_flags, 0644);
00272   errsv = errno;
00273   ReleaseTokenFSCall();
00274 
00275   if(p_file_descriptor->fd == -1)
00276     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open);
00277 
00278   /* set the read-only flag of the file descriptor */
00279   p_file_descriptor->ro = openflags & FSAL_O_RDONLY;
00280 
00281   /* output attributes */
00282   if(p_file_attributes)
00283     {
00284 
00285       status = posix2fsal_attributes(&buffstat, p_file_attributes);
00286 
00287       if(FSAL_IS_ERROR(status))
00288         {
00289           FSAL_CLEAR_MASK(p_file_attributes->asked_attributes);
00290           FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00291         }
00292     }
00293 
00294   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open);
00295 
00296 }
00297 
00322 fsal_status_t LUSTREFSAL_read(fsal_file_t *file_desc,    /* IN */
00323                               fsal_seek_t * p_seek_descriptor,  /* [IN] */
00324                               fsal_size_t buffer_size,  /* IN */
00325                               caddr_t buffer,   /* OUT */
00326                               fsal_size_t * p_read_amount,      /* OUT */
00327                               fsal_boolean_t * p_end_of_file    /* OUT */
00328     )
00329 {
00330 
00331   size_t i_size;
00332   ssize_t nb_read;
00333   int rc, errsv;
00334   int pcall = FALSE;
00335   lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)file_desc;
00336 
00337   /* sanity checks. */
00338 
00339   if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
00340     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00341 
00343   i_size = (size_t) buffer_size;
00344 
00345   /* positioning */
00346 
00347   if(p_seek_descriptor)
00348     {
00349 
00350       switch (p_seek_descriptor->whence)
00351         {
00352         case FSAL_SEEK_CUR:
00353           /* set position plus offset */
00354           pcall = FALSE;
00355           TakeTokenFSCall();
00356           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
00357           errsv = errno;
00358           ReleaseTokenFSCall();
00359           break;
00360 
00361         case FSAL_SEEK_SET:
00362           /* use pread/pwrite call */
00363           pcall = TRUE;
00364           rc = 0;
00365           break;
00366 
00367         case FSAL_SEEK_END:
00368           /* set end of file plus offset */
00369           pcall = FALSE;
00370 
00371           TakeTokenFSCall();
00372           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
00373           errsv = errno;
00374           ReleaseTokenFSCall();
00375           break;
00376 
00377         default:
00378           LogCrit(COMPONENT_FSAL, "Unexpected value for whence parameter");
00379           rc = -1;
00380           errsv = EINVAL;
00381           break;
00382         }
00383 
00384       if(rc)
00385         {
00386 
00387           LogEvent(COMPONENT_FSAL,
00388                             "Error in posix fseek operation (whence=%s, offset=%lld)",
00389                             (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00390                              (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00391                               (p_seek_descriptor->whence ==
00392                                FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00393                             (long long int)p_seek_descriptor->offset);
00394 
00395           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00396         }
00397 
00398     }
00399 
00400   /* read operation */
00401 
00402   TakeTokenFSCall();
00403 
00404   if(pcall)
00405     nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
00406   else
00407     nb_read = read(p_file_descriptor->fd, buffer, i_size);
00408   errsv = errno;
00409   ReleaseTokenFSCall();
00410 
00413   if(nb_read == -1)
00414     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00415   else if(nb_read == 0)
00416     *p_end_of_file = 1;
00417 
00418   *p_read_amount = nb_read;
00419 
00420   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00421 
00422 }
00423 
00447 fsal_status_t LUSTREFSAL_write(fsal_file_t *file_desc,   /* IN */
00448                                fsal_op_context_t * p_context,   /* IN */
00449                                fsal_seek_t * p_seek_descriptor, /* IN */
00450                                fsal_size_t buffer_size, /* IN */
00451                                caddr_t buffer,  /* IN */
00452                                fsal_size_t * p_write_amount     /* OUT */
00453     )
00454 {
00455 
00456   ssize_t nb_written;
00457   size_t i_size;
00458   int rc, errsv;
00459   int pcall = FALSE;
00460   lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)file_desc;
00461 
00462   /* sanity checks. */
00463   if(!p_file_descriptor || !buffer || !p_write_amount)
00464     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);
00465 
00466   if(p_file_descriptor->ro)
00467     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);
00468 
00470   i_size = (size_t) buffer_size;
00471 
00472   *p_write_amount = 0;
00473 
00474   /* positioning */
00475 
00476   if(p_seek_descriptor)
00477     {
00478 
00479       switch (p_seek_descriptor->whence)
00480         {
00481         case FSAL_SEEK_CUR:
00482           /* set position plus offset */
00483           pcall = FALSE;
00484 
00485           TakeTokenFSCall();
00486           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
00487           errsv = errno;
00488           ReleaseTokenFSCall();
00489           break;
00490 
00491         case FSAL_SEEK_SET:
00492           /* set absolute position to offset */
00493           pcall = TRUE;
00494           rc = 0;
00495           break;
00496 
00497         case FSAL_SEEK_END:
00498           /* set end of file plus offset */
00499           pcall = FALSE;
00500 
00501           TakeTokenFSCall();
00502           rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
00503           errsv = errno;
00504           ReleaseTokenFSCall();
00505 
00506           break;
00507 
00508         default:
00509           LogCrit(COMPONENT_FSAL, "Unexpected value for whence parameter");
00510           rc = -1;
00511           errsv = EINVAL;
00512           break;
00513         }
00514 
00515       if(rc)
00516         {
00517 
00518           LogEvent(COMPONENT_FSAL,
00519                             "Error in posix fseek operation (whence=%s, offset=%lld)",
00520                             (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00521                              (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00522                               (p_seek_descriptor->whence ==
00523                                FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00524                             (long long int)p_seek_descriptor->offset);
00525 
00526           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00527 
00528         }
00529 
00530       LogFullDebug(COMPONENT_FSAL,
00531                         "Write operation (whence=%s, offset=%lld, size=%lld)",
00532                         (p_seek_descriptor->whence ==
00533                          FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence ==
00534                                                        FSAL_SEEK_SET ? "SEEK_SET"
00535                                                        : (p_seek_descriptor->whence ==
00536                                                           FSAL_SEEK_END ? "SEEK_END" :
00537                                                           "ERROR"))),
00538                         (long long int)p_seek_descriptor->offset, (unsigned long long)buffer_size);
00539 
00540     }
00541 
00542   /* write operation */
00543 
00544   TakeTokenFSCall();
00545 
00546   if(pcall)
00547     nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
00548   else
00549     nb_written = write(p_file_descriptor->fd, buffer, i_size);
00550   errsv = errno;
00551 
00552   ReleaseTokenFSCall();
00553 
00555   if(nb_written <= 0)
00556     {
00557       LogDebug(COMPONENT_FSAL,
00558                "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.",
00559                (unsigned long long)i_size, (long long int)p_seek_descriptor->offset, 
00560                p_file_descriptor->fd, errsv);
00561       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00562     }
00563 
00564   /* set output vars */
00565 
00566   *p_write_amount = (fsal_size_t) nb_written;
00567 
00568   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00569 
00570 }
00571 
00584 fsal_status_t LUSTREFSAL_close(fsal_file_t * pfile_desc    /* IN */
00585     )
00586 {
00587 
00588   int rc, errsv;
00589   lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)pfile_desc;
00590 
00591   /* sanity checks. */
00592   if(!p_file_descriptor)
00593     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);
00594 
00595   /* avoid double close errors */ 
00596   if (((lustrefsal_file_t *)p_file_descriptor)->fd <= 0)
00597      Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00598 
00599   /* call to close */
00600   TakeTokenFSCall();
00601 
00602   rc = close(((lustrefsal_file_t *)p_file_descriptor)->fd);
00603   errsv = errno;
00604 
00605   ReleaseTokenFSCall();
00606 
00607   if(rc)
00608     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close);
00609 
00610   ((lustrefsal_file_t *)p_file_descriptor)->fd = -1;
00611 
00612   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00613 
00614 }
00615 
00616 unsigned int LUSTREFSAL_GetFileno(fsal_file_t * pfile)
00617 {
00618         return ((lustrefsal_file_t *)pfile)->fd;
00619 }
00620 
00621 
00622 
00640 fsal_status_t LUSTREFSAL_commit( fsal_file_t * pfile_desc, 
00641                                fsal_off_t    offset, 
00642                                fsal_size_t   length )
00643 {
00644   int rc, errsv;
00645   lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)pfile_desc;
00646 
00647   /* sanity checks. */
00648   if(!p_file_descriptor)
00649     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit);
00650 
00651   if (((lustrefsal_file_t *)p_file_descriptor)->fd <= 0)
00652   {
00653      LogWarn(COMPONENT_FSAL, "sync on closed fd");
00654      Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00655   }
00656 
00657   /* Flush data. */
00658   TakeTokenFSCall();
00659   rc = fsync(((lustrefsal_file_t *)p_file_descriptor)->fd);
00660   errsv = errno;
00661   ReleaseTokenFSCall();
00662   
00663   if(rc)
00664   {
00665     LogEvent(COMPONENT_FSAL, "Error in fsync operation");
00666     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit);
00667   }
00668 
00669   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00670 }