nfs-ganesha 1.4
|
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 }