[PATCH 28/39] union-mount: In-kernel copyup of xattrs

From: Valerie Aurora
Date: Mon May 03 2010 - 19:14:43 EST


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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/