blob: 84582fda1bbafbc6f8972894e791acdafd45b1eb [file] [log] [blame]
/*
* @file fsal_fileop.c
* @date $Date: 2006/01/17 14:20:07 $
* @brief Files operations.
*
* vim:noexpandtab:shiftwidth=8:tabstop=8:
*
* Copyright CEA/DAM/DIF (2008)
* contributeur : Philippe DENIEL philippe.deniel@cea.fr
* Thomas LEIBOVICI thomas.leibovici@cea.fr
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* -------------
*/
#include "fsal.h"
#include "fsal_internal.h"
#include "fsal_convert.h"
#include "gpfs_methods.h"
#include "FSAL/access_check.h"
/** @fn fsal_status_t
* GPFSFSAL_open(struct fsal_obj_handle *obj_hdl,
* const struct req_op_context *op_ctx,
* fsal_openflags_t openflags, int *file_desc,
* struct attrlist *fsal_attr, bool reopen)
*
* @brief Open a regular file for reading/writing its data content.
*
* @param obj_hdl Handle of the file to be read/modified.
* @param op_ctx Authentication context for the operation (user,...).
* @param openflags Flags that indicates behavior for file opening and access.
* This is an inclusive OR of the following values
* ( such of them are not compatible) :
* - FSAL_O_RDONLY: opening file for reading only.
* - FSAL_O_RDWR: opening file for reading and writing.
* - FSAL_O_WRONLY: opening file for writting only.
* - FSAL_O_APPEND: always write at the end of the file.
* - FSAL_O_TRUNC: truncate the file to 0 on opening.
* @param file_desc The file descriptor to be used for FSAL_read/write ops.
*
* @return ERR_FSAL_NO_ERROR on success, error otherwise
*/
fsal_status_t
GPFSFSAL_open(struct fsal_obj_handle *obj_hdl,
const struct req_op_context *op_ctx, int posix_flags,
int *file_desc, bool reopen)
{
struct gpfs_fsal_obj_handle *myself;
struct gpfs_filesystem *gpfs_fs;
fsal_status_t status;
/* sanity checks. */
if (!obj_hdl || !file_desc)
return fsalstat(ERR_FSAL_FAULT, 0);
myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle);
gpfs_fs = obj_hdl->fs->private_data;
LogFullDebug(COMPONENT_FSAL, "posix_flags 0x%X", posix_flags);
fsal_set_credentials(op_ctx->creds);
status = fsal_internal_handle2fd(gpfs_fs->root_fd, myself->handle,
file_desc, posix_flags, reopen);
fsal_restore_ganesha_credentials();
if (FSAL_IS_ERROR(status)) {
/** Try open as root access if the above call fails,
* permission will be checked somewhere else in the code.
*/
status = fsal_internal_handle2fd(gpfs_fs->root_fd,
myself->handle,
file_desc, posix_flags,
reopen);
}
return status;
}
/** @fn fsal_status_t
* GPFSFSAL_read(int fd, uint64_t offset, size_t buffer_size, caddr_t buffer,
* size_t *p_read_amount, bool *p_end_of_file)
* @brief Perform a read operation on an opened file.
* @param fd The file descriptor returned by FSAL_open.
* @offset Offset
* @param buf_size Amount (in bytes) of data to be read.
* @param buf Address where the read data is to be stored in memory.
* @param read_amount Pointer to the amount of data (in bytes) that have been read
* during this call.
* @param end_of_file Pointer to a boolean that indicates whether the end of file
* has been reached during this call.
*
* @return ERR_FSAL_NO_ERROR on success, error otherwise.
*/
fsal_status_t
GPFSFSAL_read(int fd, uint64_t offset, size_t buf_size, caddr_t buf,
size_t *read_amount, bool *end_of_file, int expfd)
{
struct read_arg rarg = {0};
ssize_t nb_read;
int errsv;
/* sanity checks. */
if (!buf || !read_amount || !end_of_file)
return fsalstat(ERR_FSAL_FAULT, 0);
rarg.mountdirfd = expfd;
rarg.fd = fd;
rarg.bufP = buf;
rarg.offset = offset;
rarg.length = buf_size;
rarg.options = 0;
fsal_set_credentials(op_ctx->creds);
nb_read = gpfs_ganesha(OPENHANDLE_READ_BY_FD, &rarg);
errsv = errno;
fsal_restore_ganesha_credentials();
/* negative values mean error */
if (nb_read < 0) {
/* if nb_read is not -1, the split rc/errno didn't work */
if (nb_read != -1) {
errsv = labs(nb_read);
LogWarn(COMPONENT_FSAL,
"Received negative value (%d) from ioctl().",
(int) nb_read);
}
if (errsv == EUNATCH)
LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
return fsalstat(posix2fsal_error(errsv), errsv);
}
if (nb_read == 0 || nb_read < buf_size)
*end_of_file = true;
*read_amount = nb_read;
return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
/** @fn fsal_status_t
* GPFSFSAL_write(int fd, uint64_t offset, size_t buf_size, caddr_t buf,
* size_t *write_amount, bool *fsal_stable,
* const struct req_op_context *op_ctx)
* @brief Perform a write operation on an opened file.
*
* @param fd The file descriptor returned by FSAL_open.
* @param buf_size Amount (in bytes) of data to be written.
* @param buf Address where the data is in memory.
* @param write_amount Pointer to the amount of data (in bytes) that have been written
* during this call.
*
* @return ERR_FSAL_NO_ERROR on success, error otherwise
*/
fsal_status_t
GPFSFSAL_write(int fd, uint64_t offset, size_t buf_size, caddr_t buf,
size_t *write_amount, bool *fsal_stable,
const struct req_op_context *op_ctx, int expfd)
{
struct write_arg warg = {0};
uint32_t stability_got = 0;
ssize_t nb_write;
int errsv;
/* sanity checks. */
if (!buf || !write_amount)
return fsalstat(ERR_FSAL_FAULT, 0);
warg.mountdirfd = expfd;
warg.fd = fd;
warg.bufP = buf;
warg.offset = offset;
warg.length = buf_size;
warg.stability_wanted = *fsal_stable;
warg.stability_got = &stability_got;
warg.options = 0;
fsal_set_credentials(op_ctx->creds);
nb_write = gpfs_ganesha(OPENHANDLE_WRITE_BY_FD, &warg);
errsv = errno;
fsal_restore_ganesha_credentials();
if (nb_write == -1) {
if (errsv == EUNATCH)
LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
return fsalstat(posix2fsal_error(errsv), errsv);
}
*write_amount = nb_write;
*fsal_stable = (stability_got) ? true : false;
return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
/** @fn fsal_status_t
* GPFSFSAL_alloc(int fd, uint64_t offset, uint64_t length, bool allocate)
* @brief Perform a de/allocc operation on an opened file.
* @param fd The file descriptor returned by FSAL_open.
* @param offset Offset
* @param length Length
* @param allocate Allocate
*
* @return ERR_FSAL_NO_ERROR on success, error otherwise
*/
fsal_status_t
GPFSFSAL_alloc(int fd, uint64_t offset, uint64_t length, bool allocate)
{
struct alloc_arg aarg = {0};
int errsv;
int rc;
aarg.fd = fd;
aarg.offset = offset;
aarg.length = length;
aarg.options = (allocate) ? IO_ALLOCATE : IO_DEALLOCATE;
fsal_set_credentials(op_ctx->creds);
rc = gpfs_ganesha(OPENHANDLE_ALLOCATE_BY_FD, &aarg);
errsv = errno;
fsal_restore_ganesha_credentials();
if (rc == -1) {
if (errsv == EUNATCH)
LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
return fsalstat(posix2fsal_error(errsv), errsv);
}
return fsalstat(ERR_FSAL_NO_ERROR, 0);
}