summaryrefslogtreecommitdiffstats
path: root/fs/afs/xattr.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-04-30 19:30:21 +0200
committerDavid Howells <dhowells@redhat.com>2019-05-07 17:48:44 +0200
commitae46578b963f6daa9853791ab4c6ac1d6375937c (patch)
tree2ec257ba3ec3b10321c03ea6205879edabd28d9d /fs/afs/xattr.c
parentafs: implement acl setting (diff)
downloadlinux-ae46578b963f6daa9853791ab4c6ac1d6375937c.tar.xz
linux-ae46578b963f6daa9853791ab4c6ac1d6375937c.zip
afs: Get YFS ACLs and information through xattrs
The YFS/AuriStor variant of AFS provides more capable ACLs and provides per-volume ACLs and per-file ACLs as well as per-directory ACLs. It also provides some extra information that can be retrieved through four ACLs: (1) afs.yfs.acl The YFS file ACL (not the same format as afs.acl). (2) afs.yfs.vol_acl The YFS volume ACL. (3) afs.yfs.acl_inherited "1" if a file's ACL is inherited from its parent directory, "0" otherwise. (4) afs.yfs.acl_num_cleaned The number of of ACEs removed from the ACL by the server because the PT entries were removed from the PTS database (ie. the subject is no longer known). Signed-off-by: David Howells <dhowells@redhat.com>
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
};