nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 3 of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 * ------------- 00024 */ 00025 00034 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif 00037 00038 #include "fsal.h" 00039 #include "fsal_internal.h" 00040 #include "FSAL/access_check.h" 00041 #include "fsal_convert.h" 00042 00082 fsal_status_t VFSFSAL_open_by_name(fsal_handle_t * dirhandle, /* IN */ 00083 fsal_name_t * filename, /* IN */ 00084 fsal_op_context_t * p_context, /* IN */ 00085 fsal_openflags_t openflags, /* IN */ 00086 fsal_file_t * file_descriptor, /* OUT */ 00087 fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ ) 00088 { 00089 fsal_status_t fsal_status; 00090 fsal_handle_t filehandle; 00091 00092 if(!dirhandle || !filename || !p_context || !file_descriptor) 00093 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name); 00094 00095 fsal_status = FSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes); 00096 if(FSAL_IS_ERROR(fsal_status)) 00097 return fsal_status; 00098 00099 return FSAL_open(&filehandle, p_context, openflags, file_descriptor, file_attributes); 00100 } 00101 00132 fsal_status_t VFSFSAL_open(fsal_handle_t * p_filehandle, /* IN */ 00133 fsal_op_context_t * p_context, /* IN */ 00134 fsal_openflags_t openflags, /* IN */ 00135 fsal_file_t * p_file_descriptor, /* OUT */ 00136 fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ 00137 ) 00138 { 00139 00140 int rc, errsv; 00141 fsal_status_t status; 00142 00143 int fd; 00144 struct stat buffstat; 00145 int posix_flags = 0; 00146 00147 /* sanity checks. 00148 * note : file_attributes is optional. 00149 */ 00150 if(!p_filehandle || !p_context || !p_file_descriptor) 00151 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); 00152 00153 /* convert fsal open flags to posix open flags */ 00154 rc = fsal2posix_openflags(openflags, &posix_flags); 00155 00156 /* flags conflicts. */ 00157 if(rc) 00158 { 00159 LogWarn(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); 00160 Return(rc, 0, INDEX_FSAL_open); 00161 } 00162 00163 TakeTokenFSCall(); 00164 status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags); 00165 ReleaseTokenFSCall(); 00166 00167 if(FSAL_IS_ERROR(status)) 00168 ReturnStatus(status, INDEX_FSAL_open); 00169 00170 /* retrieve file attributes for checking access rights */ 00171 00172 TakeTokenFSCall(); 00173 rc = fstat(fd, &buffstat); 00174 errsv = errno; 00175 ReleaseTokenFSCall(); 00176 00177 if(rc) 00178 { 00179 close(fd); 00180 00181 if(errsv == ENOENT) 00182 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open); 00183 else 00184 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); 00185 } 00186 00187 status = 00188 fsal_check_access(p_context, 00189 (openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK) | 00190 FSAL_OWNER_OK, &buffstat, NULL); 00191 if(FSAL_IS_ERROR(status)) 00192 { 00193 close(fd); 00194 ReturnStatus(status, INDEX_FSAL_open); 00195 } 00196 00197 TakeTokenFSCall(); 00198 ((vfsfsal_file_t *)p_file_descriptor)->fd = fd; 00199 errsv = errno; 00200 ReleaseTokenFSCall(); 00201 00202 /* set the read-only flag of the file descriptor */ 00203 ((vfsfsal_file_t *)p_file_descriptor)->ro = openflags & FSAL_O_RDONLY; 00204 00205 /* output attributes */ 00206 if(p_file_attributes) 00207 { 00208 00209 status = posix2fsal_attributes(&buffstat, p_file_attributes); 00210 00211 if(FSAL_IS_ERROR(status)) 00212 { 00213 FSAL_CLEAR_MASK(p_file_attributes->asked_attributes); 00214 FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00215 } 00216 } 00217 00218 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); 00219 00220 } 00221 00246 fsal_status_t VFSFSAL_read(fsal_file_t * file_desc, /* IN */ 00247 fsal_seek_t * p_seek_descriptor, /* [IN] */ 00248 fsal_size_t buffer_size, /* IN */ 00249 caddr_t buffer, /* OUT */ 00250 fsal_size_t * p_read_amount, /* OUT */ 00251 fsal_boolean_t * p_end_of_file /* OUT */ 00252 ) 00253 { 00254 vfsfsal_file_t * p_file_descriptor = (vfsfsal_file_t *) file_desc; 00255 size_t i_size; 00256 ssize_t nb_read; 00257 int rc = 0, errsv = 0; 00258 int pcall = FALSE; 00259 00260 /* sanity checks. */ 00261 00262 if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file) 00263 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); 00264 00266 i_size = (size_t) buffer_size; 00267 00268 /* positioning */ 00269 00270 if(p_seek_descriptor) 00271 { 00272 switch (p_seek_descriptor->whence) 00273 { 00274 case FSAL_SEEK_CUR: 00275 /* set position plus offset */ 00276 pcall = FALSE; 00277 TakeTokenFSCall(); 00278 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); 00279 errsv = errno; 00280 ReleaseTokenFSCall(); 00281 break; 00282 00283 case FSAL_SEEK_SET: 00284 /* use pread/pwrite call */ 00285 pcall = TRUE; 00286 rc = 0; 00287 errsv = 0; 00288 break; 00289 00290 case FSAL_SEEK_END: 00291 /* set end of file plus offset */ 00292 pcall = FALSE; 00293 00294 TakeTokenFSCall(); 00295 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); 00296 errsv = errno; 00297 ReleaseTokenFSCall(); 00298 break; 00299 } 00300 00301 if(rc) 00302 { 00303 LogFullDebug(COMPONENT_FSAL, 00304 "Error in posix fseek operation (whence=%s, offset=%lld)", 00305 (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : 00306 (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : 00307 (p_seek_descriptor->whence == 00308 FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), 00309 (long long) p_seek_descriptor->offset); 00310 00311 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); 00312 } 00313 00314 } 00315 00316 /* read operation */ 00317 00318 TakeTokenFSCall(); 00319 00320 if(pcall) 00321 nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); 00322 else 00323 nb_read = read(p_file_descriptor->fd, buffer, i_size); 00324 errsv = errno; 00325 ReleaseTokenFSCall(); 00326 00329 if(nb_read == -1) 00330 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); 00331 else if(nb_read == 0) 00332 *p_end_of_file = 1; 00333 00334 *p_read_amount = nb_read; 00335 00336 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); 00337 00338 } 00339 00363 fsal_status_t VFSFSAL_write(fsal_file_t * file_desc, /* IN */ 00364 fsal_op_context_t * p_context, /* IN */ 00365 fsal_seek_t * p_seek_descriptor, /* IN */ 00366 fsal_size_t buffer_size, /* IN */ 00367 caddr_t buffer, /* IN */ 00368 fsal_size_t * p_write_amount /* OUT */ 00369 ) 00370 { 00371 vfsfsal_file_t * p_file_descriptor = (vfsfsal_file_t *) file_desc; 00372 ssize_t nb_written; 00373 size_t i_size; 00374 int rc = 0, errsv = 0; 00375 int pcall = FALSE; 00376 00377 /* sanity checks. */ 00378 if(!p_file_descriptor || !buffer || !p_write_amount) 00379 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); 00380 00381 if(p_file_descriptor->ro) 00382 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write); 00383 00385 i_size = (size_t) buffer_size; 00386 00387 *p_write_amount = 0; 00388 00389 /* positioning */ 00390 00391 if(p_seek_descriptor) 00392 { 00393 00394 switch (p_seek_descriptor->whence) 00395 { 00396 case FSAL_SEEK_CUR: 00397 /* set position plus offset */ 00398 pcall = FALSE; 00399 00400 TakeTokenFSCall(); 00401 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); 00402 errsv = errno; 00403 ReleaseTokenFSCall(); 00404 break; 00405 00406 case FSAL_SEEK_SET: 00407 /* set absolute position to offset */ 00408 pcall = TRUE; 00409 rc = 0; 00410 errsv = 0; 00411 break; 00412 00413 case FSAL_SEEK_END: 00414 /* set end of file plus offset */ 00415 pcall = FALSE; 00416 00417 TakeTokenFSCall(); 00418 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); 00419 errsv = errno; 00420 ReleaseTokenFSCall(); 00421 break; 00422 } 00423 00424 if(rc) 00425 { 00426 LogFullDebug(COMPONENT_FSAL, 00427 "Error in posix fseek operation (whence=%s, offset=%lld)", 00428 (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : 00429 (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : 00430 (p_seek_descriptor->whence == 00431 FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), 00432 (long long) p_seek_descriptor->offset); 00433 00434 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); 00435 00436 } 00437 00438 LogFullDebug(COMPONENT_FSAL, 00439 "Write operation (whence=%s, offset=%lld, size=%zd)", 00440 (p_seek_descriptor->whence == 00441 FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence == 00442 FSAL_SEEK_SET ? "SEEK_SET" 00443 : (p_seek_descriptor->whence == 00444 FSAL_SEEK_END ? "SEEK_END" : 00445 "ERROR"))), 00446 (long long) p_seek_descriptor->offset, buffer_size); 00447 00448 } 00449 00450 /* write operation */ 00451 00452 TakeTokenFSCall(); 00453 00454 if(pcall) 00455 nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); 00456 else 00457 nb_written = write(p_file_descriptor->fd, buffer, i_size); 00458 errsv = errno; 00459 00460 ReleaseTokenFSCall(); 00461 00463 if(nb_written <= 0) 00464 { 00465 if (p_seek_descriptor) 00466 LogDebug(COMPONENT_FSAL, 00467 "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.", 00468 (unsigned long long) i_size, 00469 (long long) p_seek_descriptor->offset, 00470 p_file_descriptor->fd, 00471 errsv); 00472 else 00473 LogDebug(COMPONENT_FSAL, 00474 "Write operation of size %llu at offset 0. fd=%d, errno=%d.", 00475 (unsigned long long) i_size, 00476 p_file_descriptor->fd, 00477 errsv); 00478 00479 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); 00480 } 00481 00482 /* set output vars */ 00483 00484 *p_write_amount = (fsal_size_t) nb_written; 00485 00486 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); 00487 00488 } 00489 00502 fsal_status_t VFSFSAL_close(fsal_file_t * p_file_descriptor /* IN */ 00503 ) 00504 { 00505 00506 int rc, errsv; 00507 00508 /* sanity checks. */ 00509 if(!p_file_descriptor) 00510 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); 00511 00512 if(((vfsfsal_file_t *)p_file_descriptor)->fd == 0 ) 00513 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00514 00515 /* call to close */ 00516 TakeTokenFSCall(); 00517 00518 rc = close(((vfsfsal_file_t *)p_file_descriptor)->fd); 00519 errsv = errno; 00520 00521 ReleaseTokenFSCall(); 00522 00523 if(rc) 00524 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close); 00525 00526 ((vfsfsal_file_t *)p_file_descriptor)->fd = 0 ; 00527 00528 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00529 00530 } 00531 00532 unsigned int VFSFSAL_GetFileno(fsal_file_t * pfile) 00533 { 00534 return ((vfsfsal_file_t *)pfile)->fd; 00535 } 00536 00554 fsal_status_t VFSFSAL_commit(fsal_file_t * p_file_descriptor, 00555 fsal_off_t offset, 00556 fsal_size_t length ) 00557 { 00558 int rc, errsv; 00559 00560 /* sanity checks. */ 00561 if(!p_file_descriptor) 00562 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit); 00563 00564 if(((vfsfsal_file_t *)p_file_descriptor)->fd == 0 ) 00565 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); /* Nothing to sync, the fd is not opened */ 00566 00567 /* Flush data. */ 00568 TakeTokenFSCall(); 00569 rc = fsync(((vfsfsal_file_t *)p_file_descriptor)->fd); 00570 errsv = errno; 00571 ReleaseTokenFSCall(); 00572 00573 00574 if(rc) 00575 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit); 00576 00577 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); 00578 }