lkml.org 
[lkml]   [2010]   [May]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 28/39] union-mount: In-kernel copyup of xattrs
    Date
    Copyup extended attributes as well as file data.
    ---
    fs/union.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    1 files changed, 74 insertions(+), 0 deletions(-)

    diff --git a/fs/union.c b/fs/union.c
    index d52c7c0..abc964a 100644
    --- a/fs/union.c
    +++ b/fs/union.c
    @@ -27,6 +27,7 @@
    #include <linux/file.h>
    #include <linux/security.h>
    #include <linux/splice.h>
    +#include <linux/xattr.h>

    /*
    * This is borrowed from fs/inode.c. The hashtable for lookups. Somebody
    @@ -449,6 +450,72 @@ void detach_mnt_union(struct vfsmount *mnt)
    return;
    }

    +/**
    + * union_copyup_xattr
    + *
    + * @old: dentry of original file
    + * @new: dentry of new copy
    + *
    + * Copy up extended attributes from the original file to the new one.
    + *
    + * XXX - Permissions? For now, copying up every xattr.
    + */
    +
    +static int union_copyup_xattr(struct dentry *old, struct dentry *new)
    +{
    + ssize_t list_size, size;
    + char *buf, *name, *value;
    + int error;
    +
    + /* Check for xattr support */
    + if (!old->d_inode->i_op->getxattr ||
    + !new->d_inode->i_op->getxattr)
    + return 0;
    +
    + /* Find out how big the list of xattrs is */
    + list_size = vfs_listxattr(old, NULL, 0);
    + if (list_size <= 0)
    + return list_size;
    +
    + /* Allocate memory for the list */
    + buf = kzalloc(list_size, GFP_KERNEL);
    + if (!buf)
    + return -ENOMEM;
    +
    + /* Allocate memory for the xattr's value */
    + error = -ENOMEM;
    + value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
    + if (!value)
    + goto out;
    +
    + /* Actually get the list of xattrs */
    + list_size = vfs_listxattr(old, buf, list_size);
    + if (list_size <= 0) {
    + error = list_size;
    + goto out_free_value;
    + }
    +
    + for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
    + /* XXX Locking? old is on read-only fs */
    + size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX);
    + if (size <= 0) {
    + error = size;
    + goto out_free_value;
    + }
    + /* XXX do we really need to check for size overflow? */
    + /* XXX locks new dentry, lock ordering problems? */
    + error = vfs_setxattr(new, name, value, size, 0);
    + if (error)
    + goto out_free_value;
    + }
    +
    +out_free_value:
    + kfree(value);
    +out:
    + kfree(buf);
    + return error;
    +}
    +
    /*
    * union_create_topmost_dir - Create a matching dir in the topmost file system
    */
    @@ -473,6 +540,10 @@ struct dentry * union_create_topmost_dir(struct path *parent, struct qstr *name,
    dput(dentry);
    goto out;
    }
    +
    + res = union_copyup_xattr(lower->dentry, dentry);
    + if (res)
    + dput(dentry);
    out:
    mnt_drop_write(parent->mnt);
    return dentry;
    @@ -788,6 +859,9 @@ static int __union_copyup_len(struct nameidata *nd, struct path *path,
    goto out_dput;
    }
    /* XXX Copyup xattrs and any other dangly bits */
    + error = union_copyup_xattr(path->dentry, dentry);
    + if (error)
    + goto out_dput;
    out_newpath:
    /* path_put() of original must happen before we copy in new */
    path_put(path);
    --
    1.6.3.3


    \
     
     \ /
      Last update: 2010-05-04 01:17    [W:0.039 / U:30.800 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site