summaryrefslogtreecommitdiff
path: root/fs/afs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/xattr.c')
-rw-r--r--fs/afs/xattr.c101
1 files changed, 100 insertions, 1 deletions
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
index 31db360947a6..a5c82b0ad539 100644
--- a/fs/afs/xattr.c
+++ b/fs/afs/xattr.c
@@ -19,7 +19,11 @@ static const char afs_xattr_list[] =
"afs.acl\0"
"afs.cell\0"
"afs.fid\0"
- "afs.volume";
+ "afs.volume\0"
+ "afs.yfs.acl\0"
+ "afs.yfs.acl_inherited\0"
+ "afs.yfs.acl_num_cleaned\0"
+ "afs.yfs.vol_acl";
/*
* Retrieve a list of the supported xattrs.
@@ -134,6 +138,100 @@ static const struct xattr_handler afs_xattr_afs_acl_handler = {
};
/*
+ * Get a file's YFS ACL.
+ */
+static int afs_xattr_get_yfs(const struct xattr_handler *handler,
+ struct dentry *dentry,
+ struct inode *inode, const char *name,
+ void *buffer, size_t size)
+{
+ struct afs_fs_cursor fc;
+ struct afs_vnode *vnode = AFS_FS_I(inode);
+ struct yfs_acl *yacl = NULL;
+ struct key *key;
+ unsigned int flags = 0;
+ char buf[16], *data;
+ int which = 0, dsize, ret;
+
+ if (strcmp(name, "acl") == 0)
+ which = 0;
+ else if (strcmp(name, "acl_inherited") == 0)
+ which = 1;
+ else if (strcmp(name, "acl_num_cleaned") == 0)
+ which = 2;
+ else if (strcmp(name, "vol_acl") == 0)
+ which = 3;
+ else
+ return -EOPNOTSUPP;
+
+ if (which == 0)
+ flags |= YFS_ACL_WANT_ACL;
+ else if (which == 3)
+ flags |= YFS_ACL_WANT_VOL_ACL;
+
+ key = afs_request_key(vnode->volume->cell);
+ if (IS_ERR(key))
+ return PTR_ERR(key);
+
+ ret = -ERESTARTSYS;
+ if (afs_begin_vnode_operation(&fc, vnode, key)) {
+ while (afs_select_fileserver(&fc)) {
+ fc.cb_break = afs_calc_vnode_cb_break(vnode);
+ yacl = yfs_fs_fetch_opaque_acl(&fc, flags);
+ }
+
+ afs_check_for_remote_deletion(&fc, fc.vnode);
+ afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+ ret = afs_end_vnode_operation(&fc);
+ }
+
+ if (ret == 0) {
+ switch (which) {
+ case 0:
+ data = yacl->acl->data;
+ dsize = yacl->acl->size;
+ break;
+ case 1:
+ data = buf;
+ dsize = snprintf(buf, sizeof(buf), "%u",
+ yacl->inherit_flag);
+ break;
+ case 2:
+ data = buf;
+ dsize = snprintf(buf, sizeof(buf), "%u",
+ yacl->num_cleaned);
+ break;
+ case 3:
+ data = yacl->vol_acl->data;
+ dsize = yacl->vol_acl->size;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ ret = dsize;
+ if (size > 0) {
+ if (dsize > size) {
+ ret = -ERANGE;
+ goto out;
+ }
+ memcpy(buffer, data, dsize);
+ }
+ }
+
+out:
+ yfs_free_opaque_acl(yacl);
+ key_put(key);
+ return ret;
+}
+
+static const struct xattr_handler afs_xattr_yfs_handler = {
+ .prefix = "afs.yfs.",
+ .get = afs_xattr_get_yfs,
+};
+
+/*
* Get the name of the cell on which a file resides.
*/
static int afs_xattr_get_cell(const struct xattr_handler *handler,
@@ -227,5 +325,6 @@ const struct xattr_handler *afs_xattr_handlers[] = {
&afs_xattr_afs_cell_handler,
&afs_xattr_afs_fid_handler,
&afs_xattr_afs_volume_handler,
+ &afs_xattr_yfs_handler, /* afs.yfs. prefix */
NULL
};