nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00013 #ifdef HAVE_CONFIG_H 00014 #include "config.h" 00015 #endif 00016 00017 #include "fsal.h" 00018 #include "fsal_internal.h" 00019 #include "fsal_convert.h" 00020 #include "namespace.h" 00021 #include <string.h> 00022 00059 fsal_status_t FUSEFSAL_open(fsal_handle_t * file_hdl, /* IN */ 00060 fsal_op_context_t * p_context, /* IN */ 00061 fsal_openflags_t openflags, /* IN */ 00062 fsal_file_t * file_desc, /* OUT */ 00063 fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ 00064 ) 00065 { 00066 00067 int rc = 0; 00068 char object_path[FSAL_MAX_PATH_LEN]; 00069 int file_info_provided = FALSE; 00070 fusefsal_handle_t * filehandle = (fusefsal_handle_t *)file_hdl; 00071 fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc; 00072 00073 /* sanity checks. 00074 * note : file_attributes is optional. 00075 */ 00076 if(!filehandle || !p_context || !file_descriptor) 00077 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); 00078 00079 /* get the full path for this file */ 00080 rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator, 00081 object_path); 00082 if(rc) 00083 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_open); 00084 00085 memset(file_descriptor, 0, sizeof(fusefsal_file_t)); 00086 00087 /* set access mode flags */ 00088 00089 file_descriptor->file_info.flags = 0; 00090 00091 if(openflags & FSAL_O_RDONLY) 00092 file_descriptor->file_info.flags |= O_RDONLY; 00093 if(openflags & FSAL_O_WRONLY) 00094 file_descriptor->file_info.flags |= O_WRONLY; 00095 if(openflags & FSAL_O_RDWR) 00096 file_descriptor->file_info.flags |= O_RDWR; 00097 00098 /* set context for the next operation, so it can be retrieved by FS thread */ 00099 fsal_set_thread_context(p_context); 00100 00101 /* check open call */ 00102 00103 if(p_fs_ops->open) 00104 { 00105 LogFullDebug(COMPONENT_FSAL, "Call to open( %s, %#X )", object_path, file_descriptor->file_info.flags); 00106 00107 TakeTokenFSCall(); 00108 rc = p_fs_ops->open(object_path, &(file_descriptor->file_info)); 00109 ReleaseTokenFSCall(); 00110 00111 if(rc) 00112 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); 00113 00114 file_info_provided = TRUE; 00115 00116 } 00117 else 00118 { 00119 LogFullDebug(COMPONENT_FSAL, "no open command provided"); 00120 00121 /* ignoring open */ 00122 memset(&(file_descriptor->file_info), 0, sizeof(struct ganefuse_file_info)); 00123 } 00124 00125 /* check open flags (only FSAL_O_TRUNC and FSAL_O_APPEND are used for FUSE filesystems) */ 00126 00127 if(openflags & FSAL_O_TRUNC) 00128 { 00129 if(file_info_provided && p_fs_ops->ftruncate) 00130 { 00131 LogFullDebug(COMPONENT_FSAL, "call to ftruncate on file since FSAL_O_TRUNC was set"); 00132 00133 /* ftruncate the file */ 00134 TakeTokenFSCall(); 00135 rc = p_fs_ops->ftruncate(object_path, 0, &(file_descriptor->file_info)); 00136 ReleaseTokenFSCall(); 00137 00138 if(rc) 00139 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); 00140 } 00141 else if(p_fs_ops->truncate) 00142 { 00143 LogFullDebug(COMPONENT_FSAL, "call to truncate on file since FSAL_O_TRUNC was set"); 00144 00145 /* truncate the file */ 00146 TakeTokenFSCall(); 00147 rc = p_fs_ops->truncate(object_path, 0); 00148 ReleaseTokenFSCall(); 00149 00150 if(rc) 00151 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); 00152 } 00153 /* else: ignoring flag */ 00154 } 00155 00156 if(openflags & FSAL_O_APPEND) 00157 { 00158 struct stat stbuf; 00159 00160 /* In this case, this only solution is to get file attributes */ 00161 00162 if(file_info_provided && p_fs_ops->fgetattr) 00163 { 00164 rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info)); 00165 } 00166 else 00167 { 00168 rc = p_fs_ops->getattr(object_path, &stbuf); 00169 } 00170 00171 if(rc) 00172 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open); 00173 00174 file_descriptor->current_offset = stbuf.st_size; 00175 } 00176 else 00177 { 00178 file_descriptor->current_offset = 0; 00179 } 00180 00181 /* fill the file descriptor structure */ 00182 file_descriptor->file_handle = *filehandle; 00183 00184 /* backup context */ 00185 file_descriptor->context = *(fusefsal_op_context_t *)p_context; 00186 00187 if(file_info_provided) 00188 LogFullDebug(COMPONENT_FSAL, "FSAL_open: FH=%"PRId64, file_descriptor->file_info.fh); 00189 00190 if(file_attributes) 00191 { 00192 fsal_status_t status; 00193 00194 status = FUSEFSAL_getattrs((fsal_handle_t *)filehandle, p_context, file_attributes); 00195 00196 /* on error, we set a special bit in the mask. */ 00197 if(FSAL_IS_ERROR(status)) 00198 { 00199 FSAL_CLEAR_MASK(file_attributes->asked_attributes); 00200 FSAL_SET_MASK(file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00201 } 00202 } 00203 00204 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); 00205 00206 } 00207 00247 fsal_status_t FUSEFSAL_open_by_name(fsal_handle_t * dirhandle, /* IN */ 00248 fsal_name_t * filename, /* IN */ 00249 fsal_op_context_t * p_context, /* IN */ 00250 fsal_openflags_t openflags, /* IN */ 00251 fsal_file_t * file_descriptor, /* OUT */ 00252 fsal_attrib_list_t * 00253 file_attributes /* [ IN/OUT ] */ ) 00254 { 00255 fsal_status_t fsal_status; 00256 fsal_handle_t filehandle; 00257 00258 if(!dirhandle || !filename || !p_context || !file_descriptor) 00259 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name); 00260 00261 fsal_status = 00262 FUSEFSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes); 00263 if(FSAL_IS_ERROR(fsal_status)) 00264 return fsal_status; 00265 00266 return FUSEFSAL_open(&filehandle, p_context, openflags, file_descriptor, 00267 file_attributes); 00268 } 00269 00298 fsal_status_t FUSEFSAL_read(fsal_file_t * file_desc, /* IN */ 00299 fsal_seek_t * seek_descriptor, /* [IN] */ 00300 fsal_size_t buffer_size, /* IN */ 00301 caddr_t buffer, /* OUT */ 00302 fsal_size_t * read_amount, /* OUT */ 00303 fsal_boolean_t * end_of_file /* OUT */ 00304 ) 00305 { 00306 size_t req_size; 00307 int rc; 00308 off_t seekoffset = 0; 00309 struct stat stbuf; 00310 char object_path[FSAL_MAX_PATH_LEN]; 00311 fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc; 00312 00313 /* sanity checks. */ 00314 00315 if(!file_descriptor || !buffer || !read_amount || !end_of_file) 00316 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); 00317 00318 if(!p_fs_ops->read) 00319 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_read); 00320 00321 /* initialize returned values */ 00322 00323 *read_amount = 0; 00324 *end_of_file = 0; 00325 00326 req_size = (size_t) buffer_size; 00327 00328 /* get file's full path */ 00329 rc = NamespacePath(file_descriptor->file_handle.data.inode, 00330 file_descriptor->file_handle.data.device, 00331 file_descriptor->file_handle.data.validator, object_path); 00332 if(rc) 00333 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_read); 00334 00335 /* set context so it can be retrieved by FS */ 00336 fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context); 00337 00338 LogFullDebug(COMPONENT_FSAL, "FSAL_read: FH=%"PRId64, file_descriptor->file_info.fh); 00339 00340 if(seek_descriptor) 00341 { 00342 00343 switch (seek_descriptor->whence) 00344 { 00345 case FSAL_SEEK_SET: 00346 /* set absolute position to offset */ 00347 seekoffset = seek_descriptor->offset; 00348 break; 00349 00350 case FSAL_SEEK_CUR: 00351 /* current position + offset */ 00352 seekoffset = file_descriptor->current_offset + seek_descriptor->offset; 00353 break; 00354 00355 case FSAL_SEEK_END: 00356 /* set end of file + offset */ 00357 /* in this case, the only solution is to get entry attributes */ 00358 00359 if(p_fs_ops->fgetattr) 00360 { 00361 rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info)); 00362 } 00363 else 00364 { 00365 rc = p_fs_ops->getattr(object_path, &stbuf); 00366 } 00367 00368 if(rc) 00369 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_read); 00370 00371 seekoffset = (off_t) stbuf.st_size + seek_descriptor->offset; 00372 00373 break; 00374 00375 default: 00376 LogCrit(COMPONENT_FSAL, "FSAL_read: Invalid seek parameter: whence=%d", 00377 seek_descriptor->whence); 00378 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_read); 00379 } 00380 } 00381 else 00382 { 00383 seekoffset = file_descriptor->current_offset; 00384 } 00385 00386 /* If the call does not fill all the buffer, the rest of the data must be 00387 * substituted with zeroes. */ 00388 memset(buffer, 0, req_size); 00389 00390 TakeTokenFSCall(); 00391 rc = p_fs_ops->read(object_path, buffer, req_size, seekoffset, 00392 &(file_descriptor->file_info)); 00393 ReleaseTokenFSCall(); 00394 00395 if(rc < 0) 00396 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_read); 00397 00398 /* rc >= 0 */ 00399 00400 *read_amount = (fsal_size_t) rc; 00401 *end_of_file = (rc < (off_t) req_size); 00402 file_descriptor->current_offset = seekoffset + (off_t) rc; 00403 00404 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); 00405 00406 } 00407 00435 fsal_status_t FUSEFSAL_write(fsal_file_t * file_desc, /* IN */ 00436 fsal_op_context_t * p_context, /* IN */ 00437 fsal_seek_t * seek_descriptor, /* IN */ 00438 fsal_size_t buffer_size, /* IN */ 00439 caddr_t buffer, /* IN */ 00440 fsal_size_t * write_amount /* OUT */ 00441 ) 00442 { 00443 size_t req_size; 00444 int rc; 00445 off_t seekoffset = 0; 00446 struct stat stbuf; 00447 char object_path[FSAL_MAX_PATH_LEN]; 00448 fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc; 00449 00450 /* sanity checks. */ 00451 if(!file_descriptor || !buffer || !write_amount) 00452 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); 00453 00454 if(!p_fs_ops->write) 00455 Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_write); 00456 00457 /* initialize returned values */ 00458 00459 *write_amount = 0; 00460 00461 req_size = (size_t) buffer_size; 00462 00463 /* set context so it can be retrieved by FS */ 00464 fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context); 00465 00466 LogFullDebug(COMPONENT_FSAL, "FSAL_write: FH=%"PRId64, file_descriptor->file_info.fh); 00467 00468 /* get file's full path */ 00469 rc = NamespacePath(file_descriptor->file_handle.data.inode, 00470 file_descriptor->file_handle.data.device, 00471 file_descriptor->file_handle.data.validator, object_path); 00472 if(rc) 00473 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_write); 00474 00475 if(seek_descriptor) 00476 { 00477 00478 switch (seek_descriptor->whence) 00479 { 00480 case FSAL_SEEK_SET: 00481 /* set absolute position to offset */ 00482 seekoffset = seek_descriptor->offset; 00483 break; 00484 00485 case FSAL_SEEK_CUR: 00486 /* current position + offset */ 00487 seekoffset = file_descriptor->current_offset + seek_descriptor->offset; 00488 break; 00489 00490 case FSAL_SEEK_END: 00491 /* set end of file + offset */ 00492 /* in this case, the only solution is to get entry attributes */ 00493 00494 if(p_fs_ops->fgetattr) 00495 { 00496 rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info)); 00497 } 00498 else 00499 { 00500 rc = p_fs_ops->getattr(object_path, &stbuf); 00501 } 00502 00503 if(rc) 00504 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write); 00505 00506 seekoffset = (off_t) stbuf.st_size + seek_descriptor->offset; 00507 00508 break; 00509 00510 default: 00511 LogCrit(COMPONENT_FSAL, "FSAL_write: Invalid seek parameter: whence=%d", 00512 seek_descriptor->whence); 00513 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_write); 00514 } 00515 } 00516 else 00517 { 00518 seekoffset = file_descriptor->current_offset; 00519 } 00520 00521 TakeTokenFSCall(); 00522 rc = p_fs_ops->write(object_path, buffer, req_size, seekoffset, 00523 &(file_descriptor->file_info)); 00524 ReleaseTokenFSCall(); 00525 00526 if(rc < 0) 00527 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write); 00528 00529 file_descriptor->current_offset = seekoffset + (off_t) rc; 00530 00531 *write_amount = (fsal_size_t) rc; 00532 00533 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); 00534 } 00535 00550 fsal_status_t FUSEFSAL_close(fsal_file_t * file_desc /* IN */ 00551 ) 00552 { 00553 00554 int rc; 00555 char file_path[FSAL_MAX_PATH_LEN]; 00556 fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc; 00557 00558 /* sanity checks. */ 00559 if(!file_descriptor) 00560 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); 00561 00562 /* get the full path for file inode */ 00563 rc = NamespacePath(file_descriptor->file_handle.data.inode, 00564 file_descriptor->file_handle.data.device, 00565 file_descriptor->file_handle.data.validator, file_path); 00566 if(rc) 00567 Return(ERR_FSAL_STALE, rc, INDEX_FSAL_close); 00568 00569 if(!p_fs_ops->release) 00570 /* ignore this call */ 00571 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00572 00573 /* set context so it can be retrieved by FS */ 00574 fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context); 00575 00576 LogFullDebug(COMPONENT_FSAL, "FSAL_close: FH=%"PRId64, file_descriptor->file_info.fh); 00577 00578 TakeTokenFSCall(); 00579 00580 rc = p_fs_ops->release(file_path, &file_descriptor->file_info); 00581 00582 ReleaseTokenFSCall(); 00583 00584 if(rc) 00585 Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_close); 00586 00587 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00588 00589 } 00590 00608 fsal_status_t FUSEFSAL_commit( fsal_file_t * p_file_descriptor, 00609 fsal_off_t offset, 00610 fsal_size_t length ) 00611 { 00612 /* sanity checks. */ 00613 if(!p_file_descriptor) 00614 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit); 00615 00616 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); 00617 } 00618 00619 unsigned int FUSEFSAL_GetFileno(fsal_file_t * pfile) 00620 { 00621 return ((fusefsal_file_t *)pfile)->file_info.fh; 00622 }