/** * FSAL_access : * Tests whether the user or entity identified by its cred * can access the object identified by object_handle, * as indicated by the access_type parameters. * * \param object_handle (input): * The handle of the object to test permissions on. * \param cred (input): * Authentication context for the operation (user,...). * \param access_type (input): * Indicates the permissions to test. * This is an inclusive OR of the permissions * to be checked for the user identified by cred. * Permissions constants are : * - FSAL_R_OK : test for read permission * - FSAL_W_OK : test for write permission * - FSAL_X_OK : test for exec permission * - FSAL_F_OK : test for file existence * \param object_attributes (optional input/output): * The post operation 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). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t LUSTREFSAL_access(fsal_handle_t * p_object_handle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_accessflags_t access_type, /* IN */ fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ ) { fsal_status_t status; /* sanity checks. * note : object_attributes is optionnal in FSAL_getattrs. */ if(!p_object_handle || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access); /* * If an error occures during getattr operation, * it is returned, even though the access operation succeeded. */ if(p_object_attributes) { FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL | FSAL_ATTR_MODE); status = LUSTREFSAL_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); Return(status.major, status.minor, INDEX_FSAL_access); } status = fsal_internal_testAccess(p_context, access_type, NULL, p_object_attributes); } else { /* p_object_attributes is NULL */ fsal_attrib_list_t attrs; FSAL_CLEAR_MASK(attrs.asked_attributes); FSAL_SET_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL | FSAL_ATTR_MODE); status = LUSTREFSAL_getattrs(p_object_handle, p_context, &attrs); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_access); status = fsal_internal_testAccess(p_context, access_type, NULL, &attrs); } Return(status.major, status.minor, INDEX_FSAL_access); }
fsal_status_t posix2fsal_attributes(const struct stat *buffstat, struct attrlist *fsalattr) { FSAL_CLEAR_MASK(fsalattr->mask); /* sanity checks */ if(!buffstat || !fsalattr) return fsalstat(ERR_FSAL_FAULT, 0); FSAL_CLEAR_MASK(fsalattr->mask); /* Fills the output struct */ fsalattr->type = posix2fsal_type(buffstat->st_mode); FSAL_SET_MASK(fsalattr->mask, ATTR_TYPE); fsalattr->filesize = buffstat->st_size; FSAL_SET_MASK(fsalattr->mask, ATTR_SIZE); fsalattr->fsid = posix2fsal_fsid(buffstat->st_dev); FSAL_SET_MASK(fsalattr->mask, ATTR_FSID); fsalattr->fileid = buffstat->st_ino; FSAL_SET_MASK(fsalattr->mask, ATTR_FILEID); fsalattr->mode = unix2fsal_mode(buffstat->st_mode); FSAL_SET_MASK(fsalattr->mask, ATTR_MODE); fsalattr->numlinks = buffstat->st_nlink; FSAL_SET_MASK(fsalattr->mask, ATTR_NUMLINKS); fsalattr->owner = buffstat->st_uid; FSAL_SET_MASK(fsalattr->mask, ATTR_OWNER); fsalattr->group = buffstat->st_gid; FSAL_SET_MASK(fsalattr->mask, ATTR_GROUP); fsalattr->atime = posix2fsal_time(buffstat->st_atime, 0); FSAL_SET_MASK(fsalattr->mask, ATTR_ATIME); fsalattr->ctime = posix2fsal_time(buffstat->st_ctime, 0); FSAL_SET_MASK(fsalattr->mask, ATTR_CTIME); fsalattr->mtime = posix2fsal_time(buffstat->st_mtime, 0); FSAL_SET_MASK(fsalattr->mask, ATTR_MTIME); fsalattr->chgtime = posix2fsal_time(MAX_2(buffstat->st_mtime, buffstat->st_ctime), 0); fsalattr->change = fsalattr->chgtime.tv_sec; FSAL_SET_MASK(fsalattr->mask, ATTR_CHGTIME); fsalattr->spaceused = buffstat->st_blocks * S_BLKSIZE; FSAL_SET_MASK(fsalattr->mask, ATTR_SPACEUSED); fsalattr->rawdev = posix2fsal_devt(buffstat->st_rdev); FSAL_SET_MASK(fsalattr->mask, ATTR_RAWDEV); return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * FSAL_access : * Tests whether the user or entity identified by the p_context structure * can access the object identified by object_handle, * as indicated by the access_type parameter. * * \param object_handle (input): * The handle of the object to test permissions on. * \param p_context (input): * Authentication context for the operation (export entry, user,...). * \param access_type (input): * Indicates the permissions to be tested. * This is an inclusive OR of the permissions * to be checked for the user specified by p_context. * Permissions constants are : * - FSAL_R_OK : test for read permission * - FSAL_W_OK : test for write permission * - FSAL_X_OK : test for exec permission * - FSAL_F_OK : test for file existence * \param object_attributes (optional input/output): * The post operation 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). * Can be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error, asked permission is granted) * - ERR_FSAL_ACCESS (object permissions doesn't fit asked access type) * - ERR_FSAL_STALE (object_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes when something anormal occurs. */ fsal_status_t SNMPFSAL_access(fsal_handle_t * object_handle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_accessflags_t access_type, /* IN */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { fsal_attrib_list_t attrs; fsal_status_t st; /* sanity checks. * note : object_attributes is optional in FSAL_access. */ if(!object_handle || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access); FSAL_CLEAR_MASK(attrs.asked_attributes); FSAL_SET_MASK(attrs.asked_attributes, global_fs_info.supported_attrs); st = SNMPFSAL_getattrs(object_handle, p_context, &attrs); if(FSAL_IS_ERROR(st)) Return(st.major, st.minor, INDEX_FSAL_access); /* set attributes if needed, then call test_access. */ if(object_attributes) { *object_attributes = attrs; } st = SNMPFSAL_test_access(p_context, access_type, &attrs); Return(st.major, st.minor, INDEX_FSAL_access); }
/** * @brief Get file attributes from PanFS * * Get the attributes and convert them into VFS FSAL attributes * * @param[in] panfs_hdl PanFS Object handle to operate on * @param[in] fd Open FD to operate on * @param[in,out] attrib Attributes to get / storage for attributes * @return ERR_FSAL_NO_ERROR on success, other error code on failure */ fsal_status_t PanFS_getattrs(struct panfs_fsal_obj_handle *panfs_hdl, int fd, struct attrlist *attrib) { fsal_status_t st; struct pan_attrs pattrs; struct pan_fs_ace_s paces[PAN_FS_ACL_LEN_MAX]; pattrs.acls.naces = PAN_FS_ACL_LEN_MAX; pattrs.acls.aces = paces; st = panfs_um_get_attr(fd, &pattrs); if (FSAL_IS_ERROR(st)) { FSAL_UNSET_MASK(attrib->mask, ATTR_ACL); attrib->acl = NULL; return fsalstat(ERR_FSAL_NO_ERROR, 0); /*return st;*/ } st = panfs_acl_2_fsal_acl(&pattrs.acls, attrib); if (FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(attrib->mask); FSAL_SET_MASK(attrib->mask, ATTR_RDATTR_ERR); return st; } return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * FSAL_mkdir: * Create a directory. * * \param parent_directory_handle (input): * Handle of the parent directory where * the subdirectory is to be created. * \param p_dirname (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 object_handle (output): * Pointer to the handle of the created directory. * \param 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) * - ERR_FSAL_STALE (parent_directory_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ... * * NB: if getting postop attributes failed, * the function does not return an error * but the FSAL_ATTR_RDATTR_ERR bit is set in * the object_attributes->asked_attributes field. */ fsal_status_t ZFSFSAL_mkdir(zfsfsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_dirname, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ zfsfsal_handle_t * object_handle, /* OUT */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; mode_t unix_mode; /* sanity checks. * note : object_attributes is optional. */ if(!parent_directory_handle || !p_context || !object_handle || !p_dirname) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir); /* convert fsal args to ZFS args */ unix_mode = fsal2unix_mode(accessmode); /* Applying FSAL umask */ unix_mode = unix_mode & ~global_fs_info.umask; TakeTokenFSCall(); /* Create the directory */ inogen_t object; rc = libzfswrap_mkdir(p_context->export_context->p_vfs, &p_context->user_credential.cred, parent_directory_handle->data.zfs_handle, p_dirname->name, unix_mode, &object); ReleaseTokenFSCall(); /* >> interpret returned error << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_create); /* set output handle */ object_handle->data.zfs_handle = object; object_handle->data.type = FSAL_TYPE_DIR; if(object_attributes) { /**@TODO: skip this => libzfswrap_mkdir might return attributes */ fsal_status_t status = ZFSFSAL_getattrs(object_handle, p_context, object_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(object_attributes->asked_attributes); FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mkdir); }
void posix2fsal_attributes(const struct stat *buffstat, struct attrlist *fsalattr) { FSAL_CLEAR_MASK(fsalattr->mask); /* Fills the output struct */ fsalattr->type = posix2fsal_type(buffstat->st_mode); FSAL_SET_MASK(fsalattr->mask, ATTR_TYPE); fsalattr->filesize = buffstat->st_size; FSAL_SET_MASK(fsalattr->mask, ATTR_SIZE); fsalattr->fsid = posix2fsal_fsid(buffstat->st_dev); FSAL_SET_MASK(fsalattr->mask, ATTR_FSID); fsalattr->fileid = buffstat->st_ino; FSAL_SET_MASK(fsalattr->mask, ATTR_FILEID); fsalattr->mode = unix2fsal_mode(buffstat->st_mode); FSAL_SET_MASK(fsalattr->mask, ATTR_MODE); fsalattr->numlinks = buffstat->st_nlink; FSAL_SET_MASK(fsalattr->mask, ATTR_NUMLINKS); fsalattr->owner = buffstat->st_uid; FSAL_SET_MASK(fsalattr->mask, ATTR_OWNER); fsalattr->group = buffstat->st_gid; FSAL_SET_MASK(fsalattr->mask, ATTR_GROUP); /* Use full timer resolution */ #ifdef LINUX fsalattr->atime = buffstat->st_atim; fsalattr->ctime = buffstat->st_ctim; fsalattr->mtime = buffstat->st_mtim; fsalattr->chgtime = (gsh_time_cmp(&buffstat->st_mtim, &buffstat->st_ctim) > 0) ? fsalattr->mtime : fsalattr->ctime; #elif FREEBSD fsalattr->atime = buffstat->st_atimespec; fsalattr->ctime = buffstat->st_ctimespec; fsalattr->mtime = buffstat->st_mtimespec; fsalattr->chgtime = (gsh_time_cmp(&buffstat->st_mtimespec, &buffstat->st_ctimespec) > 0) ? fsalattr->mtime : fsalattr->ctime; #endif FSAL_SET_MASK(fsalattr->mask, ATTR_ATIME); FSAL_SET_MASK(fsalattr->mask, ATTR_CTIME); FSAL_SET_MASK(fsalattr->mask, ATTR_MTIME); fsalattr->change = timespec_to_nsecs(&fsalattr->chgtime); FSAL_SET_MASK(fsalattr->mask, ATTR_CHGTIME); fsalattr->spaceused = buffstat->st_blocks * S_BLKSIZE; FSAL_SET_MASK(fsalattr->mask, ATTR_SPACEUSED); fsalattr->rawdev = posix2fsal_devt(buffstat->st_rdev); FSAL_SET_MASK(fsalattr->mask, ATTR_RAWDEV); }
fsal_status_t SNMPFSAL_readlink(snmpfsal_handle_t * linkhandle, /* IN */ snmpfsal_op_context_t * p_context, /* IN */ fsal_path_t * p_link_content, /* OUT */ fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ ) { int rc; fsal_status_t st; char link_content_out[FSAL_MAX_PATH_LEN]; /* sanity checks. * note : link_attributes is optional. */ if(!linkhandle || !p_context || !p_link_content) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink); TakeTokenFSCall(); /* >> call your filesystem readlink function << */ ReleaseTokenFSCall(); /* >> convert error code and return on error << */ /* >> convert fs output to fsal_path_t * for example, if this is a char * (link_content_out) : */ st = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content); if(FSAL_IS_ERROR(st)) Return(st.major, st.minor, INDEX_FSAL_readlink); /* retrieves object attributes, if asked */ if(link_attributes) { fsal_status_t status; status = SNMPFSAL_getattrs(linkhandle, p_context, link_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(link_attributes->asked_attributes); FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink); }
fsal_status_t ZFSFSAL_readlink(zfsfsal_handle_t * linkhandle, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_path_t * p_link_content, /* OUT */ fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ ) { int rc; fsal_status_t st; char link_content_out[FSAL_MAX_PATH_LEN]; /* sanity checks. * note : link_attributes is optional. */ if(!linkhandle || !p_context || !p_link_content) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink); TakeTokenFSCall(); rc = libzfswrap_readlink(p_context->export_context->p_vfs, &p_context->user_credential.cred, linkhandle->data.zfs_handle, link_content_out, sizeof(link_content_out)); ReleaseTokenFSCall(); /* >> convert error code and return on error << */ /* >> convert fs output to fsal_path_t * for example, if this is a char * (link_content_out) : */ st = FSAL_str2path(link_content_out, FSAL_MAX_PATH_LEN, p_link_content); if(FSAL_IS_ERROR(st)) Return(st.major, st.minor, INDEX_FSAL_readlink); /* retrieves object attributes, if asked */ if(link_attributes) { fsal_status_t status; status = ZFSFSAL_getattrs(linkhandle, p_context, link_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(link_attributes->asked_attributes); FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink); }
fsal_status_t FUSEFSAL_truncate(fsal_handle_t *handle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_size_t length, /* IN */ fsal_file_t * file_descriptor, /* Unused in this FSAL */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; char object_path[FSAL_MAX_PATH_LEN]; fusefsal_handle_t * filehandle = (fusefsal_handle_t *)handle; /* sanity checks. * note : object_attributes is optional. */ if(!filehandle || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate); if(!p_fs_ops->truncate) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_truncate); /* get the full path for the object */ rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator, object_path); if(rc) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_truncate); /* set context for the next operation, so it can be retrieved by FS thread */ fsal_set_thread_context(p_context); TakeTokenFSCall(); rc = p_fs_ops->truncate(object_path, (off_t) length); ReleaseTokenFSCall(); if(rc) Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_truncate); if(object_attributes) { fsal_status_t st; st = FUSEFSAL_getattrs(handle, p_context, object_attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(object_attributes->asked_attributes); FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* No error occured */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate); }
fsal_status_t ZFSFSAL_symlink(zfsfsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_linkname, /* IN */ fsal_path_t * p_linkcontent, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN (ignored) */ zfsfsal_handle_t * link_handle, /* OUT */ fsal_attrib_list_t * link_attributes /* [ IN/OUT ] */ ) { int rc; /* sanity checks. * note : link_attributes is optional. */ if(!parent_directory_handle || !p_context || !link_handle || !p_linkname || !p_linkcontent) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink); /* Tests if symlinking is allowed by configuration. */ if(!global_fs_info.symlink_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink); TakeTokenFSCall(); inogen_t object; rc = libzfswrap_symlink(p_context->export_context->p_vfs, &p_context->user_credential.cred, parent_directory_handle->data.zfs_handle, p_linkname->name, p_linkcontent->path, &object); ReleaseTokenFSCall(); /* >> convert status and return on error << */ /* >> set output handle << */ link_handle->data.zfs_handle = object; link_handle->data.type = FSAL_TYPE_LNK; if(link_attributes) { fsal_status_t status = ZFSFSAL_getattrs(link_handle, p_context, link_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(link_attributes->asked_attributes); FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink); }
/** * 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, export...). * \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 (optionnal input/output): * The postop 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). * Can be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_STALE (parent_directory_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ... * * NB: if getting postop attributes failed, * the function does not return an error * but the FSAL_ATTR_RDATTR_ERR bit is set in * the object_attributes->asked_attributes field. */ fsal_status_t ZFSFSAL_create(zfsfsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_filename, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ zfsfsal_handle_t * object_handle, /* OUT */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; /* sanity checks. * note : object_attributes is optional. */ if(!parent_directory_handle || !p_context || !object_handle || !p_filename) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); /* >> convert fsal args to your fs args. * Don't forget applying FSAL umask : * mode = mode & ~global_fs_info.umask << */ TakeTokenFSCall(); inogen_t object; rc = libzfswrap_create(p_context->export_context->p_vfs, &p_context->user_credential.cred, parent_directory_handle->data.zfs_handle, p_filename->name, fsal2unix_mode(accessmode), &object); ReleaseTokenFSCall(); /* >> interpret returned error << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_create); /* >> set output handle << */ object_handle->data.zfs_handle = object; object_handle->data.type = FSAL_TYPE_FILE; if(object_attributes) { fsal_status_t status = ZFSFSAL_getattrs(object_handle, p_context, object_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(object_attributes->asked_attributes); FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create); }
/** * FSAL_link: * Create a hardlink. * * \param exttarget (input): * Handle of the target object. * \param extdir (input): * Pointer to the directory handle where * the hardlink is to be created. * \param link_name (input): * Pointer to the name of the hardlink to be created. * \param extcontext (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 attributes (optionnal input/output): * The post_operation attributes of the linked 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). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_STALE (target or dir does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ... * * NB: if getting postop attributes failed, * the function does not return an error * but the FSAL_ATTR_RDATTR_ERR bit is set in * the attributes->asked_attributes field. */ fsal_status_t CEPHFSAL_link(fsal_handle_t * exttarget, fsal_handle_t * extdir, fsal_name_t * link_name, fsal_op_context_t * extcontext, fsal_attrib_list_t * attributes) { int rc; struct stat st; char strname[FSAL_MAX_NAME_LEN]; cephfsal_handle_t* target = (cephfsal_handle_t*) exttarget; cephfsal_handle_t* dir = (cephfsal_handle_t*) extdir; cephfsal_op_context_t* context = (cephfsal_op_context_t*) context; struct ceph_mount_info *cmount = context->export_context->cmount; int uid = FSAL_OP_CONTEXT_TO_UID(context); int gid = FSAL_OP_CONTEXT_TO_GID(context); /* sanity checks. * note : attributes is optional. */ if(!target || !dir || !context || !link_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link); memset(target, 0, sizeof(cephfsal_handle_t)); /* Tests if hardlinking is allowed by configuration. */ if(!global_fs_info.link_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link); FSAL_name2str(link_name, strname, FSAL_MAX_NAME_LEN); TakeTokenFSCall(); rc = ceph_ll_link(cmount, VINODE(target), VINODE(dir), strname, &st, uid, gid); ReleaseTokenFSCall(); if (rc < 0) Return(posix2fsal_error(rc), 0, INDEX_FSAL_link); if(attributes) { fsal_status_t status; status = posix2fsal_attributes(&st, attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(attributes->asked_attributes); FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); }
/** * GPFSFSAL_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 GPFSFSAL_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; gpfsfsal_xstat_t buffxstat; #ifdef _USE_NFS4_ACL fsal_accessflags_t access_mask = 0; #endif /* sanity checks. * note : object_attributes is mandatory in GPFSFSAL_getattrs. */ if(!p_filehandle || !p_context || !p_object_attributes) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); TakeTokenFSCall(); st = fsal_get_xstat_by_handle(p_context, p_filehandle, &buffxstat); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(st)) ReturnStatus(st, INDEX_FSAL_getattrs); /* convert attributes */ st = gpfsfsal_xstat_2_fsal_attributes(&buffxstat, 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); } #ifdef _USE_NFS4_ACL if(p_object_attributes->acl) { /* Check permission to get attributes and ACL. */ access_mask = FSAL_MODE_MASK_SET(0) | /* Dummy */ FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_ATTR | FSAL_ACE_PERM_READ_ACL); st = fsal_internal_testAccess(p_context, access_mask, NULL, p_object_attributes); if(FSAL_IS_ERROR(st)) ReturnStatus(st, INDEX_FSAL_getattrs); } #endif Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs); }
/* * Common code used by fsal_lookup and fsal_readdir - * given the name try to stat an entry. If an entry is * regular file or directory then open it and use fd2handle * to get a real handle, otherwise use inum2handle to fake * a handle. */ fsal_status_t xfsfsal_stat_by_name(fsal_op_context_t * context, int atfd, const char *name, fsal_handle_t *handle, fsal_attrib_list_t * attributes) { int rc; int errsv; struct stat buffstat; fsal_status_t st; TakeTokenFSCall(); rc = fstatat(atfd, name, &buffstat, AT_SYMLINK_NOFOLLOW); errsv = errno; ReleaseTokenFSCall(); if(rc < 0) ReturnCode(posix2fsal_error(errsv), errsv); if(S_ISDIR(buffstat.st_mode) || S_ISREG(buffstat.st_mode)) { int tmpfd; TakeTokenFSCall(); tmpfd = openat(atfd, name, O_RDONLY | O_NOFOLLOW, 0600); errsv = errno; ReleaseTokenFSCall(); if(tmpfd < 0) ReturnCode(posix2fsal_error(errsv), errsv); st = fsal_internal_fd2handle(context, tmpfd, handle); close(tmpfd); } else { st = fsal_internal_inum2handle(context, buffstat.st_ino, handle); } if(FSAL_IS_ERROR(st)) return st; if(attributes) { st = posix2fsal_attributes(&buffstat, attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(attributes->asked_attributes); FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } return st; }
/** * FSAL_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 XFSFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_object_attributes /* IN/OUT */ ) { int rc, errsv; fsal_status_t st; int fd; struct stat buffstat; /* sanity checks. * note : object_attributes is mandatory in FSAL_getattrs. */ if(!p_filehandle || !p_context || !p_object_attributes) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); TakeTokenFSCall(); st = fsal_internal_handle2fd(p_context, p_filehandle, &fd, O_RDONLY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(st)) ReturnStatus(st, INDEX_FSAL_getattrs); /* get file metadata */ TakeTokenFSCall(); rc = fstat(fd, &buffstat); errsv = errno; ReleaseTokenFSCall(); close(fd); if(rc != 0) { if(errsv == ENOENT) Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_getattrs); else 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_link: * Create a hardlink. * * \param target_handle (input): * Handle of the target object. * \param dir_handle (input): * Pointer to the directory handle where * the hardlink is to be created. * \param p_link_name (input): * Pointer to the name of the hardlink 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 attributes (optionnal input/output): * The post_operation attributes of the linked 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). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_STALE (target_handle or dir_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ... * * NB: if getting postop attributes failed, * the function does not return an error * but the FSAL_ATTR_RDATTR_ERR bit is set in * the attributes->asked_attributes field. */ fsal_status_t ZFSFSAL_link(zfsfsal_handle_t * target_handle, /* IN */ zfsfsal_handle_t * dir_handle, /* IN */ fsal_name_t * p_link_name, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * attributes /* [ IN/OUT ] */ ) { int rc; /* sanity checks. * note : attributes is optional. */ if(!target_handle || !dir_handle || !p_context || !p_link_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link); /* Tests if hardlinking is allowed by configuration. */ if(!global_fs_info.link_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link); TakeTokenFSCall(); rc = libzfswrap_link(p_context->export_context->p_vfs, &p_context->user_credential.cred, dir_handle->data.zfs_handle, target_handle->data.zfs_handle, p_link_name->name); ReleaseTokenFSCall(); /* >> interpret returned error << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_link); if(attributes) { fsal_status_t status = ZFSFSAL_getattrs(target_handle, p_context, attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(attributes->asked_attributes); FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); }
/** * FSAL_readlink: * Read the content of a symbolic link. * * \param dir_hdl (input): * Handle of the link to be read. * \param p_context (input): * Authentication context for the operation (user,...). * \param p_link_content (output): * Pointer to an fsal path structure where * the link content is to be stored.. * \param link_len (input/output): * In pointer to len of content buff. . Out actual len of content. * \param link_attributes (optionnal input/output): * The post operation attributes of the symlink link. * 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_readlink(struct fsal_obj_handle *dir_hdl, /* IN */ const struct req_op_context *p_context, /* IN */ char *p_link_content, /* OUT */ size_t *link_len, /* IN/OUT */ struct attrlist *p_link_attributes) { /* IN/OUT */ fsal_status_t status; struct pt_fsal_obj_handle *pt_hdl; char link_content_out[PATH_MAX]; /* sanity checks. * note : link_attributes is optional. */ if (!dir_hdl || !p_context || !p_link_content) return fsalstat(ERR_FSAL_FAULT, 0); pt_hdl = container_of(dir_hdl, struct pt_fsal_obj_handle, obj_handle); memset(link_content_out, 0, sizeof(link_content_out)); /* Read the link on the filesystem */ status = fsal_readlink_by_handle(p_context, p_context->fsal_export, pt_hdl->handle, p_link_content, *link_len); if (FSAL_IS_ERROR(status)) return status; /* retrieves object attributes, if asked */ if (p_link_attributes) { status = PTFSAL_getattrs(p_context->fsal_export, p_context, pt_hdl->handle, p_link_attributes); /* On error, we set a flag in the returned attributes */ if (FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_link_attributes->mask); FSAL_SET_MASK(p_link_attributes->mask, ATTR_RDATTR_ERR); } } return fsalstat(ERR_FSAL_NO_ERROR, 0); }
/** * FSAL_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 LUSTREFSAL_getattrs(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_object_attributes /* IN/OUT */ ) { int rc; fsal_status_t st; fsal_path_t fsalpath; struct stat buffstat; /* sanity checks. * note : object_attributes is mandatory in FSAL_getattrs. */ if(!p_filehandle || !p_context || !p_object_attributes) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs); /* get the path of the file */ st = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath); if(FSAL_IS_ERROR(st)) ReturnStatus(st, INDEX_FSAL_getattrs); /* get file metadata */ TakeTokenFSCall(); rc = lstat(fsalpath.path, &buffstat); ReleaseTokenFSCall(); if(rc != 0) { rc = errno; if(rc == ENOENT) Return(ERR_FSAL_STALE, rc, INDEX_FSAL_getattrs); else Return(posix2fsal_error(rc), rc, 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_opendir : * Opens a directory for reading its content. * * \param exthandle (input) * the handle of the directory to be opened. * \param extcontext (input) * Permission context for the operation (user, export context...). * \param extdescriptor (output) * pointer to an allocated structure that will receive * directory stream informations, on successfull completion. * \param attributes (optional output) * On successfull completion,the structure pointed * by dir_attributes receives the new directory attributes. * Can be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_ACCESS (user does not have read permission on directory) * - ERR_FSAL_STALE (exthandle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t CEPHFSAL_opendir(fsal_handle_t * exthandle, fsal_op_context_t * extcontext, fsal_dir_t * extdescriptor, fsal_attrib_list_t * dir_attributes) { cephfsal_handle_t* handle = (cephfsal_handle_t*) exthandle; cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext; cephfsal_dir_t* descriptor = (cephfsal_dir_t*) extdescriptor; fsal_status_t status; int rc; int uid = FSAL_OP_CONTEXT_TO_UID(context); int gid = FSAL_OP_CONTEXT_TO_GID(context); struct ceph_dir_result *dh; /* sanity checks * note : dir_attributes is optional. */ if(!handle || !context || !descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); TakeTokenFSCall(); /* XXX ceph_ll_opendir has void in the interface, but Client::ll_opendir * is using dir_result_t. */ rc = ceph_ll_opendir(context->export_context->cmount, VINODE(handle), (void *) &dh, uid, gid); ReleaseTokenFSCall(); if (rc < 0) Return(posix2fsal_error(rc), 0, INDEX_FSAL_opendir); descriptor->dh = dh; descriptor->vi = VINODE(handle); descriptor->ctx = *context; if(dir_attributes) { status = CEPHFSAL_getattrs(exthandle, extcontext, dir_attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(dir_attributes->asked_attributes); FSAL_SET_MASK(dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); }
static fsal_status_t getattrs(struct fsal_obj_handle *obj_hdl, struct attrlist *attrs) { struct gpfs_fsal_obj_handle *myself; fsal_status_t status; myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); status = GPFSFSAL_getattrs(op_ctx->fsal_export, obj_hdl->fs->private_data, op_ctx, myself->handle, attrs); if (FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(attrs->mask); FSAL_SET_MASK(attrs->mask, ATTR_RDATTR_ERR); } return status; }
fsal_status_t GPFSFSAL_lookupPath(fsal_path_t * p_path, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_handle_t * object_handle, /* OUT */ fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ ) { fsal_status_t status; /* sanity checks * note : object_attributes is optionnal. */ if(!object_handle || !p_context || !p_path) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupPath); /* test whether the path begins with a slash */ if(p_path->path[0] != '/') Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupPath); /* directly call the lookup function */ status = fsal_internal_get_handle(p_context, p_path, object_handle); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_lookupPath); /* get object attributes */ if(p_object_attributes) { status = GPFSFSAL_getattrs(object_handle, p_context, p_object_attributes); 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); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath); }
fsal_status_t SNMPFSAL_setattrs(fsal_handle_t * filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * attrib_set, /* IN */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; fsal_status_t status; fsal_attrib_list_t attrs; /* sanity checks. * note : object_attributes is optional. */ if(!filehandle || !p_context || !attrib_set) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs); /* no attributes can be set in SNMP */ if(attrs.asked_attributes != 0) { Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs); } if(object_attributes) { status = SNMPFSAL_getattrs(filehandle, p_context, object_attributes); /* on error, we set a special bit in the mask. */ 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_setattrs); }
/** * 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); }
/** * 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_opendir : * Opens a directory for reading its content. * * \param dir_handle (input) * the handle of the directory to be opened. * \param p_context (input) * Permission context for the operation (user, export context...). * \param dir_descriptor (output) * pointer to an allocated structure that will receive * directory stream informations, on successfull completion. * \param dir_attributes (optional output) * On successfull completion,the structure pointed * by dir_attributes receives the new directory attributes. * Can be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_ACCESS (user does not have read permission on directory) * - ERR_FSAL_STALE (dir_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t SNMPFSAL_opendir(fsal_handle_t * dir_handle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_dir_t * dir_descriptor, /* OUT */ fsal_attrib_list_t * dir_attributes /* [ IN/OUT ] */ ) { fsal_status_t st; /* sanity checks * note : dir_attributes is optionnal. */ if(!dir_handle || !p_context || !dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); /* check it is a node... */ if(((snmpfsal_handle_t *)dir_handle)->data.object_type_reminder == FSAL_NODETYPE_LEAF) Return(ERR_FSAL_NOTDIR, 0, INDEX_FSAL_opendir); /* save request info to the dir_dircriptor */ memcpy(&((snmpfsal_dir_t *)dir_descriptor)->node_handle, (snmpfsal_handle_t *)dir_handle, sizeof(snmpfsal_handle_t)); ((snmpfsal_dir_t *)dir_descriptor)->p_context = (snmpfsal_op_context_t *)p_context; if(dir_attributes && dir_attributes->asked_attributes) { st = SNMPFSAL_getattrs(dir_handle, p_context, dir_attributes); if(FSAL_IS_ERROR(st)) { FSAL_CLEAR_MASK(dir_attributes->asked_attributes); FSAL_SET_MASK(dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); }
/** * 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_status_t GPFSFSAL_unlink(struct fsal_obj_handle *dir_hdl, /* IN */ const char *p_object_name, /* IN */ const struct req_op_context *p_context, /* IN */ struct attrlist *p_parent_attributes) { /* IN/OUT */ fsal_status_t status; gpfsfsal_xstat_t buffxstat; int mount_fd; struct gpfs_fsal_obj_handle *gpfs_hdl; /* sanity checks. */ if (!dir_hdl || !p_context || !p_object_name) return fsalstat(ERR_FSAL_FAULT, 0); gpfs_hdl = container_of(dir_hdl, struct gpfs_fsal_obj_handle, obj_handle); mount_fd = gpfs_get_root_fd(dir_hdl->export); /* build the child path */ /* get file metadata */ status = fsal_internal_stat_name(mount_fd, gpfs_hdl->handle, p_object_name, &buffxstat.buffstat); if (FSAL_IS_ERROR(status)) return status; /****************************** * DELETE FROM THE FILESYSTEM * ******************************/ fsal_set_credentials(p_context->creds); status = fsal_internal_unlink(mount_fd, gpfs_hdl->handle, p_object_name, &buffxstat.buffstat); fsal_restore_ganesha_credentials(); if (FSAL_IS_ERROR(status)) return status; /*********************** * FILL THE ATTRIBUTES * ***********************/ if (p_parent_attributes) { buffxstat.attr_valid = XATTR_STAT; status = gpfsfsal_xstat_2_fsal_attributes(&buffxstat, p_parent_attributes); if (FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_parent_attributes->mask); FSAL_SET_MASK(p_parent_attributes->mask, ATTR_RDATTR_ERR); } } /* OK */ return fsalstat(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t FSAL_proxy_truncate_stateless(proxyfsal_handle_t * filehandle, /* IN */ proxyfsal_op_context_t * p_context, /* IN */ fsal_size_t length, /* IN */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; COMPOUND4args argnfs4; COMPOUND4res resnfs4; nfs_fh4 nfs4fh; fsal_status_t fsal_status; fsal_attrib_list_t open_attrs; bitmap4 inbitmap; bitmap4 convert_bitmap; uint32_t inbitmap_val[2]; uint32_t bitmap_res[2]; uint32_t bitmap_set[2]; uint32_t bitmap_conv_val[2]; #define FSAL_TRUNCATE_STATELESS_NB_OP_ALLOC 3 nfs_argop4 argoparray[FSAL_TRUNCATE_STATELESS_NB_OP_ALLOC]; nfs_resop4 resoparray[FSAL_TRUNCATE_STATELESS_NB_OP_ALLOC]; fsal_attrib_list_t fsal_attr_set; fattr4 fattr_set; fsal_proxy_internal_fattr_t fattr_internal; struct timeval timeout = { 25, 0 }; /* sanity checks. * note : object_attributes is optional. */ if(!filehandle || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate); if(filehandle->data.object_type_reminder != FSAL_TYPE_FILE) { Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate); } /* Setup results structures */ argnfs4.argarray.argarray_val = argoparray; resnfs4.resarray.resarray_val = resoparray; fsal_internal_proxy_setup_fattr(&fattr_internal); argnfs4.minorversion = 0; /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Truncate" ; */ argnfs4.tag.utf8string_val = NULL; argnfs4.tag.utf8string_len = 0; argnfs4.argarray.argarray_len = 0; /* Get NFSv4 File handle */ if(fsal_internal_proxy_extract_fh(&nfs4fh, filehandle) == FALSE) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate); /* Get prepared for truncate */ fsal_attr_set.asked_attributes = FSAL_ATTR_SIZE; fsal_attr_set.filesize = length; convert_bitmap.bitmap4_val = bitmap_conv_val; convert_bitmap.bitmap4_len = 2; fsal_interval_proxy_fsalattr2bitmap4(&fsal_attr_set, &convert_bitmap); if(nfs4_FSALattr_To_Fattr(NULL, /* no exportlist required here */ &fsal_attr_set, &fattr_set, NULL, /* no compound data required here */ NULL, /* No fh here, filehandle is not a settable attribute */ &convert_bitmap) == -1) Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_truncate); inbitmap.bitmap4_val = inbitmap_val; inbitmap.bitmap4_len = 2; fsal_internal_proxy_create_fattr_bitmap(&inbitmap); #define FSAL_TRUNCATE_STATELESS_IDX_OP_PUTFH 0 #define FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR 1 #define FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR 2 COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh); COMPOUNDV4_ARG_ADD_OP_SETATTR(argnfs4, fattr_set); COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, inbitmap); /* For ATTR_SIZE, stateid is needed, we use the stateless "all-0's" stateid here */ argnfs4.argarray.argarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].nfs_argop4_u. opsetattr.stateid.seqid = 0; memset(argnfs4.argarray.argarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR]. nfs_argop4_u.opsetattr.stateid.other, 0, 12); resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u. opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u. opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u. opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val = (char *)&fattr_internal; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u. opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len = sizeof(fattr_internal); resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].nfs_resop4_u. opsetattr.attrsset.bitmap4_val = bitmap_set; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].nfs_resop4_u. opsetattr.attrsset.bitmap4_len = 2; TakeTokenFSCall(); COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc); if(rc != RPC_SUCCESS) { ReleaseTokenFSCall(); Return(ERR_FSAL_IO, 0, INDEX_FSAL_truncate); } ReleaseTokenFSCall(); if(resnfs4.status != NFS4_OK) return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_truncate); /* >> interpret error code << */ /* >> Optionnaly retrieve post op attributes * If your filesystem truncate call can't return them, * you can proceed like this : << */ if(object_attributes) { if(nfs4_Fattr_To_FSAL_attr(object_attributes, &resnfs4.resarray.resarray_val [FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR]. nfs_resop4_u.opgetattr.GETATTR4res_u.resok4. obj_attributes) != 1) { FSAL_CLEAR_MASK(object_attributes->asked_attributes); FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate); } } /* No error occured */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate); } /* FSAL_proxy_truncate_stateless */
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_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); }