lkml.org 
[lkml]   [2010]   [Jun]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH -V14 02/11] vfs: Add name to file handle conversion support
    Date
    This patch add a new superblock field unsigned char s_uuid[16]
    to store UUID mapping for the file system. The s_uuid[16] is used to
    identify the file system apart of file_handle

    Acked-by: Serge Hallyn <serue@us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
    ---
    fs/open.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
    include/linux/fs.h | 11 ++++
    include/linux/syscalls.h | 3 +
    3 files changed, 142 insertions(+), 0 deletions(-)

    diff --git a/fs/open.c b/fs/open.c
    index 5463266..43ac798 100644
    --- a/fs/open.c
    +++ b/fs/open.c
    @@ -29,6 +29,7 @@
    #include <linux/falloc.h>
    #include <linux/fs_struct.h>
    #include <linux/ima.h>
    +#include <linux/exportfs.h>

    #include "internal.h"

    @@ -1040,3 +1041,130 @@ int nonseekable_open(struct inode *inode, struct file *filp)
    }

    EXPORT_SYMBOL(nonseekable_open);
    +
    +#ifdef CONFIG_EXPORTFS
    +/* limit the handle size to some value */
    +#define MAX_HANDLE_SZ 4096
    +static long do_sys_name_to_handle(struct path *path,
    + struct file_handle __user *ufh)
    +{
    + long retval;
    + int handle_size;
    + struct super_block *sb;
    + struct file_handle f_handle;
    + struct file_handle *handle = NULL;
    +
    + if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) {
    + retval = -EFAULT;
    + goto err_out;
    + }
    + if (f_handle.handle_size > MAX_HANDLE_SZ) {
    + retval = -EINVAL;
    + goto err_out;
    + }
    + handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_size,
    + GFP_KERNEL);
    + if (!handle) {
    + retval = -ENOMEM;
    + goto err_out;
    + }
    +
    + /* convert handle size to multiple of sizeof(u32) */
    + handle_size = f_handle.handle_size >> 2;
    +
    + /* we ask for a non connected handle */
    + retval = exportfs_encode_fh(path->dentry,
    + (struct fid *)handle->f_handle,
    + &handle_size, 0);
    + /* convert handle size to bytes */
    + handle_size *= sizeof(u32);
    + handle->handle_type = retval;
    + handle->handle_size = handle_size;
    + if (handle_size <= f_handle.handle_size) {
    + /* get the uuid */
    + sb = path->mnt->mnt_sb;
    + memcpy(handle->fs_uuid,
    + sb->s_uuid,
    + sizeof(handle->fs_uuid));
    + retval = 0;
    + } else {
    + /*
    + * set the handle_size to zero so we copy only
    + * non variable part of the file_handle
    + */
    + handle_size = 0;
    + retval = -EOVERFLOW;
    + }
    + if (copy_to_user(ufh, handle,
    + sizeof(struct file_handle) + handle_size))
    + retval = -EFAULT;
    +
    + kfree(handle);
    +err_out:
    + return retval;
    +}
    +
    +/**
    + * sys_name_to_handle_at: convert name to handle
    + * @dfd: directory relative to which name is interpreted if not absolute
    + * @name: name that should be converted to handle.
    + * @handle: resulting file handle
    + * @flag: flag value to indicate whether to follow symlink or not
    + *
    + * @handle->handle_size indicate the space available to store the
    + * variable part of the file handle in bytes. If there is not
    + * enough space, the field is updated to return the minimum
    + * value required.
    + */
    +SYSCALL_DEFINE4(name_to_handle_at, int, dfd, const char __user *, name,
    + struct file_handle __user *, handle, int, flag)
    +{
    +
    + int follow;
    + long ret = -EINVAL;
    + struct path path, *pp;
    + struct file *file = NULL;
    +
    + if ((flag & ~AT_SYMLINK_FOLLOW) != 0)
    + goto err_out;
    +
    + if (name == NULL && dfd != AT_FDCWD) {
    + file = fget(dfd);
    + if (file) {
    + pp = &file->f_path;
    + ret = 0;
    + } else
    + ret = -EBADF;
    + } else {
    + follow = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
    + ret = user_path_at(dfd, name, follow, &path);
    + pp = &path;
    + }
    + if (ret)
    + goto err_out;
    + /*
    + * We need t make sure wether the file system
    + * support decoding of the file handle
    + */
    + if (!pp->mnt->mnt_sb->s_export_op ||
    + !pp->mnt->mnt_sb->s_export_op->fh_to_dentry) {
    + ret = -EOPNOTSUPP;
    + goto out_path;
    + }
    + ret = do_sys_name_to_handle(pp, handle);
    +
    +out_path:
    + if (file)
    + fput(file);
    + else
    + path_put(&path);
    +err_out:
    + return ret;
    +}
    +#else
    +SYSCALL_DEFINE4(name_to_handle_at, int, dfd, const char __user *, name,
    + struct file_handle __user *, handle, int, flag)
    +{
    + return -ENOSYS;
    +}
    +#endif
    diff --git a/include/linux/fs.h b/include/linux/fs.h
    index 471e1ff..ebc0f98 100644
    --- a/include/linux/fs.h
    +++ b/include/linux/fs.h
    @@ -949,6 +949,16 @@ struct file {
    unsigned long f_mnt_write_state;
    #endif
    };
    +
    +struct file_handle {
    + int handle_size;
    + int handle_type;
    + /* File system UUID identifier */
    + u8 fs_uuid[16];
    + /* file identifier */
    + unsigned char f_handle[0];
    +};
    +
    extern spinlock_t files_lock;
    #define file_list_lock() spin_lock(&files_lock);
    #define file_list_unlock() spin_unlock(&files_lock);
    @@ -1357,6 +1367,7 @@ struct super_block {
    wait_queue_head_t s_wait_unfrozen;

    char s_id[32]; /* Informational name */
    + u8 s_uuid[16]; /* UUID */

    void *s_fs_info; /* Filesystem private info */
    fmode_t s_mode;
    diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
    index 7f614ce..4d4e922 100644
    --- a/include/linux/syscalls.h
    +++ b/include/linux/syscalls.h
    @@ -61,6 +61,7 @@ struct robust_list_head;
    struct getcpu_cache;
    struct old_linux_dirent;
    struct perf_event_attr;
    +struct file_handle;

    #include <linux/types.h>
    #include <linux/aio_abi.h>
    @@ -823,5 +824,7 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
    unsigned long prot, unsigned long flags,
    unsigned long fd, unsigned long pgoff);
    asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
    +asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
    + struct file_handle __user *handle, int flag);

    #endif
    --
    1.7.1.331.ga5080


    \
     
     \ /
      Last update: 2010-06-15 19:15    [W:0.029 / U:30.124 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site