nfs-ganesha 1.4

fsal_rcp.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright (C) 2010 The Linux Box, Inc.
00005  * Contributor : Adam C. Emerson <aemerson@linuxbox.com>
00006  *
00007  * Portions copyright CEA/DAM/DIF  (2008)
00008  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00009  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00010  *
00011  *
00012  * This program is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 3 of the License, or (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with this library; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00025  *
00026  * ------------- 
00027  */
00028 
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif
00038 
00039 #include "fsal.h"
00040 #include "fsal_internal.h"
00041 #include "fsal_convert.h"
00042 
00043 #include <sys/types.h>
00044 #include <sys/stat.h>
00045 #include <fcntl.h>
00046 
00080 fsal_status_t CEPHFSAL_rcp(fsal_handle_t * filehandle,
00081                            fsal_op_context_t * p_context,
00082                            fsal_path_t * p_local_path,
00083                            fsal_rcpflag_t transfer_opt)
00084 {
00085   int local_fd;
00086   int local_flags;
00087 
00088   fsal_file_t fs_fd;
00089   fsal_openflags_t fs_flags;
00090 
00091   fsal_status_t st = FSAL_STATUS_NO_ERROR;
00092 
00093 /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00094  * This is a template implementation of rcp based on FSAL_read and FSAL_write
00095  * function. You may chose keeping it or doing your own implementation
00096  * that is optimal for your filesystems.
00097  * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00098  */
00099 
00100   /* default buffer size for RCP: 1MB */
00101 #define RCP_BUFFER_SIZE 1048576
00102   caddr_t IObuffer;
00103 
00104   int to_local = FALSE;
00105   int to_fs = FALSE;
00106 
00107   int eof = FALSE;
00108 
00109   ssize_t local_size = 0;
00110   fsal_size_t fs_size = 0;
00111 
00112   /* sanity checks. */
00113 
00114   if(!filehandle || !p_context || !p_local_path)
00115     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp);
00116 
00117   to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL);
00118   to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS);
00119 
00120 #ifdef  _DEBUG_FSAL
00121   if(to_local)
00122     DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG,
00123                       "FSAL_rcp: FSAL -> local file (%s)", p_local_path->path);
00124 
00125   if(to_fs)
00126     DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG,
00127                       "FSAL_rcp: local file -> FSAL (%s)", p_local_path->path);
00128 #endif
00129 
00130   /* must give the sens of transfert (exactly one) */
00131 
00132   if((!to_local && !to_fs) || (to_local && to_fs))
00133     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
00134 
00135   /* first, open local file with the correct flags */
00136 
00137   if(to_fs)
00138     {
00139       local_flags = O_RDONLY;
00140     }
00141   else
00142     {
00143       local_flags = O_WRONLY | O_TRUNC;
00144 
00145       if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
00146         local_flags |= O_CREAT;
00147 
00148       if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)
00149         local_flags |= O_EXCL;
00150 
00151     }
00152 
00153 #ifdef  _DEBUG_FSAL
00154   {
00155 
00156     char msg[1024];
00157 
00158     msg[0] = '\0';
00159 
00160     if((local_flags & O_RDONLY) == O_RDONLY)
00161       strcat(msg, "O_RDONLY ");
00162 
00163     if((local_flags & O_WRONLY) == O_WRONLY)
00164       strcat(msg, "O_WRONLY ");
00165 
00166     if((local_flags & O_TRUNC) == O_TRUNC)
00167       strcat(msg, "O_TRUNC ");
00168 
00169     if((local_flags & O_CREAT) == O_CREAT)
00170       strcat(msg, "O_CREAT ");
00171 
00172     if((local_flags & O_EXCL) == O_EXCL)
00173       strcat(msg, "O_EXCL ");
00174 
00175     DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG, "Openning local file %s with flags: %s",
00176                       p_local_path->path, msg);
00177 
00178   }
00179 #endif
00180 
00181   local_fd = open(p_local_path->path, local_flags, 0644);
00182 
00183   if(local_fd == -1)
00184     {
00185       /* todo : put a function in fsal_convert.c that convert your local
00186        * filesystem errors to an FSAL error code.
00187        * So you will have a call like :
00188        * Return( unix2fsal_error(errno) , errno , INDEX_FSAL_rcp );
00189        */
00190     }
00191 
00192   /* call FSAL_open with the correct flags */
00193 
00194   if(to_fs)
00195     {
00196       fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC;
00197 
00198       /* invalid flags for local to filesystem */
00199 
00200       if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
00201          || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL))
00202         {
00203           /* clean & return */
00204           close(local_fd);
00205           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
00206         }
00207     }
00208   else
00209     {
00210       fs_flags = FSAL_O_RDONLY;
00211     }
00212 
00213 #ifdef  _DEBUG_FSAL
00214   {
00215 
00216     char msg[1024];
00217 
00218     msg[0] = '\0';
00219 
00220     if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY)
00221       strcat(msg, "FSAL_O_RDONLY ");
00222 
00223     if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY)
00224       strcat(msg, "FSAL_O_WRONLY ");
00225 
00226     if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC)
00227       strcat(msg, "FSAL_O_TRUNC ");
00228 
00229     DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG, "Openning FSAL file with flags: %s", msg);
00230 
00231   }
00232 #endif
00233 
00234   st = CEPHFSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL);
00235 
00236   if(FSAL_IS_ERROR(st))
00237     {
00238       /* clean & return */
00239       close(local_fd);
00240       Return(st.major, st.minor, INDEX_FSAL_rcp);
00241     }
00242 #ifdef  _DEBUG_FSAL
00243   DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG,
00244                     "Allocating IO buffer of size %llu",
00245                     (unsigned long long)RCP_BUFFER_SIZE);
00246 #endif
00247 
00248   /* Allocates buffer */
00249 
00250   IObuffer = gsh_malloc(RCP_BUFFER_SIZE);
00251 
00252   if(IObuffer == NULL)
00253     {
00254       /* clean & return */
00255       close(local_fd);
00256       CEPHFSAL_close(&fs_fd);
00257       Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp);
00258     }
00259 
00260   /* read/write loop */
00261 
00262   while(!eof)
00263     {
00264       /* initialize error code */
00265       st = FSAL_STATUS_NO_ERROR;
00266 
00267 #ifdef  _DEBUG_FSAL
00268       DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG, "Read a block from source");
00269 #endif
00270 
00271       /* read */
00272 
00273       if(to_fs)                 /* from local filesystem */
00274         {
00275           local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE);
00276 
00277           if(local_size == -1)
00278             {
00279               st.major = ERR_FSAL_IO;
00280               st.minor = errno;
00281               break;            /* exit loop */
00282             }
00283 
00284           eof = (local_size == 0);
00285 
00286         }
00287       else                      /* from FSAL filesystem */
00288         {
00289           st=CEPHFSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof);
00290 
00291           if(FSAL_IS_ERROR(st))
00292             break;              /* exit loop */
00293 
00294         }
00295 
00296       /* write (if not eof) */
00297 
00298       if(!eof)
00299         {
00300 
00301 #ifdef  _DEBUG_FSAL
00302           DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG, "Write a block to destination");
00303 #endif
00304 
00305           if(to_fs)             /* to FSAL filesystem */
00306             {
00307 
00308               st = CEPHFSAL_write(&fs_fd, p_context, NULL, local_size, IObuffer, &fs_size);
00309 
00310               if(FSAL_IS_ERROR(st))
00311                 break;          /* exit loop */
00312 
00313             }
00314           else                  /* to local filesystem */
00315             {
00316 
00317               local_size = write(local_fd, IObuffer, fs_size);
00318 
00319               if(local_size == -1)
00320                 {
00321                   st.major = ERR_FSAL_IO;
00322                   st.minor = errno;
00323                   break;        /* exit loop */
00324                 }
00325 
00326             }                   /* if to_fs */
00327 
00328         }                       /* if eof */
00329 #ifdef  _DEBUG_FSAL
00330       else
00331         DisplayLogJdLevel(fsal_log, NIV_FULL_DEBUG, "End of source file reached");
00332 #endif
00333 
00334     }                           /* while !eof */
00335 
00336   /* Clean */
00337 
00338   gsh_free(IObuffer);
00339   close(local_fd);
00340   CEPHFSAL_close(&fs_fd);
00341 
00342   /* return status. */
00343 
00344   Return(st.major, st.minor, INDEX_FSAL_rcp);
00345 
00346 }