nfs-ganesha 1.4

fsal_truncate.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #include "fsal.h"
00019 #include "fsal_internal.h"
00020 #include "fsal_convert.h"
00021 
00022 #include <unistd.h>
00023 #include <sys/types.h>
00024 
00025 #ifdef _SHOOK
00026 #include "shook_svr.h"
00027 #endif
00028 
00052 fsal_status_t LUSTREFSAL_truncate(fsal_handle_t * p_filehandle,   /* IN */
00053                                   fsal_op_context_t * p_context,  /* IN */
00054                                   fsal_size_t length,   /* IN */
00055                                   fsal_file_t * file_descriptor,        /* Unused in this FSAL */
00056                                   fsal_attrib_list_t * p_object_attributes      /* [ IN/OUT ] */
00057     )
00058 {
00059 
00060   int rc, errsv;
00061   fsal_path_t fsalpath;
00062   fsal_status_t st;
00063   int no_trunc = 0;
00064 
00065   /* sanity checks.
00066    * note : object_attributes is optional.
00067    */
00068   if(!p_filehandle || !p_context)
00069     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate);
00070 
00071   /* get the path of the file and its handle */
00072   st = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath);
00073   if(FSAL_IS_ERROR(st))
00074     ReturnStatus(st, INDEX_FSAL_truncate);
00075 
00076 #ifdef _SHOOK
00077     /* If the file is not online:
00078      * - if truncate(0) => call tuncate(0), then "shook restore_trunc"
00079      * - if truncate(>0) => call "shook restore", then truncate
00080      */
00081     shook_state state;
00082     rc = shook_get_status(fsalpath.path, &state, FALSE);
00083     if (rc)
00084     {
00085         LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s",
00086                  fsalpath.path, strerror(-rc));
00087         if (rc)
00088             Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate);
00089     }
00090     else if (state != SS_ONLINE)
00091     {
00092         if (length == 0)
00093         {
00094             LogInfo(COMPONENT_FSAL, "File is offline: calling shook restore_trunc");
00095 
00096             /* first truncate the file, them call the shook_svr to clear
00097              * the 'released' flag */
00098 
00099             TakeTokenFSCall();
00100             rc = truncate(fsalpath.path, 0);
00101             errsv = errno;
00102             ReleaseTokenFSCall();
00103 
00104             if (rc == 0)
00105             {
00106                 /* use a short timeout of 2s */
00107                 rc = shook_server_call(SA_RESTORE_TRUNC, ((lustrefsal_op_context_t *)p_context)->export_context->fsname,
00108                                        &((lustrefsal_handle_t *)p_filehandle)->data.fid, 2);
00109                 if (rc)
00110                     Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate);
00111                 else {
00112                     /* check that file is online, else operation is still
00113                      * in progress: return err jukebox */
00114                     rc = shook_get_status(fsalpath.path, &state, FALSE);
00115                     if (rc)
00116                     {
00117                         LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s",
00118                                  fsalpath.path, strerror(-rc));
00119                         if (rc)
00120                             Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate);
00121                     }
00122                     else if (state != SS_ONLINE)
00123                         Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_truncate);
00124                     /* OK */
00125                 }
00126                 /* file is already truncated, no need to truncate again */
00127                 no_trunc = 1;
00128             }
00129             else
00130             {
00131                   if(errsv == ENOENT)
00132                     Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_truncate);
00133                   else
00134                     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_truncate);
00135             }
00136         }
00137         else /* length > 0 */
00138         {
00139             /* trigger restore. Give it a chance to retrieve the file in less than a second.
00140              * Else, it returns ETIME that is converted in ERR_DELAY */
00141             rc = shook_server_call(SA_RESTORE, ((lustrefsal_op_context_t *)p_context)->export_context->fsname,
00142                                    &((lustrefsal_handle_t *)p_filehandle)->data.fid, 1);
00143             if (rc)
00144                 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate);
00145             else {
00146                 /* check that file is online, else operation is still
00147                  * in progress: return err jukebox */
00148                 rc = shook_get_status(fsalpath.path, &state, FALSE);
00149                 if (rc)
00150                 {
00151                     LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s",
00152                              fsalpath.path, strerror(-rc));
00153                     if (rc)
00154                         Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_truncate);
00155                 }
00156                 else if (state != SS_ONLINE)
00157                     Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_truncate);
00158                 /* OK */
00159             }
00160 
00161             /* if rc = 0, file can be opened */
00162         }
00163     }
00164     /* else file is on line */
00165 #endif
00166 
00167   /* Executes the POSIX truncate operation */
00168 
00169   if (!no_trunc)
00170   {
00171     TakeTokenFSCall();
00172     rc = truncate(fsalpath.path, length);
00173     errsv = errno;
00174     ReleaseTokenFSCall();
00175   }
00176 
00177   /* convert return code */
00178   if(rc)
00179     {
00180       if(errsv == ENOENT)
00181         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_truncate);
00182       else
00183         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_truncate);
00184     }
00185 
00186   /* Optionally retrieve attributes */
00187   if(p_object_attributes)
00188     {
00189 
00190       fsal_status_t st;
00191 
00192       st = LUSTREFSAL_getattrs(p_filehandle, p_context, p_object_attributes);
00193 
00194       if(FSAL_IS_ERROR(st))
00195         {
00196           FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00197           FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00198         }
00199 
00200     }
00201 
00202   /* No error occurred */
00203   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate);
00204 
00205 }