/** * FSAL_getattrs: * Get attributes for the object specified by its filehandle. * * \param filehandle (input): * The handle of the object to get parameters. * \param context (input): * Authentication context for the operation (user, export...). * \param object_attributes (mandatory input/output): * The retrieved attributes for the object. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_STALE (object_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Another error code if an error occured. */ fsal_status_t CEPHFSAL_getattrs(fsal_handle_t * exthandle, fsal_op_context_t * extcontext, fsal_attrib_list_t * object_attributes) { int rc; struct stat st; fsal_status_t status; cephfsal_handle_t* filehandle = (cephfsal_handle_t*) exthandle; cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext; int uid = FSAL_OP_CONTEXT_TO_UID(context); int gid = FSAL_OP_CONTEXT_TO_GID(context); /* sanity checks. * note : object_attributes is mandatory in FSAL_getattrs. */ if(!filehandle || !context || !object_attributes) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); TakeTokenFSCall(); rc = ceph_ll_getattr(context->export_context->cmount, VINODE(filehandle), &st, uid, gid); ReleaseTokenFSCall(); if (rc < 0) Return(posix2fsal_error(rc), 0, INDEX_FSAL_getattrs); /* convert attributes */ status = posix2fsal_attributes(&st, object_attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(object_attributes->asked_attributes); FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs); }
fsal_status_t tank_remove_extattr_by_name(struct fsal_obj_handle *obj_hdl, const char *xattr_name) { struct zfs_fsal_obj_handle *obj_handle = NULL; int retval = 0; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; retval = libzfswrap_removexattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_name); if (retval != 0) return fsalstat(posix2fsal_error(retval), retval); return fsalstat(ERR_FSAL_NO_ERROR, 0); }
static int xattr_id_to_name(libzfswrap_vfs_t *p_vfs, creden_t *pcred, inogen_t object, unsigned int xattr_id, char *name) { unsigned int index; unsigned int curr_idx; char names[MAXPATHLEN], *ptr; size_t namesize; size_t len = 0; int retval = 0; if (xattr_id < XATTR_COUNT) return ERR_FSAL_INVAL; index = xattr_id - XATTR_COUNT; /* get xattrs */ retval = libzfswrap_listxattr(p_vfs, pcred, object, (char **)&names, &namesize); if (retval) return posix2fsal_error(retval); if (namesize == 0) return ERR_FSAL_NOENT; errno = 0; for (ptr = names, curr_idx = 0; ptr < names + namesize; curr_idx++, ptr += len + 1) { len = strlen(ptr); if (curr_idx == index) { strcpy(name, ptr); return ERR_FSAL_NO_ERROR; } } return ERR_FSAL_NOENT; }
/** @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); }
static fsal_status_t getxattrs(struct fsal_obj_handle *obj_hdl, xattrname4 *xa_name, xattrvalue4 *xa_value) { int rc; int errsv; struct getxattr_arg gxarg; struct gpfs_fsal_obj_handle *myself; struct gpfs_filesystem *gpfs_fs = obj_hdl->fs->private_data; myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); gxarg.mountdirfd = gpfs_fs->root_fd; gxarg.handle = myself->handle; gxarg.name_len = xa_name->utf8string_len; gxarg.name = xa_name->utf8string_val; gxarg.value_len = xa_value->utf8string_len; gxarg.value = xa_value->utf8string_val; rc = gpfs_ganesha(OPENHANDLE_GETXATTRS, &gxarg); if (rc < 0) { errsv = errno; LogDebug(COMPONENT_FSAL, "GETXATTRS returned rc %d errsv %d", rc, errsv); if (errsv == ERANGE) return fsalstat(ERR_FSAL_TOOSMALL, 0); if (errsv == ENODATA) return fsalstat(ERR_FSAL_NOENT, 0); return fsalstat(posix2fsal_error(errsv), errsv); } LogDebug(COMPONENT_FSAL, "GETXATTRS returned value %.*s len %d rc %d", gxarg.value_len, (char *)gxarg.value, gxarg.value_len, rc); xa_value->utf8string_len = gxarg.value_len; return fsalstat(ERR_FSAL_NO_ERROR, 0); }
static fsal_status_t makedir(struct fsal_obj_handle *dir_hdl, const char *name, struct attrlist *attrib, struct fsal_obj_handle **handle) { fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR; int retval = 0; struct pt_fsal_obj_handle *hdl; fsal_status_t status; ptfsal_handle_t *fh = alloca(sizeof(ptfsal_handle_t)); *handle = NULL; /* poison it */ if (!dir_hdl->ops->handle_is(dir_hdl, DIRECTORY)) { LogCrit(COMPONENT_FSAL, "Parent handle is not a directory. hdl = 0x%p", dir_hdl); return fsalstat(ERR_FSAL_NOTDIR, 0); } memset(fh, 0, sizeof(ptfsal_handle_t)); fh->data.handle.handle_size = FSI_CCL_PERSISTENT_HANDLE_N_BYTES; attrib->mask = op_ctx->fsal_export->ops->fs_supported_attrs(op_ctx->fsal_export); status = PTFSAL_mkdir(dir_hdl, name, op_ctx, attrib->mode, fh, attrib); if (FSAL_IS_ERROR(status)) return status; /* allocate an obj_handle and fill it up */ hdl = alloc_handle(fh, attrib, NULL, NULL, NULL, op_ctx->fsal_export); if (hdl == NULL) { retval = ENOMEM; goto fileerr; } *handle = &hdl->obj_handle; return fsalstat(ERR_FSAL_NO_ERROR, 0); fileerr: fsal_error = posix2fsal_error(retval); return fsalstat(fsal_error, retval); }
/** * FSAL_dynamic_fsinfo: * Return dynamic filesystem info such as * used size, free size, number of objects... * * \param filehandle (input): * Handle of an object in the filesystem * whom info is to be retrieved. * \param cred (input): * Authentication context for the operation (user,...). * \param dynamicinfo (output): * Pointer to the static info of the filesystem. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - ERR_FSAL_FAULT: NULL pointer passed as input parameter. * - ERR_FSAL_SERVERFAULT: Unexpected error. */ fsal_status_t LUSTREFSAL_dynamic_fsinfo(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_dynamicfsinfo_t * p_dynamicinfo /* OUT */ ) { fsal_path_t pathfsal; fsal_status_t status; struct statvfs buffstatvfs; int rc, errsv; /* sanity checks. */ if(!p_filehandle || !p_dynamicinfo || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_dynamic_fsinfo); status = fsal_internal_Handle2FidPath(p_context, p_filehandle, &pathfsal); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_dynamic_fsinfo); TakeTokenFSCall(); rc = statvfs(pathfsal.path, &buffstatvfs); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_dynamic_fsinfo); p_dynamicinfo->total_bytes = buffstatvfs.f_frsize * buffstatvfs.f_blocks; p_dynamicinfo->free_bytes = buffstatvfs.f_frsize * buffstatvfs.f_bfree; p_dynamicinfo->avail_bytes = buffstatvfs.f_frsize * buffstatvfs.f_bavail; p_dynamicinfo->total_files = buffstatvfs.f_files; p_dynamicinfo->free_files = buffstatvfs.f_ffree; p_dynamicinfo->avail_files = buffstatvfs.f_favail; p_dynamicinfo->time_delta.seconds = 1; p_dynamicinfo->time_delta.nseconds = 0; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_dynamic_fsinfo); }
fsal_status_t ZFSFSAL_close(fsal_file_t * file_desc /* IN */ ) { int rc = 0; zfsfsal_file_t * file_descriptor = (zfsfsal_file_t *)file_desc; /* sanity checks. */ if(!file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); TakeTokenFSCall(); if(!file_descriptor->is_closed) { /* Test that the vfs still exist */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&file_descriptor->handle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); ReleaseTokenFSCall(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_close); } rc = libzfswrap_close(p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, file_descriptor->flags); ZFSFSAL_VFS_Unlock(); file_descriptor->is_closed = 1; } ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(rc), rc, INDEX_FSAL_close); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); }
fsal_status_t gpfs_seek(struct fsal_obj_handle *obj_hdl, struct io_info *info) { struct fseek_arg arg; struct gpfs_fsal_obj_handle *myself; fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR; struct gpfs_io_info io_info; int retval = 0; myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); assert(myself->u.file.fd >= 0 && myself->u.file.openflags != FSAL_O_CLOSED); arg.mountdirfd = myself->u.file.fd; arg.openfd = myself->u.file.fd; arg.info = &io_info; io_info.io_offset = info->io_content.hole.di_offset; if (info->io_content.what == NFS4_CONTENT_DATA) io_info.io_what = SEEK_DATA; else if (info->io_content.what == NFS4_CONTENT_HOLE) io_info.io_what = SEEK_HOLE; else return fsalstat(ERR_FSAL_UNION_NOTSUPP, 0); retval = gpfs_ganesha(OPENHANDLE_SEEK_BY_FD, &arg); if (retval == -1) { retval = errno; if (retval == EUNATCH) LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH"); fsal_error = posix2fsal_error(retval); } else { info->io_eof = io_info.io_eof; info->io_content.hole.di_offset = io_info.io_offset; info->io_content.hole.di_length = io_info.io_len; } return fsalstat(fsal_error, 0); }
fsal_status_t XFSFSAL_check_quota( char * path, /* IN */ fsal_quota_type_t quota_type, fsal_uid_t fsal_uid) /* IN */ { struct dqblk fs_quota; char fs_spec[MAXPATHLEN]; if(!path ) ReturnCode(ERR_FSAL_FAULT, 0); if(fsal_internal_path2fsname( path, fs_spec) == -1) ReturnCode(ERR_FSAL_INVAL, 0); if( fsal_uid == 0 ) /* No quota for root */ ReturnCode(ERR_FSAL_NO_ERROR, 0) ; memset((char *)&fs_quota, 0, sizeof(struct dqblk)); if(quotactl(FSAL_QCMD(Q_GETQUOTA, USRQUOTA), fs_spec, fsal_uid, (caddr_t) & fs_quota) < 0 ) ReturnCode(posix2fsal_error(errno), errno); switch( quota_type ) { case FSAL_QUOTA_BLOCKS: if( fs_quota.dqb_curspace > fs_quota.dqb_bhardlimit ) ReturnCode( ERR_FSAL_DQUOT, EDQUOT ) ; break ; case FSAL_QUOTA_INODES: if( fs_quota.dqb_curinodes > fs_quota.dqb_ihardlimit ) ReturnCode( ERR_FSAL_DQUOT, EDQUOT ) ; break ; } /* switch( quota_type ) */ ReturnCode(ERR_FSAL_NO_ERROR, 0) ; } /* XFSFSAL_check_quota */
/** * VFSFSAL_getattrs: * Get attributes for the object specified by its filehandle. * * \param filehandle (input): * The handle of the object to get parameters. * \param cred (input): * Authentication context for the operation (user,...). * \param object_attributes (mandatory input/output): * The retrieved attributes for the object. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t VFSFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_object_attributes /* IN/OUT */ ) { fsal_status_t st; int rc = 0 ; int errsv; struct stat buffstat; /* sanity checks. * note : object_attributes is mandatory in VFSFSAL_getattrs. */ if(!p_filehandle || !p_context || !p_object_attributes) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); TakeTokenFSCall(); rc = vfs_stat_by_handle( ((vfsfsal_op_context_t *)p_context)->export_context->mount_root_fd, &((vfsfsal_handle_t *)p_filehandle)->data.vfs_handle, &buffstat ) ; errsv = errno; ReleaseTokenFSCall(); if( rc == -1 ) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs); /* convert attributes */ st = posix2fsal_attributes(&buffstat, p_object_attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); ReturnStatus(st, INDEX_FSAL_getattrs); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs); }
fsal_status_t fsal_internal_get_handle_at(int dfd, /* IN */ const char *name, /* IN */ fsal_handle_t *p_handle /* OUT */ ) { int errsrv = 0 ; if( !name || !p_handle ) ReturnCode(ERR_FSAL_FAULT, 0); memset(p_handle, 0, sizeof(vfsfsal_handle_t)); LogFullDebug(COMPONENT_FSAL, "get handle at for %s", name); ((vfsfsal_handle_t *)p_handle)->data.vfs_handle.handle_bytes = VFS_HANDLE_LEN ; if( vfs_name_by_handle_at( dfd, name, &((vfsfsal_handle_t *)p_handle)->data.vfs_handle ) != 0 ) { errsrv = errno; ReturnCode(posix2fsal_error(errsrv), errsrv); } ReturnCode(ERR_FSAL_NO_ERROR, 0); } /* fsal_internal_get_handle_at */
/** * Removes a xattr by Name * * \param p_objecthandle Handle of the object you want to get attribute for. * \param p_context pointer to the current security context. * \param xattr_name xattr's name */ fsal_status_t ZFSFSAL_RemoveXAttrByName(fsal_handle_t * obj_handle, /* IN */ fsal_op_context_t * p_context, /* IN */ const fsal_name_t * xattr_name) /* IN */ { int rc; creden_t cred; zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle; /* Hook to prevent any modification in the snapshots */ if(p_objecthandle->data.i_snap != 0) Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue); cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); rc = libzfswrap_removexattr(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &cred, p_objecthandle->data.zfs_handle, xattr_name->name); ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue); }
static fsal_status_t lustre_linkfile(struct fsal_obj_handle *obj_hdl, struct fsal_obj_handle *destdir_hdl, const char *name) { struct lustre_fsal_obj_handle *myself, *destdir; char srcpath[MAXPATHLEN]; char destdirpath[MAXPATHLEN]; char destnamepath[MAXPATHLEN]; int rc = 0; fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR; if (!op_ctx->fsal_export->ops-> fs_supports(op_ctx->fsal_export, fso_link_support)) { fsal_error = ERR_FSAL_NOTSUPP; goto out; } myself = container_of(obj_hdl, struct lustre_fsal_obj_handle, obj_handle); lustre_handle_to_path(obj_hdl->fs->path, myself->handle, srcpath); destdir = container_of(destdir_hdl, struct lustre_fsal_obj_handle, obj_handle); lustre_handle_to_path(obj_hdl->fs->path, destdir->handle, destdirpath); snprintf(destnamepath, MAXPATHLEN, "%s/%s", destdirpath, name); rc = CRED_WRAP(op_ctx->creds, int, link, srcpath, destnamepath); if (rc == -1) { rc = errno; fsal_error = posix2fsal_error(rc); } out: return fsalstat(fsal_error, rc); }
/** @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); }
/** * FSAL_dynamic_fsinfo: * Return dynamic filesystem info such as * used size, free size, number of objects... * * \param filehandle (input): * Handle of an object in the filesystem * whom info is to be retrieved. * \param p_context (input): * Authentication context for the operation (user,...). * \param dynamicinfo (output): * Pointer to the static info of the filesystem. * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t ZFSFSAL_dynamic_fsinfo(fsal_handle_t * filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_dynamicfsinfo_t * dynamicinfo /* OUT */ ) { /* sanity checks. */ if(!filehandle || !dynamicinfo || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_dynamic_fsinfo); TakeTokenFSCall(); struct statvfs statfs; int rc = libzfswrap_statfs(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &statfs); ReleaseTokenFSCall(); /* >> interpret returned status << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_dynamic_fsinfo); dynamicinfo->total_bytes = statfs.f_frsize * statfs.f_blocks; dynamicinfo->free_bytes = statfs.f_frsize * statfs.f_bfree; dynamicinfo->avail_bytes = statfs.f_frsize * statfs.f_bavail; dynamicinfo->total_files = statfs.f_files; dynamicinfo->free_files = statfs.f_ffree; dynamicinfo->avail_files = statfs.f_favail; dynamicinfo->time_delta.seconds = 1; dynamicinfo->time_delta.nseconds = 0; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_dynamic_fsinfo); }
fsal_status_t fsal_internal_fd2handle( vfsfsal_op_context_t * p_context, int fd, vfsfsal_handle_t * phandle) { int rc = 0 ; int errsv = 0 ; int mnt_id = 0 ; phandle->data.vfs_handle.handle_bytes = VFS_HANDLE_LEN ; if( ( rc = vfs_fd_to_handle( fd, &phandle->data.vfs_handle, &mnt_id ) ) ) ReturnCode(posix2fsal_error(errsv), errsv); #if 0 { char str[1024] ; sprint_mem( str, phandle->data.vfs_handle.handle, phandle->data.vfs_handle.handle_bytes ) ; printf( "=====> fsal_internal_fd2handle: type=%u bytes=%u|%s\n", phandle->data.vfs_handle.handle_type, phandle->data.vfs_handle.handle_bytes, str ) ; } #endif ReturnCode(ERR_FSAL_NO_ERROR, 0); } /* fsal_internal_fd2handle */
/** * VFSFSAL_getattrs_descriptor: * Get attributes for the object specified by its descriptor or by it's filehandle. * * \param p_file_descriptor (input): * The file descriptor of the object to get parameters. * \param p_filehandle (input): * The handle of the object to get parameters. * \param p_context (input): * Authentication context for the operation (user,...). * \param p_object_attributes (mandatory input/output): * The retrieved attributes for the object. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t VFSFSAL_getattrs_descriptor(fsal_file_t * p_file_descriptor, /* IN */ fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_object_attributes /* IN/OUT */ ) { fsal_status_t st; struct stat64 buffstat; int rc, errsv; /* sanity checks. * note : object_attributes is mandatory in VFSFSAL_getattrs. */ if(!p_file_descriptor || !p_filehandle || !p_context || !p_object_attributes) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs_descriptor); TakeTokenFSCall(); rc = fstat64(((vfsfsal_file_t *)p_file_descriptor)->fd, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc == -1) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs_descriptor); /* convert attributes */ st = posixstat64_2_fsal_attributes(&buffstat, p_object_attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); ReturnStatus(st, INDEX_FSAL_getattrs_descriptor); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs_descriptor); }
/** * FSAL_closedir : * Free the resources allocated for reading directory entries. * * \param dir_descriptor (input): * Pointer to a directory descriptor filled by FSAL_opendir. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t POSIXFSAL_closedir(fsal_dir_t * dir_descriptor /* IN */ ) { posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor; int rc; /* sanity checks */ if(!p_dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); #ifdef _USE_POSIXDB_READDIR_BLOCK if(p_dir_descriptor->p_dbentries) Mem_Free(p_dir_descriptor->p_dbentries); #endif rc = closedir(p_dir_descriptor->p_dir); if(rc != 0) Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir); /* fill dir_descriptor with zeros */ memset(p_dir_descriptor, 0, sizeof(posixfsal_dir_t)); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); }
fsal_status_t tank_list_ext_attrs(struct fsal_obj_handle *obj_hdl, unsigned int argcookie, fsal_xattrent_t *xattrs_tab, unsigned int xattrs_tabsize, unsigned int *p_nb_returned, int *end_of_list) { unsigned int index; unsigned int out_index; unsigned int cookie = argcookie; struct zfs_fsal_obj_handle *obj_handle = NULL; char names[MAXPATHLEN], *ptr; size_t namesize; int xattr_idx; int retval; creden_t cred; /* sanity checks */ if (!obj_hdl || !xattrs_tab || !p_nb_returned || !end_of_list) return fsalstat(ERR_FSAL_FAULT, 0); obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; /* Deal with special cookie */ if (cookie == XATTR_RW_COOKIE) cookie = XATTR_COUNT; for (index = cookie, out_index = 0; index < XATTR_COUNT && out_index < xattrs_tabsize; index++) { if (do_match_type(xattr_list[index].flags, obj_hdl->attributes.type)) { /* fills an xattr entry */ xattrs_tab[out_index].xattr_id = index; strncpy(xattr_list[index].xattr_name, xattrs_tab[out_index].xattr_name, MAXNAMLEN); xattr_list[index].xattr_name[MAXNAMLEN] = '\0'; xattrs_tab[out_index].xattr_cookie = index + 1; /* set asked attributes (all supported) */ xattrs_tab[out_index].attributes.mask = obj_hdl->attributes.mask; if (file_attributes_to_xattr_attrs(&obj_hdl->attributes, &xattrs_tab [out_index] .attributes, index)) { /* set error flag */ xattrs_tab[out_index].attributes.mask = ATTR_RDATTR_ERR; } /* next output slot */ out_index++; } } /* save a call if output array is full */ if (out_index == xattrs_tabsize) { *end_of_list = false; *p_nb_returned = out_index; return fsalstat(ERR_FSAL_NO_ERROR, 0); } /* get the path of the file in Lustre */ /* get xattrs */ retval = libzfswrap_listxattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, (char **)&names, &namesize); if (retval) return fsalstat(posix2fsal_error(retval), retval); if (namesize > 0) { size_t len = 0; errno = 0; for (ptr = names, xattr_idx = 0; (ptr < names + namesize) && (out_index < xattrs_tabsize); xattr_idx++, ptr += len + 1) { len = strlen(ptr); index = XATTR_COUNT + xattr_idx; /* skip if index is before cookie */ if (index < cookie) continue; /* fills an xattr entry */ xattrs_tab[out_index].xattr_id = index; strncpy(xattrs_tab[out_index].xattr_name, ptr, len + 1); xattrs_tab[out_index].xattr_cookie = index + 1; /* set asked attributes (all supported) */ xattrs_tab[out_index].attributes.mask = obj_hdl->attributes.mask; if (file_attributes_to_xattr_attrs (&obj_hdl->attributes, &xattrs_tab[out_index].attributes, index)) { /* set error flag */ xattrs_tab[out_index].attributes.mask = ATTR_RDATTR_ERR; } /* next output slot */ out_index++; } /* all xattrs are in the output array */ if (ptr >= names + namesize) *end_of_list = true; else *end_of_list = false; } else /* no xattrs */ *end_of_list = true; *p_nb_returned = out_index; return fsalstat(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t tank_getextattr_value_by_id(struct fsal_obj_handle *obj_hdl, unsigned int xattr_id, caddr_t buffer_addr, size_t buffer_size, size_t *p_output_size) { struct zfs_fsal_obj_handle *obj_handle = NULL; int retval = -1; creden_t cred; obj_handle = container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle); /* sanity checks */ if (!obj_hdl || !p_output_size || !buffer_addr) return fsalstat(ERR_FSAL_FAULT, 0); cred.uid = op_ctx->creds->caller_uid; cred.gid = op_ctx->creds->caller_gid; /* check that this index match the type of entry */ if ((xattr_id < XATTR_COUNT) && !do_match_type(xattr_list[xattr_id].flags, obj_hdl->attributes.type)) { return fsalstat(ERR_FSAL_INVAL, 0); } else if (xattr_id >= XATTR_COUNT) { char attr_name[MAXPATHLEN]; /* get the name for this attr */ retval = xattr_id_to_name(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, xattr_id, attr_name); if (retval) return fsalstat(retval, 0); retval = libzfswrap_getxattr(ZFSFSAL_GetVFS(obj_handle->handle), &cred, obj_handle->handle->zfs_handle, attr_name, &buffer_addr); if (retval) return fsalstat(posix2fsal_error(retval), retval); /* the xattr value can be a binary, or a string. * trying to determine its type... */ *p_output_size = strnlen(buffer_addr, buffer_size); xattr_format_value(buffer_addr, p_output_size, buffer_size); return fsalstat(ERR_FSAL_NO_ERROR, 0); } else { /* built-in attr */ /* get the value */ retval = xattr_list[xattr_id].get_func(obj_hdl, buffer_addr, buffer_size, p_output_size, xattr_list[xattr_id] .arg); return fsalstat(retval, 0); } }
/** * FSAL_create: * Create a regular file. * * \param parent_directory_handle (input): * Handle of the parent directory where the file is to be created. * \param p_filename (input): * Pointer to the name of the file to be created. * \param cred (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the file to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param object_handle (output): * Pointer to the handle of the created file. * \param object_attributes (optional input/output): * The attributes of the created file. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occurred. */ fsal_status_t GPFSFSAL_create(fsal_handle_t * p_parent_directory_handle, /* IN */ fsal_name_t * p_filename, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_handle_t * p_object_handle, /* OUT */ fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ ) { int rc = 0, errsv; int setgid_bit = 0; fsal_status_t status; int fd, newfd; mode_t unix_mode; fsal_accessflags_t access_mask = 0; fsal_attrib_list_t parent_dir_attrs; /* sanity checks. * note : object_attributes is optional. */ if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_filename) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); /* convert fsal mode to unix mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~global_fs_info.umask; LogFullDebug(COMPONENT_FSAL, "Creation mode: 0%o", accessmode); TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_parent_directory_handle, &fd, O_RDONLY | O_DIRECTORY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_create); /* retrieve directory metadata */ parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_parent_directory_handle, p_context, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_create); /* Check the user can write in the directory, and check the setgid bit on the directory */ if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID) setgid_bit = 1; /* Set both mode and ace4 mask */ access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE); status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_create); /* call to filesystem */ TakeTokenFSCall(); /* create the file. * O_EXCL=> error if the file already exists */ newfd = openat(fd, p_filename->name, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, unix_mode); errsv = errno; if(newfd < 0) { close(fd); ReleaseTokenFSCall(); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); } /* we no longer need the parent directory open any more */ close(fd); /* close the file descriptor */ /*** * Previously the file handle was closed here. I don't think that we need that, but leaving the commented out logic just in case. rc = close(newfd); errsv = errno; if(rc) { close(fd); ReleaseTokenFSCall(); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); } */ /* get a handle for this new fd, doing this directly ensures no race because we still have the fd open until the end of this function */ status = fsal_internal_fd2handle(newfd, p_object_handle); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) { close(newfd); ReturnStatus(status, INDEX_FSAL_create); } /* the file has been created */ /* chown the file to the current user */ if(p_context->credential.user != geteuid()) { TakeTokenFSCall(); /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ rc = fchown(newfd, p_context->credential.user, setgid_bit ? -1 : (int)p_context->credential.group); errsv = errno; ReleaseTokenFSCall(); if(rc) { close(newfd); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); } } /* if we got this far successfully, but the file close fails, we've got a problem, possibly a disk full problem. */ close(newfd); if(rc) Return(posix2fsal_error(errno), errno, INDEX_FSAL_create); /* retrieve file attributes */ if(p_object_attributes) { status = GPFSFSAL_getattrs(p_object_handle, p_context, p_object_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create); }
/** * FSAL_mknode: * Create a special object in the filesystem. * Not supported upon HPSS. * * \return ERR_FSAL_NOTSUPP. */ fsal_status_t GPFSFSAL_mknode(fsal_handle_t * parentdir_handle, /* IN */ fsal_name_t * p_node_name, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_nodetype_t nodetype, /* IN */ fsal_dev_t * dev, /* IN */ fsal_handle_t * p_object_handle, /* OUT (handle to the created node) */ fsal_attrib_list_t * node_attributes /* [ IN/OUT ] */ ) { int rc, errsv; int setgid_bit = 0; fsal_status_t status; int fd, newfd; mode_t unix_mode = 0; dev_t unix_dev = 0; fsal_accessflags_t access_mask = 0; fsal_attrib_list_t parent_dir_attrs; /* sanity checks. * note : link_attributes is optional. */ if(!parentdir_handle || !p_context || !p_node_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~global_fs_info.umask; switch (nodetype) { case FSAL_TYPE_BLK: if(!dev) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); unix_mode |= S_IFBLK; unix_dev = (dev->major << 8) | (dev->minor & 0xFF); break; case FSAL_TYPE_CHR: if(!dev) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); unix_mode |= S_IFCHR; unix_dev = (dev->major << 8) | (dev->minor & 0xFF); break; case FSAL_TYPE_SOCK: unix_mode |= S_IFSOCK; break; case FSAL_TYPE_FIFO: unix_mode |= S_IFIFO; break; default: LogMajor(COMPONENT_FSAL, "Invalid node type in FSAL_mknode: %d", nodetype); Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode); } /* build the directory path */ status = fsal_internal_handle2fd(p_context, parentdir_handle, &fd, O_RDONLY | O_DIRECTORY); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_mknode); /* retrieve directory attributes */ parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(parentdir_handle, p_context, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_mknode); /* Check the user can write in the directory, and check weither the setgid bit on the directory */ if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID) setgid_bit = 1; /* Set both mode and ace4 mask */ access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE); status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_mknode); /* creates the node, then stats it */ rc = mknodat(fd, p_node_name->name, unix_mode, unix_dev); errsv = errno; if(rc) { close(fd); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); } /* WARNING: * After creating the new node, the node name could have been changed. * This is a race condition. However only root creates new nodes. This * is an unlikely race condition, but hopefully can be fixed someday. */ if(FSAL_IS_ERROR(status = fsal_internal_get_handle_at(fd, p_node_name, p_object_handle))) { close(fd); ReturnStatus(status, INDEX_FSAL_mknode); } if(FSAL_IS_ERROR(status = fsal_internal_handle2fd_at(fd, p_object_handle, &newfd, O_RDONLY | O_NOFOLLOW))) { close(fd); ReturnStatus(status, INDEX_FSAL_mknode); } /* the node has been created */ /* chown the file to the current user/group */ if(p_context->credential.user != geteuid()) { /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ rc = fchown(newfd, p_context->credential.user, setgid_bit ? -1 : (int)p_context->credential.group); errsv = errno; if(rc) { close(fd); close(newfd); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); } } close(fd); close(newfd); /* Fills the attributes if needed */ if(node_attributes) { status = GPFSFSAL_getattrs(p_object_handle, p_context, node_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(node_attributes->asked_attributes); FSAL_SET_MASK(node_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* Finished */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode); }
fsal_status_t LUSTREFSAL_unlink(fsal_handle_t * p_parent_directory_handle, /* IN */ fsal_name_t * p_object_name, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_parent_directory_attributes /* [IN/OUT ] */ ) { fsal_status_t status; int rc, errsv; struct stat buffstat, buffstat_parent; fsal_path_t fsalpath; /* sanity checks. */ if(!p_parent_directory_handle || !p_context || !p_object_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink); /* build the FID path */ status = fsal_internal_Handle2FidPath(p_context, p_parent_directory_handle, &fsalpath); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_unlink); /* get directory metadata */ TakeTokenFSCall(); rc = lstat(fsalpath.path, &buffstat_parent); errsv = errno; ReleaseTokenFSCall(); if(rc) { if(errsv == ENOENT) Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_unlink); else Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink); } /* build the child path */ status = fsal_internal_appendNameToPath(&fsalpath, p_object_name); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_unlink); /* get file metadata */ TakeTokenFSCall(); rc = lstat(fsalpath.path, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink); /* check access rights */ /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */ if((buffstat_parent.st_mode & S_ISVTX) && buffstat_parent.st_uid != p_context->credential.user && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0) { Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_unlink); } /* client must be able to lookup the parent directory and modify it */ status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat_parent, NULL); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_unlink); /****************************** * DELETE FROM THE FILESYSTEM * ******************************/ TakeTokenFSCall(); /* If the object to delete is a directory, use 'rmdir' to delete the object, else use 'unlink' */ rc = (S_ISDIR(buffstat.st_mode)) ? rmdir(fsalpath.path) : unlink(fsalpath.path); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink); /*********************** * FILL THE ATTRIBUTES * ***********************/ if(p_parent_directory_attributes) { status = LUSTREFSAL_getattrs(p_parent_directory_handle, p_context, p_parent_directory_attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_parent_directory_attributes->asked_attributes); FSAL_SET_MASK(p_parent_directory_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink); }
fsal_status_t gpfs_read_plus(struct fsal_obj_handle *obj_hdl, uint64_t offset, size_t buffer_size, void *buffer, size_t *read_amount, bool *end_of_file, struct io_info *info) { struct gpfs_fsal_obj_handle *myself; fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 }; struct read_arg rarg; ssize_t nb_read; int errsv = 0; if (!buffer || !read_amount || !end_of_file || !info) return fsalstat(ERR_FSAL_FAULT, 0); myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); assert(myself->u.file.fd >= 0 && myself->u.file.openflags != FSAL_O_CLOSED); rarg.mountdirfd = myself->u.file.fd; rarg.fd = myself->u.file.fd; rarg.bufP = buffer; rarg.offset = offset; rarg.length = buffer_size; rarg.options = IO_SKIP_HOLE; nb_read = gpfs_ganesha(OPENHANDLE_READ_BY_FD, &rarg); errsv = errno; if (nb_read < 0) { if (errsv == EUNATCH) LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH"); if (errsv != ENODATA) return fsalstat(posix2fsal_error(errsv), errsv); /* errsv == ENODATA */ info->io_content.what = NFS4_CONTENT_HOLE; info->io_content.hole.di_offset = offset; /*offset of hole*/ info->io_content.hole.di_length = buffer_size;/*length of hole*/ *read_amount = buffer_size; if ((buffer_size + offset) > myself->attributes.filesize) { if (offset > myself->attributes.filesize) *read_amount = 0; else *read_amount = myself->attributes.filesize - offset; info->io_content.hole.di_length = *read_amount; } } else { info->io_content.what = NFS4_CONTENT_DATA; info->io_content.data.d_offset = offset + nb_read; info->io_content.data.d_data.data_len = nb_read; info->io_content.data.d_data.data_val = buffer; *read_amount = nb_read; } if (nb_read != -1 && (nb_read == 0 || nb_read < buffer_size || ((offset + nb_read) >= myself->attributes.filesize))) *end_of_file = true; else *end_of_file = false; return status; }
/** * FSAL_create: * Create a regular file. * * \param parent_hdl (input): * Handle of the parent directory where the file is to be created. * \param p_filename (input): * Pointer to the name of the file to be created. * \param p_context (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the file to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param p_object_handle (output): * Pointer to the handle of the created file. * \param p_object_attributes (optional input/output): * The attributes of the created file. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occurred. */ fsal_status_t PTFSAL_create(struct fsal_obj_handle *dir_hdl, /* IN */ const char *p_filename, /* IN */ const struct req_op_context *p_context, /* IN */ uint32_t accessmode, /* IN */ ptfsal_handle_t *p_object_handle, /* OUT */ struct attrlist *p_object_attributes) { /* IN/OUT */ int errsv; fsal_status_t status; struct pt_fsal_obj_handle *pt_hdl; mode_t unix_mode; int open_rc; ptfsal_handle_t *p_fsi_handle = (ptfsal_handle_t *) p_object_handle; FSI_TRACE(FSI_DEBUG, "Begin to create file************************\n"); /* sanity checks. * note : object_attributes is optional. */ if (!dir_hdl || !p_context || !p_object_handle || !p_filename) return fsalstat(ERR_FSAL_FAULT, 0); pt_hdl = container_of(dir_hdl, struct pt_fsal_obj_handle, obj_handle); /* convert fsal mode to unix mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~p_context->fsal_export->exp_ops. fs_umask(p_context->fsal_export); LogFullDebug(COMPONENT_FSAL, "Creation mode: 0%o", accessmode); open_rc = ptfsal_open(pt_hdl, p_filename, p_context, unix_mode, p_object_handle); if (open_rc < 0) { errsv = errno; return fsalstat(posix2fsal_error(errsv), errsv); } FSI_TRACE(FSI_DEBUG, "New Handle = %s", (char *)p_fsi_handle->data.handle.f_handle); /* retrieve file attributes */ if (p_object_attributes) { status = PTFSAL_getattrs(p_context->fsal_export, p_context, p_object_handle, p_object_attributes); /* on error, we set a special bit in the mask. */ if (FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_object_attributes->mask); FSAL_SET_MASK(p_object_attributes->mask, ATTR_RDATTR_ERR); } } FSI_TRACE(FSI_DEBUG, "End to create file************************\n"); /* OK */ return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * FSAL_mkdir: * Create a directory. * * \param dir_hdl (input): * Handle of the parent directory where * the subdirectory is to be created. * \param p_context (input): * Pointer to the name of the directory to be created. * \param cred (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the directory to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param p_object_handle (output): * Pointer to the handle of the created directory. * \param p_object_attributes (optionnal input/output): * The attributes of the created directory. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t PTFSAL_mkdir(struct fsal_obj_handle *dir_hdl, /* IN */ const char *p_dirname, /* IN */ const struct req_op_context *p_context, /* IN */ uint32_t accessmode, /* IN */ ptfsal_handle_t *p_object_handle, /* OUT */ struct attrlist *p_object_attributes) { /* IN/OUT */ int rc, errsv; int setgid_bit = 0; mode_t unix_mode; fsal_status_t status; struct attrlist parent_dir_attrs; char newPath[PATH_MAX]; struct pt_fsal_obj_handle *pt_hdl; FSI_TRACE(FSI_INFO, "MKDIR BEGIN-------------------------\n"); /* sanity checks. * note : object_attributes is optional. */ if (!dir_hdl || !p_context || !p_object_handle || !p_dirname) return fsalstat(ERR_FSAL_FAULT, 0); pt_hdl = container_of(dir_hdl, struct pt_fsal_obj_handle, obj_handle); /* convert FSAL mode to unix mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~p_context->fsal_export->exp_ops. fs_umask(p_context->fsal_export); /* get directory metadata */ parent_dir_attrs.mask = p_context->fsal_export->exp_ops. fs_supported_attrs(p_context->fsal_export); status = PTFSAL_getattrs(p_context->fsal_export, p_context, pt_hdl->handle, &parent_dir_attrs); if (FSAL_IS_ERROR(status)) return status; /* Check the user can write in the directory, and check the * setgid bit on the directory */ if (fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID) setgid_bit = 1; rc = ptfsal_mkdir(pt_hdl, p_dirname, p_context, unix_mode, p_object_handle); errsv = errno; if (rc) return fsalstat(posix2fsal_error(errsv), errsv); if (FSAL_IS_ERROR(status)) return status; /* the directory has been created */ /* chown the dir to the current user/group */ if (p_context->creds->caller_uid != geteuid()) { FSI_TRACE(FSI_DEBUG, "MKDIR %d", __LINE__); /* if the setgid_bit was set on the parent directory, do not * change the group of the created file, because it's already * the parentdir's group */ if (fsi_get_name_from_handle (p_context, p_context->fsal_export, pt_hdl->handle, (char *)newPath, NULL) < 0) { FSI_TRACE(FSI_DEBUG, "Failed to get name from handle %s", (char *)p_object_handle->data.handle. f_handle); return fsalstat(posix2fsal_error(errsv), errsv); } rc = ptfsal_chown(p_context, p_context->fsal_export, newPath, p_context->creds->caller_uid, setgid_bit ? -1 : (int)p_context->creds-> caller_gid); errsv = errno; if (rc) return fsalstat(posix2fsal_error(errsv), errsv); } /* retrieve file attributes */ if (p_object_attributes) { FSI_TRACE(FSI_DEBUG, "MKDIR %d", __LINE__); status = PTFSAL_getattrs(p_context->fsal_export, p_context, p_object_handle, p_object_attributes); /* on error, we set a special bit in the mask. */ if (FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_object_attributes->mask); FSAL_SET_MASK(p_object_attributes->mask, ATTR_RDATTR_ERR); } } FSI_TRACE(FSI_INFO, "MKDIR END ------------------\n"); FSI_TRACE(FSI_DEBUG, "MKDIR %d", __LINE__); /* OK */ return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * FSAL_write: * Perform a write operation on an opened file. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param seek_descriptor (optional input): * Specifies the position where data is to be written. * If not specified, data will be written at the current position. * \param buffer_size (input): * Amount (in bytes) of data to be written. * \param buffer (input): * Address in memory of the data to write to file. * \param write_amount (output): * Pointer to the amount of data (in bytes) that have been written * during this call. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t GPFSFSAL_write(fsal_file_t * file_desc, /* IN */ fsal_seek_t * p_seek_descriptor, /* IN */ fsal_size_t buffer_size, /* IN */ caddr_t buffer, /* IN */ fsal_size_t * p_write_amount /* OUT */ ) { ssize_t nb_written; size_t i_size; int rc = 0, errsv = 0; int pcall = FALSE; gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; /* sanity checks. */ if(!p_file_descriptor || !buffer || !p_write_amount) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); if(p_file_descriptor->ro) Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write); /** @todo: manage fsal_size_t to size_t convertion */ i_size = (size_t) buffer_size; *p_write_amount = 0; /* positioning */ if(p_seek_descriptor) { switch (p_seek_descriptor->whence) { case FSAL_SEEK_CUR: /* set position plus offset */ pcall = FALSE; TakeTokenFSCall(); rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); errsv = errno; ReleaseTokenFSCall(); break; case FSAL_SEEK_SET: /* set absolute position to offset */ pcall = TRUE; rc = 0; break; case FSAL_SEEK_END: /* set end of file plus offset */ pcall = FALSE; TakeTokenFSCall(); rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); errsv = errno; ReleaseTokenFSCall(); break; } if(rc) { LogFullDebug(COMPONENT_FSAL, "Error in posix fseek operation (whence=%s, offset=%lld)", (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : (p_seek_descriptor->whence == FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), (long long) p_seek_descriptor->offset); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); } LogFullDebug(COMPONENT_FSAL, "Write operation (whence=%s, offset=%lld, size=%lld)", (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : (p_seek_descriptor->whence == FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), (long long) p_seek_descriptor->offset, buffer_size); } /* write operation */ TakeTokenFSCall(); if(pcall) nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); else nb_written = write(p_file_descriptor->fd, buffer, i_size); errsv = errno; ReleaseTokenFSCall(); /** @todo: manage ssize_t to fsal_size_t convertion */ if(nb_written <= 0) { if (p_seek_descriptor) LogDebug(COMPONENT_FSAL, "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.", (unsigned long long) i_size, (long long) p_seek_descriptor->offset, p_file_descriptor->fd, errsv); else LogDebug(COMPONENT_FSAL, "Write operation of size %llu at offset 0. fd=%d, errno=%d.", (unsigned long long) i_size, p_file_descriptor->fd, errsv); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write); } /* set output vars */ *p_write_amount = (fsal_size_t) nb_written; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); }
/** * FSAL_read: * Perform a read operation on an opened file. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param seek_descriptor (optional input): * Specifies the position where data is to be read. * If not specified, data will be read at the current position. * \param buffer_size (input): * Amount (in bytes) of data to be read. * \param buffer (output): * Address where the read data is to be stored in memory. * \param read_amount (output): * Pointer to the amount of data (in bytes) that have been read * during this call. * \param end_of_file (output): * Pointer to a boolean that indicates whether the end of file * has been reached during this call. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t GPFSFSAL_read(fsal_file_t * file_desc, /* IN */ fsal_seek_t * p_seek_descriptor, /* [IN] */ fsal_size_t buffer_size, /* IN */ caddr_t buffer, /* OUT */ fsal_size_t * p_read_amount, /* OUT */ fsal_boolean_t * p_end_of_file /* OUT */ ) { size_t i_size; ssize_t nb_read; int rc = 0, errsv = 0; int pcall = FALSE; gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; /* sanity checks. */ if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); /** @todo: manage fsal_size_t to size_t convertion */ i_size = (size_t) buffer_size; /* positioning */ if(p_seek_descriptor) { switch (p_seek_descriptor->whence) { case FSAL_SEEK_CUR: /* set position plus offset */ pcall = FALSE; TakeTokenFSCall(); rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR); errsv = errno; ReleaseTokenFSCall(); break; case FSAL_SEEK_SET: /* use pread/pwrite call */ pcall = TRUE; rc = 0; break; case FSAL_SEEK_END: /* set end of file plus offset */ pcall = FALSE; TakeTokenFSCall(); rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END); errsv = errno; ReleaseTokenFSCall(); break; } if(rc) { LogFullDebug(COMPONENT_FSAL, "Error in posix fseek operation (whence=%s, offset=%lld)", (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" : (p_seek_descriptor->whence == FSAL_SEEK_END ? "SEEK_END" : "ERROR"))), (long long) p_seek_descriptor->offset); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); } } /* read operation */ TakeTokenFSCall(); if(pcall) nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset); else nb_read = read(p_file_descriptor->fd, buffer, i_size); errsv = errno; ReleaseTokenFSCall(); /** @todo: manage ssize_t to fsal_size_t convertion */ if(nb_read == -1) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read); else if(nb_read == 0) *p_end_of_file = 1; *p_read_amount = nb_read; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); }
/** * GPFSFSAL_lock_op: * Lock/unlock/test an owner independent (anonymous) lock for a region in a file. * * \param p_file_descriptor (input): * File descriptor of the file to lock. * \param p_filehandle (input): * File handle of the file to lock. * \param p_context (input): * Context * \param p_owner (input): * Owner for the requested lock; Opaque to FSAL. * \param lock_op (input): * Can be either FSAL_OP_LOCKT, FSAL_OP_LOCK, FSAL_OP_UNLOCK. * The operations are test if a file region is locked, lock a * file region, unlock a file region. * \param lock_type (input): * Can be either FSAL_LOCK_R, FSAL_LOCK_W. * Either a read lock or write lock. * \param lock_start (input): * Start of lock region measured as offset of bytes from start of file. * \param lock_length (input): * Number of bytes to lock. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - ERR_FSAL_FAULT: One of the in put parameters is NULL. * - ERR_FSAL_PERM: lock_op was FSAL_OP_LOCKT and the result was that the operation would not be possible. */ fsal_status_t GPFSFSAL_lock_op( fsal_file_t * p_file_descriptor, /* IN */ fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ void * p_owner, /* IN */ fsal_lock_op_t lock_op, /* IN */ fsal_lock_param_t request_lock, /* IN */ fsal_lock_param_t * conflicting_lock) /* OUT */ { int retval; struct glock glock_args; struct set_get_lock_arg gpfs_sg_arg; glock_args.lfd = ((gpfsfsal_file_t *)p_file_descriptor)->fd; gpfsfsal_op_context_t *gpfs_op_cxt = (gpfsfsal_op_context_t *)p_context; gpfsfsal_file_t * pfd = (gpfsfsal_file_t *) p_file_descriptor; if(p_file_descriptor == NULL) { LogDebug(COMPONENT_FSAL, "p_file_descriptor arg is NULL."); Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op); } if(p_filehandle == NULL) { LogDebug(COMPONENT_FSAL, "p_filehandle arg is NULL."); Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op); } if(p_context == NULL) { LogDebug(COMPONENT_FSAL, "p_context arg is NULL."); Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op); } if(p_owner == NULL) { LogDebug(COMPONENT_FSAL, "p_owner arg is NULL."); Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op); } if(conflicting_lock == NULL && lock_op == FSAL_OP_LOCKT) { LogDebug(COMPONENT_FSAL, "Conflicting_lock argument can't be NULL with lock_op = LOCKT"); Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op); } LogFullDebug(COMPONENT_FSAL, "Locking: op:%d type:%d start:%llu length:%llu owner:%p", lock_op, request_lock.lock_type, request_lock.lock_start, request_lock.lock_length, p_owner); if(lock_op == FSAL_OP_LOCKT) glock_args.cmd = F_GETLK; else if(lock_op == FSAL_OP_LOCK || lock_op == FSAL_OP_UNLOCK) glock_args.cmd = F_SETLK; else if(lock_op == FSAL_OP_LOCKB) glock_args.cmd = F_SETLKW; /*TODO: Handle FSAL_OP_CANCEL */ else { LogDebug(COMPONENT_FSAL, "ERROR: Lock operation requested was not TEST, GET, or SET."); Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op); } if(request_lock.lock_type == FSAL_LOCK_R) glock_args.flock.l_type = F_RDLCK; else if(request_lock.lock_type == FSAL_LOCK_W) glock_args.flock.l_type = F_WRLCK; else { LogDebug(COMPONENT_FSAL, "ERROR: The requested lock type was not read or write."); Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op); } if(lock_op == FSAL_OP_UNLOCK) glock_args.flock.l_type = F_UNLCK; glock_args.flock.l_len = request_lock.lock_length; glock_args.flock.l_start = request_lock.lock_start; glock_args.flock.l_whence = SEEK_SET; glock_args.lfd = pfd->fd; glock_args.lock_owner = p_owner; gpfs_sg_arg.mountdirfd = gpfs_op_cxt->export_context->mount_root_fd; gpfs_sg_arg.lock = &glock_args; errno = 0; retval = gpfs_ganesha(lock_op == FSAL_OP_LOCKT ? OPENHANDLE_GET_LOCK : OPENHANDLE_SET_LOCK, &gpfs_sg_arg); if(retval && lock_op == FSAL_OP_LOCK) { if(conflicting_lock != NULL) { glock_args.cmd = F_GETLK; retval = gpfs_ganesha(OPENHANDLE_GET_LOCK, &gpfs_sg_arg); if(retval) { LogCrit(COMPONENT_FSAL, "After failing a set lock request, An attempt to get the current owner details also failed."); Return(posix2fsal_error(errno), errno, INDEX_FSAL_lock_op); } conflicting_lock->lock_owner = glock_args.flock.l_pid; conflicting_lock->lock_length = glock_args.flock.l_len; conflicting_lock->lock_start = glock_args.flock.l_start; conflicting_lock->lock_type = glock_args.flock.l_type; } Return(posix2fsal_error(errno), errno, INDEX_FSAL_lock_op); } /* F_UNLCK is returned then the tested operation would be possible. */ if(conflicting_lock != NULL) { if(lock_op == FSAL_OP_LOCKT && glock_args.flock.l_type != F_UNLCK) { conflicting_lock->lock_owner = glock_args.flock.l_pid; conflicting_lock->lock_length = glock_args.flock.l_len; conflicting_lock->lock_start = glock_args.flock.l_start; conflicting_lock->lock_type = glock_args.flock.l_type; } else { conflicting_lock->lock_owner = 0; conflicting_lock->lock_length = 0; conflicting_lock->lock_start = 0; conflicting_lock->lock_type = FSAL_NO_LOCK; } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lock_op); }