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