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_convert.h" 00041 #include <sys/fsuid.h> 00042 00082 fsal_status_t GPFSFSAL_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 GPFSFSAL_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 * file_desc, /* OUT */ 00136 fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ 00137 ) 00138 { 00139 00140 int rc; 00141 fsal_status_t status; 00142 00143 int fd; 00144 int posix_flags = 0; 00145 gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; 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 p_file_descriptor->fd = fd; 00166 ReleaseTokenFSCall(); 00167 00168 if(FSAL_IS_ERROR(status)) 00169 { 00170 p_file_descriptor->fd = 0; 00171 ReturnStatus(status, INDEX_FSAL_open); 00172 } 00173 00174 /* output attributes */ 00175 if(p_file_attributes) 00176 { 00177 00178 p_file_attributes->asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; 00179 status = GPFSFSAL_getattrs(p_filehandle, p_context, p_file_attributes); 00180 if(FSAL_IS_ERROR(status)) 00181 { 00182 p_file_descriptor->fd = 0; 00183 close(fd); 00184 ReturnStatus(status, INDEX_FSAL_open); 00185 } 00186 } 00187 00188 /* set the read-only flag of the file descriptor */ 00189 p_file_descriptor->ro = openflags & FSAL_O_RDONLY; 00190 00191 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); 00192 00193 } 00194 00219 fsal_status_t GPFSFSAL_read(fsal_file_t * file_desc, /* IN */ 00220 fsal_seek_t * p_seek_descriptor, /* [IN] */ 00221 fsal_size_t buffer_size, /* IN */ 00222 caddr_t buffer, /* OUT */ 00223 fsal_size_t * p_read_amount, /* OUT */ 00224 fsal_boolean_t * p_end_of_file /* OUT */ 00225 ) 00226 { 00227 00228 size_t i_size; 00229 ssize_t nb_read; 00230 int rc = 0, errsv = 0; 00231 int pcall = FALSE; 00232 gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; 00233 00234 /* sanity checks. */ 00235 00236 if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file) 00237 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); 00238 00240 i_size = (size_t) buffer_size; 00241 00242 /* positioning */ 00243 00244 if(p_seek_descriptor) 00245 { 00246 00247 switch (p_seek_descriptor->whence) 00248 { 00249 case FSAL_SEEK_CUR: 00250 /* set position plus offset */ 00251 pcall = FALSE; 00252 TakeTokenFSCall(); 00253 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); 00254 errsv = errno; 00255 ReleaseTokenFSCall(); 00256 break; 00257 00258 case FSAL_SEEK_SET: 00259 /* use pread/pwrite call */ 00260 pcall = TRUE; 00261 rc = 0; 00262 break; 00263 00264 case FSAL_SEEK_END: 00265 /* set end of file plus offset */ 00266 pcall = FALSE; 00267 00268 TakeTokenFSCall(); 00269 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); 00270 errsv = errno; 00271 ReleaseTokenFSCall(); 00272 00273 break; 00274 } 00275 00276 if(rc) 00277 { 00278 LogFullDebug(COMPONENT_FSAL, 00279 "Error in posix fseek operation (whence=%s, offset=%lld)", 00280 format_seek_whence(p_seek_descriptor->whence), 00281 (long long) p_seek_descriptor->offset); 00282 00283 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); 00284 } 00285 00286 } 00287 00288 /* read operation */ 00289 00290 TakeTokenFSCall(); 00291 00292 if(pcall) 00293 nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); 00294 else 00295 nb_read = read(p_file_descriptor->fd, buffer, i_size); 00296 errsv = errno; 00297 ReleaseTokenFSCall(); 00298 00301 if(nb_read == -1) 00302 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); 00303 else if(nb_read == 0) 00304 *p_end_of_file = 1; 00305 00306 *p_read_amount = nb_read; 00307 00308 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); 00309 00310 } 00311 00335 fsal_status_t GPFSFSAL_write(fsal_file_t * file_desc, /* IN */ 00336 fsal_op_context_t * p_context, /* IN */ 00337 fsal_seek_t * p_seek_descriptor, /* IN */ 00338 fsal_size_t buffer_size, /* IN */ 00339 caddr_t buffer, /* IN */ 00340 fsal_size_t * p_write_amount /* OUT */ 00341 ) 00342 { 00343 00344 ssize_t nb_written; 00345 size_t i_size; 00346 int rc = 0, errsv = 0; 00347 int pcall = FALSE, fsuid, fsgid; 00348 gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; 00349 00350 /* sanity checks. */ 00351 if(!p_file_descriptor || !buffer || !p_write_amount) 00352 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); 00353 00354 if(p_file_descriptor->ro) 00355 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write); 00356 00358 i_size = (size_t) buffer_size; 00359 00360 *p_write_amount = 0; 00361 00362 /* positioning */ 00363 00364 if(p_seek_descriptor) 00365 { 00366 00367 switch (p_seek_descriptor->whence) 00368 { 00369 case FSAL_SEEK_CUR: 00370 /* set position plus offset */ 00371 pcall = FALSE; 00372 00373 TakeTokenFSCall(); 00374 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); 00375 errsv = errno; 00376 ReleaseTokenFSCall(); 00377 break; 00378 00379 case FSAL_SEEK_SET: 00380 /* set absolute position to offset */ 00381 pcall = TRUE; 00382 rc = 0; 00383 break; 00384 00385 case FSAL_SEEK_END: 00386 /* set end of file plus offset */ 00387 pcall = FALSE; 00388 00389 TakeTokenFSCall(); 00390 rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); 00391 errsv = errno; 00392 ReleaseTokenFSCall(); 00393 00394 break; 00395 } 00396 00397 if(rc) 00398 { 00399 LogFullDebug(COMPONENT_FSAL, 00400 "Error in posix fseek operation (whence=%s, offset=%lld)", 00401 format_seek_whence(p_seek_descriptor->whence), 00402 (long long) p_seek_descriptor->offset); 00403 00404 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); 00405 00406 } 00407 00408 LogFullDebug(COMPONENT_FSAL, 00409 "Write operation (whence=%s, offset=%lld, size=%zd)", 00410 format_seek_whence(p_seek_descriptor->whence), 00411 (long long) p_seek_descriptor->offset, buffer_size); 00412 00413 } 00414 00415 /* write operation */ 00416 00417 TakeTokenFSCall(); 00418 00419 fsuid = setfsuid(p_context->credential.user); 00420 fsgid = setfsgid(p_context->credential.group); 00421 if(pcall) 00422 nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); 00423 else 00424 nb_written = write(p_file_descriptor->fd, buffer, i_size); 00425 errsv = errno; 00426 00427 setfsuid(fsuid); 00428 setfsgid(fsgid); 00429 ReleaseTokenFSCall(); 00430 00432 if(nb_written <= 0) 00433 { 00434 if (p_seek_descriptor) 00435 LogDebug(COMPONENT_FSAL, 00436 "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.", 00437 (unsigned long long) i_size, 00438 (long long) p_seek_descriptor->offset, 00439 p_file_descriptor->fd, 00440 errsv); 00441 else 00442 LogDebug(COMPONENT_FSAL, 00443 "Write operation of size %llu at offset 0. fd=%d, errno=%d.", 00444 (unsigned long long) i_size, 00445 p_file_descriptor->fd, 00446 errsv); 00447 00448 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); 00449 } 00450 00451 /* set output vars */ 00452 00453 *p_write_amount = (fsal_size_t) nb_written; 00454 00455 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); 00456 00457 } 00458 00471 fsal_status_t GPFSFSAL_close(fsal_file_t * p_file_descriptor /* IN */ 00472 ) 00473 { 00474 00475 int rc, errsv; 00476 00477 /* sanity checks. */ 00478 if(!p_file_descriptor) 00479 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); 00480 00481 /* call to close */ 00482 00483 TakeTokenFSCall(); 00484 00485 rc = close(((gpfsfsal_file_t *)p_file_descriptor)->fd); 00486 errsv = errno; 00487 00488 ReleaseTokenFSCall(); 00489 00490 if(rc) 00491 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close); 00492 00493 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); 00494 00495 } 00496 00497 unsigned int GPFSFSAL_GetFileno(fsal_file_t * pfile) 00498 { 00499 return ((gpfsfsal_file_t *)pfile)->fd; 00500 } 00501 00519 fsal_status_t GPFSFSAL_commit( fsal_file_t * p_file_descriptor, 00520 fsal_off_t offset, 00521 fsal_size_t length ) 00522 { 00523 int rc, errsv; 00524 00525 /* sanity checks. */ 00526 if(!p_file_descriptor) 00527 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit); 00528 00529 /* Flush data. */ 00530 TakeTokenFSCall(); 00531 rc = fsync(((gpfsfsal_file_t *)p_file_descriptor)->fd); 00532 errsv = errno; 00533 ReleaseTokenFSCall(); 00534 00535 if(rc) 00536 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit); 00537 00538 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); 00539 }