nfs-ganesha 1.4

fsal_rcp.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
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 #include "abstract_mem.h"
00022 
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <fcntl.h>
00026 #include <string.h>
00027 
00061 fsal_status_t ZFSFSAL_rcp(fsal_handle_t * filehandle,      /* IN */
00062                        fsal_op_context_t * p_context,   /* IN */
00063                        fsal_path_t * p_local_path,      /* IN */
00064                        fsal_rcpflag_t transfer_opt      /* IN */
00065     )
00066 {
00067 
00068   int local_fd;
00069   int local_flags;
00070   int errsv;
00071 
00072   zfsfsal_file_t fs_fd;
00073   fsal_openflags_t fs_flags;
00074 
00075   fsal_status_t st = FSAL_STATUS_NO_ERROR;
00076 
00077 /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00078  * This is a template implementation of rcp based on FSAL_read and FSAL_write
00079  * function. You may chose keeping it or doing your own implementation
00080  * that is optimal for your filesystems.
00081  * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00082  */
00083 
00084   /* default buffer size for RCP: 1MB */
00085 #define RCP_BUFFER_SIZE 1048576
00086   caddr_t IObuffer;
00087 
00088   int to_local = FALSE;
00089   int to_fs = FALSE;
00090 
00091   int eof = FALSE;
00092 
00093   ssize_t local_size;
00094   fsal_size_t fs_size;
00095 
00096   /* sanity checks. */
00097 
00098   if(!filehandle || !p_context || !p_local_path)
00099     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp);
00100 
00101   to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL);
00102   to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS);
00103 
00104   if(to_local)
00105     LogFullDebug(COMPONENT_FSAL,
00106                       "FSAL_rcp: FSAL -> local file (%s)", p_local_path->path);
00107 
00108   if(to_fs)
00109     LogFullDebug(COMPONENT_FSAL,
00110                       "FSAL_rcp: local file -> FSAL (%s)", p_local_path->path);
00111 
00112   /* must give the sens of transfert (exactly one) */
00113 
00114   if((!to_local && !to_fs) || (to_local && to_fs))
00115     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
00116 
00117   /* first, open local file with the correct flags */
00118 
00119   if(to_fs)
00120     {
00121       local_flags = O_RDONLY;
00122     }
00123   else
00124     {
00125       local_flags = O_WRONLY | O_TRUNC;
00126 
00127       if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
00128         local_flags |= O_CREAT;
00129 
00130       if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)
00131         local_flags |= O_EXCL;
00132 
00133     }
00134 
00135   if (isFullDebug(COMPONENT_FSAL))
00136   {
00137 
00138     char msg[1024];
00139 
00140     msg[0] = '\0';
00141 
00142     if((local_flags & O_RDONLY) == O_RDONLY)
00143       strcat(msg, "O_RDONLY ");
00144 
00145     if((local_flags & O_WRONLY) == O_WRONLY)
00146       strcat(msg, "O_WRONLY ");
00147 
00148     if((local_flags & O_TRUNC) == O_TRUNC)
00149       strcat(msg, "O_TRUNC ");
00150 
00151     if((local_flags & O_CREAT) == O_CREAT)
00152       strcat(msg, "O_CREAT ");
00153 
00154     if((local_flags & O_EXCL) == O_EXCL)
00155       strcat(msg, "O_EXCL ");
00156 
00157     LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s",
00158                       p_local_path->path, msg);
00159 
00160   }
00161 
00162   local_fd = open(p_local_path->path, local_flags);
00163   errsv = errno;
00164 
00165   if(local_fd == -1)
00166     {
00167       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rcp);
00168     }
00169 
00170   /* call FSAL_open with the correct flags */
00171 
00172   if(to_fs)
00173     {
00174       fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC;
00175 
00176       /* invalid flags for local to filesystem */
00177 
00178       if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
00179          || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL))
00180         {
00181           /* clean & return */
00182           close(local_fd);
00183           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
00184         }
00185     }
00186   else
00187     {
00188       fs_flags = FSAL_O_RDONLY;
00189     }
00190 
00191   if (isFullDebug(COMPONENT_FSAL))
00192   {
00193 
00194     char msg[1024];
00195 
00196     msg[0] = '\0';
00197 
00198     if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY)
00199       strcat(msg, "FSAL_O_RDONLY ");
00200 
00201     if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY)
00202       strcat(msg, "FSAL_O_WRONLY ");
00203 
00204     if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC)
00205       strcat(msg, "FSAL_O_TRUNC ");
00206 
00207     LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg);
00208 
00209   }
00210 
00211 
00212   st = ZFSFSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL);
00213 
00214   if(FSAL_IS_ERROR(st))
00215     {
00216       /* clean & return */
00217       close(local_fd);
00218       Return(st.major, st.minor, INDEX_FSAL_rcp);
00219     }
00220 
00221   LogFullDebug(COMPONENT_FSAL,
00222                     "Allocating IO buffer of size %llu",
00223                     (unsigned long long)RCP_BUFFER_SIZE);
00224 
00225 
00226   /* Allocates buffer */
00227 
00228   IObuffer = gsh_malloc(RCP_BUFFER_SIZE);
00229 
00230   if(IObuffer == NULL)
00231     {
00232       /* clean & return */
00233       close(local_fd);
00234       ZFSFSAL_close(&fs_fd);
00235       Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp);
00236     }
00237 
00238   /* read/write loop */
00239 
00240   while(!eof)
00241     {
00242       /* initialize error code */
00243       st = FSAL_STATUS_NO_ERROR;
00244 
00245       LogFullDebug(COMPONENT_FSAL, "Read a block from source");
00246 
00247       /* read */
00248 
00249       if(to_fs)                 /* from local filesystem */
00250         {
00251           local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE);
00252 
00253           if(local_size == -1)
00254             {
00255               st.major = ERR_FSAL_IO;
00256               st.minor = errno;
00257               break;            /* exit loop */
00258             }
00259 
00260           eof = (local_size == 0);
00261 
00262         }
00263       else                      /* from FSAL filesystem */
00264         {
00265           fs_size = 0;
00266           st = ZFSFSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof);
00267 
00268           if(FSAL_IS_ERROR(st))
00269             break;              /* exit loop */
00270 
00271         }
00272 
00273       /* write (if not eof) */
00274 
00275       if(!eof || ((!to_fs) && (fs_size > 0)))
00276         {
00277 
00278           LogFullDebug(COMPONENT_FSAL, "Write a block to destination");
00279 
00280           if(to_fs)             /* to FSAL filesystem */
00281             {
00282 
00283               st = ZFSFSAL_write(&fs_fd, p_context, NULL, local_size, IObuffer, &fs_size);
00284 
00285               if(FSAL_IS_ERROR(st))
00286                 break;          /* exit loop */
00287 
00288             }
00289           else                  /* to local filesystem */
00290             {
00291 
00292               local_size = write(local_fd, IObuffer, fs_size);
00293 
00294               if(local_size == -1)
00295                 {
00296                   st.major = ERR_FSAL_IO;
00297                   st.minor = errno;
00298                   break;        /* exit loop */
00299                 }
00300 
00301             }                   /* if to_fs */
00302 
00303         }                       /* if eof */
00304       else
00305         LogFullDebug(COMPONENT_FSAL, "End of source file reached");
00306 
00307     }                           /* while !eof */
00308 
00309   /* Clean */
00310 
00311   gsh_free(IObuffer);
00312   close(local_fd);
00313   ZFSFSAL_close(&fs_fd);
00314 
00315   /* return status. */
00316 
00317   Return(st.major, st.minor, INDEX_FSAL_rcp);
00318 
00319 }