/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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 during this call. */ fsal_status_t GPFSFSAL_open(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_desc, /* OUT */ fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ ) { int rc, errsv; fsal_status_t status; int fd; int posix_flags = 0; gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; /* sanity checks. * note : file_attributes is optional. */ if(!p_filehandle || !p_context || !p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* convert fsal open flags to posix open flags */ rc = fsal2posix_openflags(openflags, &posix_flags); /* flags conflicts. */ if(rc) { LogWarn(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); Return(rc, 0, INDEX_FSAL_open); } TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* output attributes */ if(p_file_attributes) { p_file_attributes->asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_filehandle, p_context, p_file_attributes); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); } TakeTokenFSCall(); p_file_descriptor->fd = fd; errsv = errno; ReleaseTokenFSCall(); /* set the read-only flag of the file descriptor */ p_file_descriptor->ro = openflags & FSAL_O_RDONLY; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
/* * 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_sync: * This function is used for processing stable writes and COMMIT requests. * Calling this function makes sure the changes to a specific file are * written to disk rather than kept in memory. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t XFSFSAL_sync(xfsfsal_file_t * p_file_descriptor /* IN */) { int rc, errsv; /* sanity checks. */ if(!p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_sync); if( p_file_descriptor->fd == 0 ) Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_sync); /* Nothing to sync, the file is not opened */ /* Flush data. */ TakeTokenFSCall(); rc = fsync(p_file_descriptor->fd); errsv = errno; ReleaseTokenFSCall(); if(rc) { LogEvent(COMPONENT_FSAL, "Error in fsync operation"); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_sync); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_sync); }
fsal_status_t POSIXFSAL_close(fsal_file_t * file_descriptor, /* IN */ fsal_op_context_t * p_context /* IN */ ) { posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor; int rc, errsv; /* sanity checks. */ if(!p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); /* call to close */ TakeTokenFSCall(); #ifdef _FSAL_POSIX_USE_STREAM rc = fclose(p_file_descriptor->p_file); #else rc = close(p_file_descriptor->filefd); #endif errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); }
fsal_status_t GPFSFSAL_close(fsal_file_t * p_file_descriptor /* IN */ ) { int rc, errsv; /* sanity checks. */ if(!p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); /* call to close */ TakeTokenFSCall(); rc = close(((gpfsfsal_file_t *)p_file_descriptor)->fd); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); }
/** * 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 GPFSFSAL_dynamic_fsinfo(gpfsfsal_handle_t * p_filehandle, /* IN */ gpfsfsal_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); TakeTokenFSCall(); rc = fstatvfs(p_context->export_context->mount_root_fd, &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); }
/** * return index if found, * negative value on error. */ static int xattr_name_to_id(libzfswrap_vfs_t *p_vfs, zfsfsal_op_context_t *p_context, zfsfsal_handle_t *p_objecthandle, const char *psz_name, unsigned int *p_id) { unsigned int i; char *psz_buffer, *ptr; size_t i_size; creden_t cred; cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; /* get xattrs */ TakeTokenFSCall(); int rc = libzfswrap_listxattr(p_vfs, &cred, p_objecthandle->data.zfs_handle, &psz_buffer, &i_size); ReleaseTokenFSCall(); if(rc) return posix2fsal_error(rc); for(ptr = psz_buffer, i = 0; ptr < psz_buffer + i_size; i++, ptr += strlen(ptr) + 1) { if(!strcmp(psz_name, ptr)) { *p_id = i + XATTR_COUNT; free(psz_buffer); return ERR_FSAL_NO_ERROR; } } free(psz_buffer); return ERR_FSAL_NOENT; }
/** * FSAL_commit: * This function is used for processing stable writes and COMMIT requests. * Calling this function makes sure the changes to a specific file are * written to disk rather than kept in memory. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param offset: * The starting offset for the portion of file to be synced * \param length: * The length for the portion of file to be synced. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t POSIXFSAL_commit(fsal_file_t * file_descriptor, fsal_op_context_t * p_context, /* IN */ fsal_off_t offset, fsal_size_t length ) { posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor; int rc, errsv; /* sanity checks. */ if(!p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit); /* Flush data. */ TakeTokenFSCall(); rc = fsync(p_file_descriptor->filefd); errsv = errno; ReleaseTokenFSCall(); if(rc) { LogEvent(COMPONENT_FSAL, "Error in fsync operation"); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); }
/** * 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); }
/** * FSAL_commit: * This function is used for processing stable writes and COMMIT requests. * Calling this function makes sure the changes to a specific file are * written to disk rather than kept in memory. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param offset: * The starting offset for the portion of file to be synced * \param length: * The length for the portion of file to be synced. * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t XFSFSAL_commit( fsal_file_t * p_file_descriptor, fsal_op_context_t * p_context, /* IN */ fsal_off_t offset, fsal_size_t length ) { int rc, errsv; /* sanity checks. */ if(!p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit); if(((xfsfsal_file_t *)p_file_descriptor)->fd == 0 ) Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); /* Nothing to sync, the file is not opened */ /* Flush data. */ TakeTokenFSCall(); rc = fsync(((xfsfsal_file_t *)p_file_descriptor)->fd); errsv = errno; ReleaseTokenFSCall(); if(rc) { LogEvent(COMPONENT_FSAL, "Error in fsync operation"); Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit); }
fsal_status_t ZFSFSAL_SetXAttrValue(fsal_handle_t * obj_handle, /* IN */ const fsal_name_t * xattr_name, /* IN */ fsal_op_context_t * p_context, /* IN */ caddr_t buffer_addr, /* IN */ size_t buffer_size, /* IN */ int create /* IN */ ) { //@TODO: use the create parameter ? int rc; creden_t cred; zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle; /* Hook to prevent any modification in the snapshots */ if(p_objecthandle->data.i_snap != 0) Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue); /* Remove trailing '\n', if any */ chomp_attr_value((char*)buffer_addr, buffer_size); cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); rc = libzfswrap_setxattr(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &cred, p_objecthandle->data.zfs_handle, xattr_name->name, (char*)buffer_addr); ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue); }
/* * Free the resources allocated for reading directory entries. * * \param dir_descriptor (input): * Pointer to a directory descriptor filled by FSAL_opendir. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t dpmfsal_closedir(fsal_dir_t * dir_descriptor // IN ) { int rc; // Sanity checks if (!dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); LogInfo(COMPONENT_FSAL, "dpmfsal_closedir: start"); TakeTokenFSCall(); rc = dpns_closedir(dir_descriptor->p_dir); ReleaseTokenFSCall(); if (rc) Return(dpns2fsal_error(serrno), serrno, INDEX_FSAL_opendir); if (dpns_endsess() < 0) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); // Fill the descriptor with 0s memset(dir_descriptor, 0, sizeof(fsal_dir_t)); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); }
/** * Removes a xattr by Id * * \param p_objecthandle Handle of the object you want to get attribute for. * \param p_context pointer to the current security context. * \param xattr_id xattr's id */ fsal_status_t ZFSFSAL_RemoveXAttrById(fsal_handle_t * obj_handle, /* IN */ fsal_op_context_t * context, /* IN */ unsigned int xattr_id) /* IN */ { int rc; creden_t cred; char psz_name[FSAL_MAX_NAME_LEN]; zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle; zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context; /* Hook to prevent any modification in the snapshots */ if(p_objecthandle->data.i_snap != 0) Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue); if((rc = xattr_id_to_name(p_context->export_context->p_vfs, p_context, p_objecthandle, xattr_id, psz_name))) Return(rc, 0, INDEX_FSAL_SetXAttrValue); cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); rc = libzfswrap_removexattr(p_context->export_context->p_vfs, &cred, p_objecthandle->data.zfs_handle, psz_name); ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue); }
fsal_status_t ZFSFSAL_close(zfsfsal_file_t * file_descriptor /* IN */ ) { int rc = 0; /* sanity checks. */ if(!file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close); TakeTokenFSCall(); if(!file_descriptor->is_closed) { rc = libzfswrap_close(file_descriptor->p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, file_descriptor->flags); file_descriptor->is_closed = 1; } ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(rc), rc, INDEX_FSAL_close); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close); }
/** * Get the value of an extended attribute from its name. * * \param p_objecthandle Handle of the object you want to get attribute for. * \param xattr_name the name of the attribute to be read. * \param p_context pointer to the current security context. * \param buffer_addr address of the buffer where the xattr value is to be stored. * \param buffer_size size of the buffer where the xattr value is to be stored. * \param p_output_size size of the data actually stored into the buffer. */ fsal_status_t ZFSFSAL_GetXAttrValueByName(fsal_handle_t * obj_handle, /* IN */ const fsal_name_t * xattr_name, /* IN */ fsal_op_context_t * p_context, /* IN */ caddr_t buffer_addr, /* IN/OUT */ size_t buffer_size, /* IN */ size_t * p_output_size /* OUT */ ) { unsigned int index; char *psz_value; int rc; creden_t cred; zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle; /* sanity checks */ if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr || !xattr_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); /* look for this name */ for(index = 0; index < XATTR_COUNT; index++) { if(do_match_type(xattr_list[index].flags, p_objecthandle->data.type) && !strcmp(xattr_list[index].xattr_name, xattr_name->name)) { return ZFSFSAL_GetXAttrValueById((fsal_handle_t *)p_objecthandle, index, p_context, buffer_addr, buffer_size, p_output_size); } } /* Get the right VFS */ libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue); } cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); if((rc = libzfswrap_getxattr(p_vfs, &cred, p_objecthandle->data.zfs_handle, xattr_name->name, &psz_value))) { ZFSFSAL_VFS_Unlock(); Return(posix2fsal_error(rc), 0, INDEX_FSAL_GetXAttrValue); } ZFSFSAL_VFS_Unlock(); /* Copy the string (remove this call by changing the libzfswrap API) */ strncpy(buffer_addr, psz_value, buffer_size); buffer_addr[buffer_size - 1] = '\0'; *p_output_size = strlen(psz_value); free(psz_value); Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue); }
/** * FSAL_opendir : * Opens a directory for reading its content. * * \param dir_handle (input) * the handle of the directory to be opened. * \param cred (input) * Permission context for the operation (user,...). * \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. * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t GPFSFSAL_opendir(fsal_handle_t * p_dir_handle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_dir_t * dir_desc, /* OUT */ fsal_attrib_list_t * p_dir_attributes /* [ IN/OUT ] */ ) { fsal_status_t status; fsal_accessflags_t access_mask = 0; fsal_attrib_list_t dir_attrs; gpfsfsal_dir_t *p_dir_descriptor = (gpfsfsal_dir_t *)dir_desc; /* sanity checks * note : dir_attributes is optionnal. */ if(!p_dir_handle || !p_context || !p_dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); /* get the path of the directory */ TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_dir_handle, &p_dir_descriptor->fd, O_RDONLY | O_DIRECTORY); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_opendir); /* get directory metadata */ dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_dir_handle, p_context, &dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_opendir); /* Test access rights for this directory */ /* Set both mode and ace4 mask */ access_mask = FSAL_MODE_MASK_SET(FSAL_R_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR); status = fsal_internal_testAccess(p_context, access_mask, NULL, &dir_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_opendir); /* if everything is OK, fills the dir_desc structure : */ memcpy(&(p_dir_descriptor->context), p_context, sizeof(fsal_op_context_t)); memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(fsal_handle_t)); if(p_dir_attributes) *p_dir_attributes = dir_attrs; p_dir_descriptor->dir_offset = 0; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); }
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 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_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 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_getetxattrs: * 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_getextattrs(xfsfsal_handle_t * p_filehandle, /* IN */ xfsfsal_op_context_t * p_context, /* IN */ fsal_extattrib_list_t * p_object_attributes /* OUT */ ) { fsal_status_t st ; xfs_bstat_t bstat; xfs_ino_t xfs_ino; struct stat buffstat; int fd = 0 ; /* 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_getextattrs); if( p_object_attributes->asked_attributes & FSAL_ATTR_GENERATION ) { /* get file metadata */ xfs_ino = p_filehandle->data.inode ; TakeTokenFSCall(); if(fsal_internal_get_bulkstat_by_inode(fd, &xfs_ino, &bstat) < 0) { close(fd); ReleaseTokenFSCall(); ReturnCode(posix2fsal_error(errno), errno); } ReleaseTokenFSCall(); p_object_attributes->generation = bstat.bs_gen ; } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getextattrs); } /* XFSFSAL_getextattrs */
/** * 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); }
/** * FSAL_read: * Perform a read operation on an opened file. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param seek_descriptor (optional input): * Specifies the position where data is to be read. * If not specified, data will be read at the current position. * \param buffer_size (input): * Amount (in bytes) of data to be read. * \param buffer (output): * Address where the read data is to be stored in memory. * \param read_amount (output): * Pointer to the amount of data (in bytes) that have been read * during this call. * \param end_of_file (output): * Pointer to a boolean that indicates whether the end of file * has been reached during this call. * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_INVAL (invalid parameter) * - ERR_FSAL_NOT_OPENED (tried to read in a non-opened zfsfsal_file_t) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t ZFSFSAL_read(zfsfsal_file_t * file_descriptor, /* IN */ fsal_seek_t * seek_descriptor, /* [IN] */ fsal_size_t buffer_size, /* IN */ caddr_t buffer, /* OUT */ fsal_size_t * read_amount, /* OUT */ fsal_boolean_t * end_of_file /* OUT */ ) { off_t offset = 0; int rc; int behind = 0; /* sanity checks. */ if(!file_descriptor || !buffer || !read_amount || !end_of_file) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read); TakeTokenFSCall(); if(seek_descriptor) { switch(seek_descriptor->whence) { case FSAL_SEEK_CUR: offset = file_descriptor->current_offset + seek_descriptor->offset; break; case FSAL_SEEK_SET: offset = seek_descriptor->offset; break; case FSAL_SEEK_END: behind = 1; offset = seek_descriptor->offset; break; } } rc = libzfswrap_read(file_descriptor->p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, buffer, buffer_size, behind, offset); ReleaseTokenFSCall(); /* >> interpreted returned status << */ if(!rc) *end_of_file = 1; /* >> dont forget setting output vars : read_amount, end_of_file << */ *read_amount = buffer_size; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read); }
/** * 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_write: * Perform a write operation on an opened file. * * \param file_descriptor (input): * The file descriptor returned by FSAL_open. * \param seek_descriptor (optional input): * Specifies the position where data is to be written. * If not specified, data will be written at the current position. * \param buffer_size (input): * Amount (in bytes) of data to be written. * \param buffer (input): * Address in memory of the data to write to file. * \param write_amount (output): * Pointer to the amount of data (in bytes) that have been written * during this call. * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_INVAL (invalid parameter) * - ERR_FSAL_NOT_OPENED (tried to write in a non-opened zfsfsal_file_t) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ERR_FSAL_NOSPC, ERR_FSAL_DQUOT... */ fsal_status_t ZFSFSAL_write(zfsfsal_file_t * file_descriptor, /* IN */ fsal_seek_t * seek_descriptor, /* IN */ fsal_size_t buffer_size, /* IN */ caddr_t buffer, /* IN */ fsal_size_t * write_amount /* OUT */ ) { int rc, behind = 0; off_t offset; /* sanity checks. */ if(!file_descriptor || !buffer || !write_amount) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write); TakeTokenFSCall(); if(seek_descriptor) { switch(seek_descriptor->whence) { case FSAL_SEEK_CUR: offset = file_descriptor->current_offset + seek_descriptor->offset; break; case FSAL_SEEK_SET: offset = seek_descriptor->offset; break; case FSAL_SEEK_END: behind = 1; offset = seek_descriptor->offset; break; } } rc = libzfswrap_write(file_descriptor->p_vfs, &file_descriptor->cred, file_descriptor->p_vnode, buffer, buffer_size, behind, offset); ReleaseTokenFSCall(); /* >> interpreted returned status << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_write); /* >> dont forget setting output vars : write_amount << */ *write_amount = buffer_size; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write); }
/** * 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); }
/** * 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); }