nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 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 00021 #ifdef _SHOOK 00022 #include "shook_svr.h" 00023 #endif 00024 00025 00065 fsal_status_t LUSTREFSAL_open_by_name(fsal_handle_t * dirhandle, /* IN */ 00066 fsal_name_t * filename, /* IN */ 00067 fsal_op_context_t * p_context, /* IN */ 00068 fsal_openflags_t openflags, /* IN */ 00069 fsal_file_t * file_descriptor, /* OUT */ 00070 fsal_attrib_list_t * 00071 file_attributes /* [ IN/OUT ] */ ) 00072 { 00073 fsal_status_t fsal_status; 00074 fsal_handle_t filehandle; 00075 00076 if(!dirhandle || !filename || !p_context || !file_descriptor) 00077 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name); 00078 00079 fsal_status = 00080 LUSTREFSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes); 00081 if(FSAL_IS_ERROR(fsal_status)) 00082 return fsal_status; 00083 00084 return LUSTREFSAL_open(&filehandle, p_context, openflags, file_descriptor, 00085 file_attributes); 00086 } 00087 00118 fsal_status_t LUSTREFSAL_open(fsal_handle_t * p_filehandle, /* IN */ 00119 fsal_op_context_t * p_context, /* IN */ 00120 fsal_openflags_t openflags, /* IN */ 00121 fsal_file_t *file_desc, /* OUT */ 00122 fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ 00123 ) 00124 { 00125 int rc, errsv; 00126 fsal_status_t status; 00127 lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)file_desc; 00128 fsal_path_t fsalpath; 00129 struct stat buffstat; 00130 int posix_flags = 0; 00131 00132 /* sanity checks. 00133 * note : file_attributes is optional. 00134 */ 00135 if(!p_filehandle || !p_context || !p_file_descriptor) 00136 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); 00137 00138 status = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath); 00139 if(FSAL_IS_ERROR(status)) 00140 ReturnStatus(status, INDEX_FSAL_open); 00141 00142 /* retrieve file attributes for checking access rights */ 00143 00144 TakeTokenFSCall(); 00145 rc = lstat(fsalpath.path, &buffstat); 00146 errsv = errno; 00147 ReleaseTokenFSCall(); 00148 00149 if(rc) 00150 { 00151 if(errsv == ENOENT) 00152 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open); 00153 else 00154 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); 00155 } 00156 00157 #if 0 00158 status = 00159 fsal_internal_testAccess(p_context, 00160 openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK, 00161 &buffstat, NULL); 00162 if(FSAL_IS_ERROR(status)) 00163 ReturnStatus(status, INDEX_FSAL_open); 00164 #endif 00165 00166 /* convert fsal open flags to posix open flags */ 00167 rc = fsal2posix_openflags(openflags, &posix_flags); 00168 00169 /* flags conflicts. */ 00170 if(rc) 00171 { 00172 LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", 00173 openflags); 00174 Return(rc, 0, INDEX_FSAL_open); 00175 } 00176 00177 /* @TODO For HSM systems, trigger file asynchronous restore 00178 * if the file in offline, to avoid freezing current thread. 00179 * In this case, return EAGAIN to the upper layers. 00180 */ 00181 #ifdef _LUSTRE_HSM 00182 /* call "lfs hsm_restore" if file is released */ 00183 /* @TODO */ 00184 #endif 00185 #ifdef _SHOOK 00186 /* call "shook restore" if file is not online 00187 * or "shook restore_trunc" if file is not online and openflag 00188 * includes O_TRUNC 00189 */ 00190 shook_state state; 00191 rc = shook_get_status(fsalpath.path, &state, 0); 00192 if (rc) 00193 { 00194 LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s", 00195 fsalpath.path, strerror(-rc)); 00196 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open); 00197 } 00198 else if (state != SS_ONLINE) 00199 { 00200 LogInfo(COMPONENT_FSAL, "File is offline: triggering shook restore"); 00201 00202 if (posix_flags & O_TRUNC) 00203 { 00204 TakeTokenFSCall(); 00205 rc = truncate(fsalpath.path, 0); 00206 errsv = errno; 00207 ReleaseTokenFSCall(); 00208 00209 if (rc == 0) 00210 { 00211 /* use a short timeout of 2s */ 00212 rc = shook_server_call(SA_RESTORE_TRUNC, ((lustrefsal_op_context_t *)p_context)->export_context->fsname, 00213 &((lustrefsal_handle_t *)p_filehandle)->data.fid, 2); 00214 if (rc) 00215 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open); 00216 else { 00217 /* check that file is online, else operation is still 00218 * in progress: return err jukebox */ 00219 rc = shook_get_status(fsalpath.path, &state, FALSE); 00220 if (rc) 00221 { 00222 LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s", 00223 fsalpath.path, strerror(-rc)); 00224 if (rc) 00225 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open); 00226 } 00227 else if (state != SS_ONLINE) 00228 Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_open); 00229 /* else: OK */ 00230 } 00231 } 00232 else 00233 { 00234 if(errsv == ENOENT) 00235 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open); 00236 else 00237 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); 00238 } 00239 /* continue to open */ 00240 00241 } else { 00242 /* trigger restore. Give it a chance to retrieve the file in less than a second. 00243 * Else, it returns ETIME that is converted in ERR_DELAY */ 00244 rc = shook_server_call(SA_RESTORE, ((lustrefsal_op_context_t*)p_context)->export_context->fsname, 00245 &((lustrefsal_handle_t *)p_filehandle)->data.fid, 1); 00246 if (rc) 00247 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open); 00248 else { 00249 /* check that file is online, else operation is still 00250 * in progress: return err jukebox */ 00251 rc = shook_get_status(fsalpath.path, &state, FALSE); 00252 if (rc) 00253 { 00254 LogEvent(COMPONENT_FSAL, "Error retrieving shook status of %s: %s", 00255 fsalpath.path, strerror(-rc)); 00256 if (rc) 00257 Return(posix2fsal_error(-rc), -rc, INDEX_FSAL_open); 00258 } 00259 else if (state != SS_ONLINE) 00260 Return(ERR_FSAL_DELAY, -rc, INDEX_FSAL_open); 00261 /* else: OK */ 00262 } 00263 00264 /* if rc = 0, file can be opened */ 00265 } 00266 } 00267 /* else: we can open file directly */ 00268 #endif 00269 00270 TakeTokenFSCall(); 00271 p_file_descriptor->fd = open(fsalpath.path, posix_flags, 0644); 00272 errsv = errno; 00273 ReleaseTokenFSCall(); 00274 00275 if(p_file_descriptor->fd == -1) 00276 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); 00277 00278 /* set the read-only flag of the file descriptor */ 00279 p_file_descriptor->ro = openflags & FSAL_O_RDONLY; 00280 00281 /* output attributes */ 00282 if(p_file_attributes) 00283 { 00284 00285 status = posix2fsal_attributes(&buffstat, p_file_attributes); 00286 00287 if(FSAL_IS_ERROR(status)) 00288 { 00289 FSAL_CLEAR_MASK(p_file_attributes->asked_attributes); 00290 FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00291 } 00292 } 00293 00294 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); 00295 00296 } 00297 00322 fsal_status_t LUSTREFSAL_read(fsal_file_t *file_desc, /* IN */ 00323 fsal_seek_t * p_seek_descriptor, /* [IN] */ 00324 fsal_size_t buffer_size, /* IN */ 00325 caddr_t buffer, /* OUT */ 00326 fsal_size_t * p_read_amount, /* OUT */ 00327 fsal_boolean_t * p_end_of_file /* OUT */ 00328 ) 00329 { 00330 00331 size_t i_size; 00332 ssize_t nb_read; 00333 int rc, errsv; 00334 int pcall = FALSE; 00335 lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)file_desc; 00336 00337 /* sanity checks. */ 00338 00339 if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file) 00340 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); 00341 00343 i_size = (size_t) buffer_size; 00344 00345 /* positioning */ 00346 00347 if(p_seek_descriptor) 00348 { 00349 00350 switch (p_seek_descriptor->whence) 00351 { 00352 case FSAL_SEEK_CUR: 00353 /* set position plus offset */ 00354 pcall = FALSE; 00355 TakeTokenFSCall(); 00356 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); 00357 errsv = errno; 00358 ReleaseTokenFSCall(); 00359 break; 00360 00361 case FSAL_SEEK_SET: 00362 /* use pread/pwrite call */ 00363 pcall = TRUE; 00364 rc = 0; 00365 break; 00366 00367 case FSAL_SEEK_END: 00368 /* set end of file plus offset */ 00369 pcall = FALSE; 00370 00371 TakeTokenFSCall(); 00372 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); 00373 errsv = errno; 00374 ReleaseTokenFSCall(); 00375 break; 00376 00377 default: 00378 LogCrit(COMPONENT_FSAL, "Unexpected value for whence parameter"); 00379 rc = -1; 00380 errsv = EINVAL; 00381 break; 00382 } 00383 00384 if(rc) 00385 { 00386 00387 LogEvent(COMPONENT_FSAL, 00388 "Error in posix fseek operation (whence=%s, offset=%lld)", 00389 (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : 00390 (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : 00391 (p_seek_descriptor->whence == 00392 FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), 00393 (long long int)p_seek_descriptor->offset); 00394 00395 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); 00396 } 00397 00398 } 00399 00400 /* read operation */ 00401 00402 TakeTokenFSCall(); 00403 00404 if(pcall) 00405 nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); 00406 else 00407 nb_read = read(p_file_descriptor->fd, buffer, i_size); 00408 errsv = errno; 00409 ReleaseTokenFSCall(); 00410 00413 if(nb_read == -1) 00414 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); 00415 else if(nb_read == 0) 00416 *p_end_of_file = 1; 00417 00418 *p_read_amount = nb_read; 00419 00420 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); 00421 00422 } 00423 00447 fsal_status_t LUSTREFSAL_write(fsal_file_t *file_desc, /* IN */ 00448 fsal_op_context_t * p_context, /* IN */ 00449 fsal_seek_t * p_seek_descriptor, /* IN */ 00450 fsal_size_t buffer_size, /* IN */ 00451 caddr_t buffer, /* IN */ 00452 fsal_size_t * p_write_amount /* OUT */ 00453 ) 00454 { 00455 00456 ssize_t nb_written; 00457 size_t i_size; 00458 int rc, errsv; 00459 int pcall = FALSE; 00460 lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)file_desc; 00461 00462 /* sanity checks. */ 00463 if(!p_file_descriptor || !buffer || !p_write_amount) 00464 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); 00465 00466 if(p_file_descriptor->ro) 00467 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write); 00468 00470 i_size = (size_t) buffer_size; 00471 00472 *p_write_amount = 0; 00473 00474 /* positioning */ 00475 00476 if(p_seek_descriptor) 00477 { 00478 00479 switch (p_seek_descriptor->whence) 00480 { 00481 case FSAL_SEEK_CUR: 00482 /* set position plus offset */ 00483 pcall = FALSE; 00484 00485 TakeTokenFSCall(); 00486 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); 00487 errsv = errno; 00488 ReleaseTokenFSCall(); 00489 break; 00490 00491 case FSAL_SEEK_SET: 00492 /* set absolute position to offset */ 00493 pcall = TRUE; 00494 rc = 0; 00495 break; 00496 00497 case FSAL_SEEK_END: 00498 /* set end of file plus offset */ 00499 pcall = FALSE; 00500 00501 TakeTokenFSCall(); 00502 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); 00503 errsv = errno; 00504 ReleaseTokenFSCall(); 00505 00506 break; 00507 00508 default: 00509 LogCrit(COMPONENT_FSAL, "Unexpected value for whence parameter"); 00510 rc = -1; 00511 errsv = EINVAL; 00512 break; 00513 } 00514 00515 if(rc) 00516 { 00517 00518 LogEvent(COMPONENT_FSAL, 00519 "Error in posix fseek operation (whence=%s, offset=%lld)", 00520 (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : 00521 (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : 00522 (p_seek_descriptor->whence == 00523 FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), 00524 (long long int)p_seek_descriptor->offset); 00525 00526 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); 00527 00528 } 00529 00530 LogFullDebug(COMPONENT_FSAL, 00531 "Write operation (whence=%s, offset=%lld, size=%lld)", 00532 (p_seek_descriptor->whence == 00533 FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence == 00534 FSAL_SEEK_SET ? "SEEK_SET" 00535 : (p_seek_descriptor->whence == 00536 FSAL_SEEK_END ? "SEEK_END" : 00537 "ERROR"))), 00538 (long long int)p_seek_descriptor->offset, (unsigned long long)buffer_size); 00539 00540 } 00541 00542 /* write operation */ 00543 00544 TakeTokenFSCall(); 00545 00546 if(pcall) 00547 nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); 00548 else 00549 nb_written = write(p_file_descriptor->fd, buffer, i_size); 00550 errsv = errno; 00551 00552 ReleaseTokenFSCall(); 00553 00555 if(nb_written <= 0) 00556 { 00557 LogDebug(COMPONENT_FSAL, 00558 "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.", 00559 (unsigned long long)i_size, (long long int)p_seek_descriptor->offset, 00560 p_file_descriptor->fd, errsv); 00561 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); 00562 } 00563 00564 /* set output vars */ 00565 00566 *p_write_amount = (fsal_size_t) nb_written; 00567 00568 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); 00569 00570 } 00571 00584 fsal_status_t LUSTREFSAL_close(fsal_file_t * pfile_desc /* IN */ 00585 ) 00586 { 00587 00588 int rc, errsv; 00589 lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)pfile_desc; 00590 00591 /* sanity checks. */ 00592 if(!p_file_descriptor) 00593 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); 00594 00595 /* avoid double close errors */ 00596 if (((lustrefsal_file_t *)p_file_descriptor)->fd <= 0) 00597 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00598 00599 /* call to close */ 00600 TakeTokenFSCall(); 00601 00602 rc = close(((lustrefsal_file_t *)p_file_descriptor)->fd); 00603 errsv = errno; 00604 00605 ReleaseTokenFSCall(); 00606 00607 if(rc) 00608 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close); 00609 00610 ((lustrefsal_file_t *)p_file_descriptor)->fd = -1; 00611 00612 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00613 00614 } 00615 00616 unsigned int LUSTREFSAL_GetFileno(fsal_file_t * pfile) 00617 { 00618 return ((lustrefsal_file_t *)pfile)->fd; 00619 } 00620 00621 00622 00640 fsal_status_t LUSTREFSAL_commit( fsal_file_t * pfile_desc, 00641 fsal_off_t offset, 00642 fsal_size_t length ) 00643 { 00644 int rc, errsv; 00645 lustrefsal_file_t * p_file_descriptor = (lustrefsal_file_t *)pfile_desc; 00646 00647 /* sanity checks. */ 00648 if(!p_file_descriptor) 00649 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit); 00650 00651 if (((lustrefsal_file_t *)p_file_descriptor)->fd <= 0) 00652 { 00653 LogWarn(COMPONENT_FSAL, "sync on closed fd"); 00654 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); 00655 } 00656 00657 /* Flush data. */ 00658 TakeTokenFSCall(); 00659 rc = fsync(((lustrefsal_file_t *)p_file_descriptor)->fd); 00660 errsv = errno; 00661 ReleaseTokenFSCall(); 00662 00663 if(rc) 00664 { 00665 LogEvent(COMPONENT_FSAL, "Error in fsync operation"); 00666 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit); 00667 } 00668 00669 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); 00670 }