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); }
/** * * MFSL_setattrs_check_perms : Checks authorization to perform an asynchronous setattr. * * Checks authorization to perform an asynchronous setattr. * * @param filehandle [IN] mfsl object to be operated on. * @param pspecdata [INOUT] mfsl object associated specific data * @param p_context [IN] associated fsal context * @param p_mfsl_context [INOUT] associated mfsl context * @param attrib_set [IN] attributes to be set * * @return always FSAL_NO_ERROR (not yet implemented */ fsal_status_t MFSL_setattrs_check_perms(mfsl_object_t * filehandle, /* IN */ mfsl_object_specific_data_t * pspecdata, /* IN */ fsal_op_context_t * p_context, /* IN */ mfsl_context_t * p_mfsl_context, /* IN */ fsal_attrib_list_t * attrib_set /* IN */ ) { fsal_status_t fsal_status; /* Root is the only one that can chown or chgrp */ if(attrib_set->asked_attributes & (FSAL_ATTR_OWNER | FSAL_ATTR_GROUP)) { if(p_context->user_credential.user != 0) MFSL_return(ERR_FSAL_ACCESS, 0); } fsal_status = FSAL_setattr_access(p_context, attrib_set, &pspecdata->async_attr); if(FSAL_IS_ERROR(fsal_status)) return fsal_status; MFSL_return(ERR_FSAL_NO_ERROR, 0); } /* MFSL_setattr_check_perms */
/** * 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 FUSEFSAL_open_by_name(fsal_handle_t * dirhandle, /* IN */ fsal_name_t * filename, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_descriptor, /* OUT */ fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ ) { fsal_status_t fsal_status; fsal_handle_t filehandle; if(!dirhandle || !filename || !p_context || !file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name); fsal_status = FUSEFSAL_lookup(dirhandle, filename, p_context, &filehandle, file_attributes); if(FSAL_IS_ERROR(fsal_status)) return fsal_status; return FUSEFSAL_open(&filehandle, p_context, openflags, file_descriptor, file_attributes); }
/** * FSAL_Init : Initializes the FileSystem Abstraction Layer. * * \param init_info (input, fsal_parameter_t *) : * Pointer to a structure that contains * all initialization parameters for the FSAL. * Specifically, it contains settings about * the filesystem on which the FSAL is based, * security settings, logging policy and outputs, * and other general FSAL options. * * \return Major error codes : * ERR_FSAL_NO_ERROR (initialisation OK) * ERR_FSAL_FAULT (init_info pointer is null) * ERR_FSAL_SERVERFAULT (misc FSAL error) * ERR_FSAL_ALREADY_INIT (The FS is already initialized) * ERR_FSAL_BAD_INIT (FS specific init error, * minor error code gives the reason * for this error.) * ERR_FSAL_SEC_INIT (Security context init error). */ fsal_status_t VFSFSAL_Init(fsal_parameter_t * init_info /* IN */ ) { fsal_status_t status; /* sanity check. */ if(!init_info) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init); /* proceeds FSAL internal initialization */ status = fsal_internal_init_global(&(init_info->fsal_info), &(init_info->fs_common_info), & (init_info->fs_specific_info)); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_Init); /* Regular exit */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init); }
/** * 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); }
/** * Get the attributes of an extended attribute from its index. * * \param p_objecthandle Handle of the object you want to get attribute for. * \param p_context pointer to the current security context. * \param xattr_cookie xattr's cookie (as returned by listxattrs). * \param p_attrs xattr's attributes. */ fsal_status_t FSAL_GetXAttrAttrs(fsal_handle_t * p_objecthandle, /* IN */ fsal_op_context_t * p_context, /* IN */ unsigned int xattr_id, /* IN */ fsal_attrib_list_t * p_attrs /**< IN/OUT xattr attributes (if supported) */ ) { int rc; char buff[MAXNAMLEN]; fsal_status_t st; fsal_attrib_list_t file_attrs; /* sanity checks */ if(!p_objecthandle || !p_context || !p_attrs) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrAttrs); /* object attributes we want to retrieve from parent */ file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID; /* don't retrieve attributes not asked */ file_attrs.asked_attributes &= p_attrs->asked_attributes; st = FSAL_getattrs(p_objecthandle, p_context, &file_attrs); if(FSAL_IS_ERROR(st)) Return(st.major, st.minor, INDEX_FSAL_GetXAttrAttrs); if((rc = file_attributes_to_xattr_attrs(&file_attrs, p_attrs, xattr_id))) { Return(ERR_FSAL_INVAL, rc, INDEX_FSAL_GetXAttrAttrs); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrAttrs); } /* FSAL_GetXAttrAttrs */
/** * 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); }
cache_inode_status_t cache_inode_statfs(cache_entry_t *entry, fsal_dynamicfsinfo_t *dynamicinfo, fsal_op_context_t *context, cache_inode_status_t *status) { fsal_status_t fsal_status = {0, 0}; /* Sanity check */ if(!entry || !context || !dynamicinfo || !status) { *status = CACHE_INODE_INVALID_ARGUMENT; return *status; } /* Default return value */ *status = CACHE_INODE_SUCCESS; /* Get FSAL to get dynamic info */ if(FSAL_IS_ERROR ((fsal_status = FSAL_dynamic_fsinfo(&entry->handle, context, dynamicinfo)))) { *status = cache_inode_error_convert(fsal_status); if (fsal_status.major == ERR_FSAL_STALE) { cache_inode_kill_entry(entry); } return *status; } LogFullDebug(COMPONENT_CACHE_INODE, "cache_inode_statfs: dynamicinfo: {total_bytes = %zu, " "free_bytes = %zu, avail_bytes = %zu, total_files = %llu, " "free_files = %llu, avail_files = %llu}", dynamicinfo->total_bytes, dynamicinfo->free_bytes, dynamicinfo->avail_bytes, dynamicinfo->total_files, dynamicinfo->free_files, dynamicinfo->avail_files); return CACHE_INODE_SUCCESS; } /* cache_inode_statfs */
/** * * nfs2_FSALToFhandle: converts a FSAL file handle to a nfs2 file handle. * * Converts a nfs2 file handle to a FSAL file handle. * * @param pfh2 [OUT] pointer to the extracted file handle * @param pfsalhandle [IN] pointer to the FSAL handle to be converted * @param pfsalhandle [IN] pointer to the FSAL handle to be converted * * @return 1 if successful, 0 otherwise * */ int nfs2_FSALToFhandle(fhandle2 * pfh2, fsal_handle_t * pfsalhandle, exportlist_t * pexport) { fsal_status_t fsal_status; file_handle_v2_t file_handle; print_buff(COMPONENT_FILEHANDLE, (char *)pfsalhandle, sizeof(fsal_handle_t)); /* zero-ification of the buffer to be used as handle */ memset(pfh2, 0, NFS2_FHSIZE); memset((caddr_t) &file_handle, 0, sizeof(file_handle_v2_t)); /* Fill in the fs opaque part */ fsal_status = FSAL_DigestHandle(&pexport->FS_export_context, FSAL_DIGEST_NFSV2, pfsalhandle, (caddr_t) & file_handle.fsopaque); if(FSAL_IS_ERROR(fsal_status)) { if( fsal_status.major == ERR_FSAL_TOOSMALL ) LogCrit( COMPONENT_FILEHANDLE, "NFSv2 file handle is too small to manage this fsal" ) ; else LogCrit( COMPONENT_FILEHANDLE, "FSAL_DigestHandle return (%u,%u) when called from %s", fsal_status.major, fsal_status.minor, __func__ ) ; return 0; } /* keep track of the export id */ file_handle.exportid = pexport->id; /* Set the last byte */ file_handle.xattr_pos = 0; /* Set the data */ memcpy((caddr_t) pfh2, &file_handle, sizeof(file_handle_v2_t)); print_fhandle2(COMPONENT_FILEHANDLE, pfh2); return 1; } /* nfs2_FSALToFhandle */
/** * 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); }
fsal_status_t FSAL_get_cookieverf(fsal_handle_t * handle, fsal_op_context_t * p_context, uint64_t * verf) { fsal_status_t rc; msectimer_t timer_start, timer_end; timer_start = timer_get(); if (fsal_functions.fsal_get_cookieverf) { rc = fsal_functions.fsal_get_cookieverf(handle, verf); } else { fsal_attrib_list_t attributes; memset(&attributes, 0, sizeof(fsal_attrib_list_t)); attributes.asked_attributes = FSAL_ATTR_MTIME; rc = FSAL_getattrs(handle, p_context, &attributes); if (!FSAL_IS_ERROR(rc)) { memcpy(verf, &attributes.mtime, sizeof(uint64_t)); ReturnCode(ERR_FSAL_NO_ERROR, 0); } } timer_end = timer_get(); p_context->latency += timer_end - timer_start; p_context->count++; return rc; }
bool make_pseudofs_node(char *name, struct pseudofs_state *state) { struct fsal_obj_handle *new_node = NULL; fsal_status_t fsal_status; bool retried = false; struct attrlist sattr; retry: /* First, try to lookup the entry */ fsal_status = fsal_lookup(state->obj, name, &new_node, NULL); if (!FSAL_IS_ERROR(fsal_status)) { /* Make sure new node is a directory */ if (new_node->type != DIRECTORY) { LogCrit(COMPONENT_EXPORT, "BUILDING PSEUDOFS: Export_Id %d Path %s Pseudo Path %s LOOKUP %s is not a directory", state->export->export_id, state->export->fullpath, state->export->pseudopath, name); /* Release the reference on the new node */ new_node->obj_ops.put_ref(new_node); return false; } LogDebug(COMPONENT_EXPORT, "BUILDING PSEUDOFS: Parent %p entry %p %s FSAL %s already exists", state->obj, new_node, name, new_node->fsal->name); state->obj->obj_ops.put_ref(state->obj); /* Make new node the current node */ state->obj = new_node; return true; }
/** @fn fsal_status_t * GPFSFSAL_open(struct fsal_obj_handle *obj_hdl, * const struct req_op_context *op_ctx, * fsal_openflags_t openflags, int *file_desc, * struct attrlist *fsal_attr) * * @brief Open a regular file for reading/writing its data content. * * @param obj_hdl Handle of the file to be read/modified. * @param op_ctx Authentication context for the operation (user,...). * @param openflags Flags that indicates behavior for file opening and access. * This is an inclusive OR of the following values * ( such of them are not compatible) : * - FSAL_O_RDONLY: opening file for reading only. * - FSAL_O_RDWR: opening file for reading and writing. * - FSAL_O_WRONLY: opening file for writting only. * - FSAL_O_APPEND: always write at the end of the file. * - FSAL_O_TRUNC: truncate the file to 0 on opening. * @param file_desc The file descriptor to be used for FSAL_read/write ops. * * @return ERR_FSAL_NO_ERROR on success, error otherwise */ fsal_status_t GPFSFSAL_open(struct fsal_obj_handle *obj_hdl, const struct req_op_context *op_ctx, int posix_flags, int *file_desc) { struct gpfs_fsal_obj_handle *myself; fsal_status_t status; struct gpfs_fsal_export *exp = container_of(op_ctx->fsal_export, struct gpfs_fsal_export, export); int export_fd = exp->export_fd; /* sanity checks. */ if (!obj_hdl || !file_desc) return fsalstat(ERR_FSAL_FAULT, 0); myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); LogFullDebug(COMPONENT_FSAL, "posix_flags 0x%X export_fd %d", posix_flags, export_fd); fsal_set_credentials(op_ctx->creds); status = fsal_internal_handle2fd(export_fd, myself->handle, file_desc, posix_flags); fsal_restore_ganesha_credentials(); if (FSAL_IS_ERROR(status)) { /** Try open as root access if the above call fails, * permission will be checked somewhere else in the code. */ status = fsal_internal_handle2fd(export_fd, myself->handle, file_desc, posix_flags); } return status; }
/** * 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); }
/** * @brief Create a directory. * * @param dir_hdl Handle of the parent directory * @param dir_name Pointer to the name of the directory to be created. * @param op_ctx Authentication context for the operation (user,...). * @param accessmode Mode for the directory to be created. * @param gpfs_fh Pointer to the handle of the created directory. * @param fsal_attr Attributes of the created directory. * @return ERR_FSAL_NO_ERROR on success, error otherwise * */ fsal_status_t GPFSFSAL_mkdir(struct fsal_obj_handle *dir_hdl, const char *dir_name, const struct req_op_context *op_ctx, uint32_t accessmode, struct gpfs_file_handle *gpfs_fh, struct attrlist *obj_attr) { mode_t unix_mode; fsal_status_t status; /* note : obj_attr is optional. */ if (!dir_hdl || !op_ctx || !gpfs_fh || !dir_name) return fsalstat(ERR_FSAL_FAULT, 0); /* convert FSAL mode to unix mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~op_ctx->fsal_export->exp_ops.fs_umask(op_ctx->fsal_export); /* build new entry path */ /* creates the directory and get its handle */ fsal_set_credentials(op_ctx->creds); status = fsal_internal_create(dir_hdl, dir_name, unix_mode | S_IFDIR, 0, gpfs_fh, NULL); fsal_restore_ganesha_credentials(); if (FSAL_IS_ERROR(status)) return status; /* retrieve file attributes */ return GPFSFSAL_getattrs(op_ctx->fsal_export, dir_hdl->fs->private_data, op_ctx, gpfs_fh, obj_attr); }
/** * FSAL_Init : Initializes the FileSystem Abstraction Layer. * * \param init_info (input, fsal_parameter_t *) : * Pointer to a structure that contains * all initialization parameters for the FSAL. * Specifically, it contains settings about * the filesystem on which the FSAL is based, * security settings, logging policy and outputs, * and other general FSAL options. * * \return Major error codes : * ERR_FSAL_NO_ERROR (initialisation OK) * ERR_FSAL_FAULT (init_info pointer is null) * ERR_FSAL_SERVERFAULT (misc FSAL error) * ERR_FSAL_ALREADY_INIT (The FS is already initialized) * ERR_FSAL_BAD_INIT (FS specific init error, * minor error code gives the reason * for this error.) * ERR_FSAL_SEC_INIT (Security context init error). */ fsal_status_t GPFSFSAL_Init(fsal_parameter_t * init_info /* IN */ ) { char *fshandle; size_t fshandlelen = 0; fsal_status_t status; int rc = 0; /* sanity check. */ if(!init_info) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init); /* save open-by-handle char device */ memcpy(open_by_handle_path, init_info->fs_specific_info.open_by_handle_dev_file, MAXPATHLEN); open_by_handle_fd = open(init_info->fs_specific_info.open_by_handle_dev_file, O_RDONLY); if(open_by_handle_fd < 0) { LogMajor(COMPONENT_FSAL, "FSAL INIT: ERROR: Could not open open-by-handle character device file at %s: rc = %d", init_info->fs_specific_info.open_by_handle_dev_file, errno); ReturnCode(ERR_FSAL_INVAL, 0); } /* proceeds FSAL internal initialization */ status = fsal_internal_init_global(&(init_info->fsal_info), &(init_info->fs_common_info), &(init_info->fs_specific_info)); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_Init); /* Regular exit */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init); }
/** @fn fsal_status_t * GPFSFSAL_open(struct fsal_obj_handle *obj_hdl, * const struct req_op_context *op_ctx, * fsal_openflags_t openflags, int *file_desc, * struct attrlist *fsal_attr, bool reopen) * * @brief Open a regular file for reading/writing its data content. * * @param obj_hdl Handle of the file to be read/modified. * @param op_ctx Authentication context for the operation (user,...). * @param openflags Flags that indicates behavior for file opening and access. * This is an inclusive OR of the following values * ( such of them are not compatible) : * - FSAL_O_RDONLY: opening file for reading only. * - FSAL_O_RDWR: opening file for reading and writing. * - FSAL_O_WRONLY: opening file for writting only. * - FSAL_O_APPEND: always write at the end of the file. * - FSAL_O_TRUNC: truncate the file to 0 on opening. * @param file_desc The file descriptor to be used for FSAL_read/write ops. * * @return ERR_FSAL_NO_ERROR on success, error otherwise */ fsal_status_t GPFSFSAL_open(struct fsal_obj_handle *obj_hdl, const struct req_op_context *op_ctx, int posix_flags, int *file_desc, bool reopen) { struct gpfs_fsal_obj_handle *myself; struct gpfs_filesystem *gpfs_fs; fsal_status_t status; /* sanity checks. */ if (!obj_hdl || !file_desc) return fsalstat(ERR_FSAL_FAULT, 0); myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); gpfs_fs = obj_hdl->fs->private_data; LogFullDebug(COMPONENT_FSAL, "posix_flags 0x%X", posix_flags); status = fsal_internal_handle2fd(gpfs_fs->root_fd, myself->handle, file_desc, posix_flags, reopen); if (FSAL_IS_ERROR(status)) { /** In some environments, "root" is denied write access, * so try with the request credentials if the above call * fails. */ fsal_set_credentials(op_ctx->creds); status = fsal_internal_handle2fd(gpfs_fs->root_fd, myself->handle, file_desc, posix_flags, reopen); fsal_restore_ganesha_credentials(); } return status; }
/** * FSAL_unlink_access_default : * test if a client identified by cred can unlink on a directory knowing its attributes * * \param pcontext user's context. * \param pattrsrc source directory attributes * \param pattrobj object attributes * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_ACCESS (Permission denied) * - ERR_FSAL_FAULT (null pointer parameter) * - ERR_FSAL_INVAL (missing attributes : mode, group, user,...) * - ERR_FSAL_SERVERFAULT (unexpected error) */ fsal_status_t FSAL_unlink_access_default(fsal_op_context_t * pcontext, /* IN */ fsal_attrib_list_t * pattrsrc, /* IN */ fsal_attrib_list_t * pattrobj) /* IN */ { fsal_status_t fsal_status; /* Sticky Bit on the parent directory? */ if(pattrsrc->mode & FSAL_MODE_SVTX) { /* The user must own the file or the parent directory. */ if( ( pattrsrc->owner != FSAL_OP_CONTEXT_TO_UID(pcontext) ) || ( pattrobj->owner != FSAL_OP_CONTEXT_TO_UID(pcontext) ) ) Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_unlink_access); } /* The user must be able to lookup and write the parent directory */ fsal_status = FSAL_test_access_default(pcontext, ( FSAL_W_OK | FSAL_X_OK ), pattrsrc); if(FSAL_IS_ERROR(fsal_status)) Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_unlink_access); /* If this point is reached, then access is granted */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink_access); } /* FSAL_unlink_access */
fsal_status_t PROXYFSAL_truncate(proxyfsal_handle_t * filehandle, /* IN */ proxyfsal_op_context_t * p_context, /* IN */ fsal_size_t length, /* IN */ fsal_file_t * file_descriptor, /* [IN|OUT] */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; COMPOUND4args argnfs4; COMPOUND4res resnfs4; nfs_fh4 nfs4fh; uint64_t fileid; 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_NB_OP_ALLOC 3 nfs_argop4 argoparray[FSAL_TRUNCATE_NB_OP_ALLOC]; nfs_resop4 resoparray[FSAL_TRUNCATE_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); } if(file_descriptor == NULL) { /* Use the stateless version */ fsal_status = FSAL_proxy_truncate_stateless(filehandle, p_context, length, object_attributes); Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* First, we need to get the fileid on a filehandle base */ fsal_status = FSAL_DigestHandle(p_context->export_context, FSAL_DIGEST_FILEID4, filehandle, (caddr_t) & fileid); if(FSAL_IS_ERROR(fsal_status)) { Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* Then we have of open the file by fileid */ open_attrs.asked_attributes = FSAL_ATTRS_POSIX; fsal_status = FSAL_open_by_fileid(filehandle, fileid, p_context, FSAL_O_RDWR, file_descriptor, &open_attrs); if(FSAL_IS_ERROR(fsal_status)) { Return(fsal_status.major, fsal_status.minor, 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_IDX_OP_PUTFH 0 #define FSAL_TRUNCATE_IDX_OP_SETATTR 1 #define FSAL_TRUNCATE_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 */ argnfs4.argarray.argarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_argop4_u.opsetattr. stateid.seqid = file_descriptor->stateid.seqid; memcpy(argnfs4.argarray.argarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_argop4_u. opsetattr.stateid.other, file_descriptor->stateid.other, 12); resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_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_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_IDX_OP_SETATTR].nfs_resop4_u.opsetattr. attrsset.bitmap4_val = bitmap_set; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_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_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); } } /* Close the previously opened filedescriptor */ fsal_status = FSAL_close_by_fileid(file_descriptor, fileid); if(FSAL_IS_ERROR(fsal_status)) { Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* No error occured */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate); }
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); }
/** * 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); }
cache_inode_status_t cache_inode_kill_entry( cache_entry_t * pentry, cache_inode_lock_how_t lock_how, hash_table_t * ht, cache_inode_client_t * pclient, cache_inode_status_t * pstatus ) { fsal_handle_t *pfsal_handle = NULL; cache_inode_fsal_data_t fsaldata; cache_inode_parent_entry_t *parent_iter = NULL; cache_inode_parent_entry_t *parent_iter_next = NULL; hash_buffer_t key, old_key; hash_buffer_t old_value; int rc; fsal_status_t fsal_status; memset( (char *)&fsaldata, 0, sizeof( fsaldata ) ) ; LogInfo(COMPONENT_CACHE_INODE, "Using cache_inode_kill_entry for entry %p", pentry); /* Invalidation is not for junctions or special files */ if( ( pentry->internal_md.type == FS_JUNCTION ) || ( pentry->internal_md.type == SOCKET_FILE ) || ( pentry->internal_md.type == FIFO_FILE ) || ( pentry->internal_md.type == CHARACTER_FILE ) || ( pentry->internal_md.type == BLOCK_FILE ) ) { free_lock( pentry, lock_how ) ; *pstatus = CACHE_INODE_SUCCESS; return *pstatus; } #if 0 /** @todo: BUGAZOMEU : directory invalidation seems quite tricky, temporarily avoid it */ if( pentry->internal_md.type == DIRECTORY ) { free_lock( pentry, lock_how ) ; *pstatus = CACHE_INODE_SUCCESS; return *pstatus; } /** @todo: BUGAZOMEU : file invalidation seems quite tricky, temporarily avoid it */ /* We need to know how to manage how to deal with "files with states" */ if( pentry->internal_md.type == REGULAR_FILE ) { free_lock( pentry, lock_how ) ; *pstatus = CACHE_INODE_SUCCESS; return *pstatus; } #endif if(pstatus == NULL) return CACHE_INODE_INVALID_ARGUMENT; if(pentry == NULL || pclient == NULL || ht == NULL) { free_lock( pentry, lock_how ) ; *pstatus = CACHE_INODE_INVALID_ARGUMENT; return *pstatus; } /* Get the FSAL handle */ if((pfsal_handle = cache_inode_get_fsal_handle(pentry, pstatus)) == NULL) { free_lock( pentry, lock_how ) ; LogCrit(COMPONENT_CACHE_INODE, "cache_inode_kill_entry: unable to retrieve pentry's specific filesystem info"); return *pstatus; } /* Invalidate the related LRU gc entry (no more required) */ if(pentry->gc_lru_entry != NULL) { if(LRU_invalidate(pentry->gc_lru, pentry->gc_lru_entry) != LRU_LIST_SUCCESS) { free_lock( pentry, lock_how ) ; *pstatus = CACHE_INODE_LRU_ERROR; return *pstatus; } } fsaldata.handle = *pfsal_handle; fsaldata.cookie = DIR_START; /* Use the handle to build the key */ if(cache_inode_fsaldata_2_key(&key, &fsaldata, pclient)) { free_lock( pentry, lock_how ) ; LogCrit(COMPONENT_CACHE_INODE, "cache_inode_kill_entry: could not build hashtable key"); cache_inode_release_fsaldata_key(&key, pclient); *pstatus = CACHE_INODE_NOT_FOUND; return *pstatus; } /* use the key to delete the entry */ if((rc = HashTable_Del(ht, &key, &old_key, &old_value)) != HASHTABLE_SUCCESS) { if( rc != HASHTABLE_ERROR_NO_SUCH_KEY) /* rc=3 => Entry was previously removed */ LogCrit( COMPONENT_CACHE_INODE, "cache_inode_kill_entry: entry could not be deleted, status = %d", rc); cache_inode_release_fsaldata_key(&key, pclient); *pstatus = CACHE_INODE_NOT_FOUND; return *pstatus; } /* Release the hash key data */ cache_inode_release_fsaldata_key(&old_key, pclient); /* Clean up the associated ressources in the FSAL */ if(FSAL_IS_ERROR(fsal_status = FSAL_CleanObjectResources(pfsal_handle))) { LogCrit(COMPONENT_CACHE_INODE, "cache_inode_kill_entry: Couldn't free FSAL ressources fsal_status.major=%u", fsal_status.major); } /* Sanity check: old_value.pdata is expected to be equal to pentry, * and is released later in this function */ if((cache_entry_t *) old_value.pdata != pentry) { LogCrit(COMPONENT_CACHE_INODE, "cache_inode_kill_entry: unexpected pdata %p from hash table (pentry=%p)", old_value.pdata, pentry); } /* Release the current key */ cache_inode_release_fsaldata_key(&key, pclient); /* Recover the parent list entries */ parent_iter = pentry->parent_list; while(parent_iter != NULL) { parent_iter_next = parent_iter->next_parent; ReleaseToPool(parent_iter, &pclient->pool_parent); parent_iter = parent_iter_next; } /* If entry is datacached, remove it from the cache */ if(pentry->internal_md.type == REGULAR_FILE) { cache_content_status_t cache_content_status; if(pentry->object.file.pentry_content != NULL) if(cache_content_release_entry ((cache_content_entry_t *) pentry->object.file.pentry_content, (cache_content_client_t *) pclient->pcontent_client, &cache_content_status) != CACHE_CONTENT_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "Could not removed datacached entry for pentry %p", pentry); } /* If entry is a DIRECTORY, invalidate dirents */ if(pentry->internal_md.type == DIRECTORY) { cache_inode_invalidate_related_dirents(pentry, pclient); } // free_lock( pentry, lock_how ) ; /* Really needed ? The pentry is unaccessible now and will be destroyed */ /* Destroy the mutex associated with the pentry */ cache_inode_mutex_destroy(pentry); /* Put the pentry back to the pool */ ReleaseToPool(pentry, &pclient->pool_entry); *pstatus = CACHE_INODE_SUCCESS; return *pstatus; } /* cache_inode_kill_entry */
/** * 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_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) * - Another error code if an error occured. */ fsal_status_t GPFSFSAL_link(fsal_handle_t * p_target_handle, /* IN */ fsal_handle_t * p_dir_handle, /* IN */ fsal_name_t * p_link_name, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_attrib_list_t * p_attributes /* [ IN/OUT ] */ ) { fsal_status_t status; int srcfd, dstfd; fsal_accessflags_t access_mask = 0; fsal_attrib_list_t parent_dir_attrs; /* sanity checks. * note : attributes is optional. */ if(!p_target_handle || !p_dir_handle || !p_context || !p_context->export_context || !p_link_name || !p_link_name->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); /* get the target handle access by fid */ TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_target_handle, &srcfd, O_RDONLY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_link); /* build the destination path and check permissions on the directory */ TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_dir_handle, &dstfd, O_RDONLY | O_DIRECTORY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) { close(srcfd); ReturnStatus(status, INDEX_FSAL_link); } /* retrieve target directory metadata */ parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_dir_handle, p_context, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_link); /* check permission on target directory */ /* 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_link); /* Create the link on the filesystem */ TakeTokenFSCall(); status = fsal_internal_link_at(srcfd, dstfd, p_link_name->name); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) { close(srcfd); close(dstfd); ReturnStatus(status, INDEX_FSAL_link); } /* optionnaly get attributes */ if(p_attributes) { status = GPFSFSAL_getattrs(p_target_handle, p_context, p_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_attributes->asked_attributes); FSAL_SET_MASK(p_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } close(srcfd); close(dstfd); /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); }
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); }
/** * @brief The Rquota getquota function, for all versions. * * The RQUOTA getquota function, for all versions. * * @param[in] parg Ignored * @param[in] pexport Ignored * @param[in] pcontext Ignored * @param[in] pworker Ignored * @param[in] preq Ignored * @param[out] pres Ignored * */ int rquota_getquota(nfs_arg_t *parg, exportlist_t *pexport, fsal_op_context_t *pcontext, nfs_worker_data_t *pworker, struct svc_req *preq, nfs_res_t * pres) { fsal_status_t fsal_status; fsal_quota_t fsal_quota; fsal_path_t fsal_path; int quota_type = USRQUOTA; int quota_id; char work[MAXPATHLEN]; LogFullDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling rquota_getquota"); if(preq->rq_vers == EXT_RQUOTAVERS) { quota_type = parg->arg_ext_rquota_getquota.gqa_type; quota_id = parg->arg_ext_rquota_getquota.gqa_id; } else { quota_type = USRQUOTA; quota_id = parg->arg_rquota_getquota.gqa_uid; } if(parg->arg_rquota_getquota.gqa_pathp[0] == '/') strncpy(work, parg->arg_rquota_getquota.gqa_pathp, MAXPATHLEN); else { if(nfs_export_tag2path(nfs_param.pexportlist, parg->arg_rquota_getquota.gqa_pathp, strnlen(parg->arg_rquota_getquota.gqa_pathp, MAXPATHLEN), work, MAXPATHLEN) == -1) { pres->res_rquota_getquota.status = Q_EPERM; return NFS_REQ_OK; } } if(FSAL_IS_ERROR((fsal_status = FSAL_str2path(work, MAXPATHLEN, &fsal_path)))) { pres->res_rquota_getquota.status = Q_EPERM; return NFS_REQ_OK; } fsal_status = FSAL_get_quota(&fsal_path, quota_type, quota_id, &fsal_quota); if(FSAL_IS_ERROR(fsal_status)) { if(fsal_status.major == ERR_FSAL_NO_QUOTA) pres->res_rquota_getquota.status = Q_NOQUOTA; else pres->res_rquota_getquota.status = Q_EPERM; return NFS_REQ_OK; } /* success */ pres->res_rquota_getquota.status = Q_OK; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_active = TRUE; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_bsize = fsal_quota.bsize; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_bhardlimit = fsal_quota.bhardlimit; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_bsoftlimit = fsal_quota.bsoftlimit; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_curblocks = fsal_quota.curblocks; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_curfiles = fsal_quota.curfiles; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_fhardlimit = fsal_quota.fhardlimit; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_fsoftlimit = fsal_quota.fsoftlimit; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_btimeleft = fsal_quota.btimeleft; pres->res_rquota_getquota.getquota_rslt_u.gqr_rquota.rq_ftimeleft = fsal_quota.ftimeleft; return NFS_REQ_OK; } /* rquota_getquota */
/** * 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) * - Another error code if an error occured. */ fsal_status_t GPFSFSAL_mkdir(fsal_handle_t * p_parent_directory_handle, /* IN */ fsal_name_t * p_dirname, /* 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, errsv; int setgid_bit = 0; mode_t unix_mode; fsal_status_t status; int fd, newfd; 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_dirname) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir); /* convert FSAL mode to unix mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~global_fs_info.umask; TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_parent_directory_handle, &fd, O_RDONLY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_mkdir); /* get 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_SUBDIRECTORY); status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_mkdir); /* build new entry path */ /* creates the directory and get its handle */ TakeTokenFSCall(); rc = mkdirat(fd, p_dirname->name, unix_mode); errsv = errno; if(rc) { close(fd); ReleaseTokenFSCall(); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mkdir); } ReleaseTokenFSCall(); /**** * There is a race here between mkdir creation and the open, not * sure there is any way to close it in practice. */ /* get the new handle */ TakeTokenFSCall(); status = fsal_internal_get_handle_at(fd, p_dirname, p_object_handle); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) { close(fd); ReturnStatus(status, INDEX_FSAL_mkdir); } TakeTokenFSCall(); status = fsal_internal_handle2fd_at(fd, p_object_handle, &newfd, O_RDONLY | O_DIRECTORY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) { close(fd); ReturnStatus(status, INDEX_FSAL_mkdir); } /* the directory has been created */ /* chown the dir to the current user/group */ 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(fd); close(newfd); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mkdir); } } close(fd); close(newfd); /* 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_mkdir); }