summaryrefslogtreecommitdiffstats
path: root/fs/afs/fsclient.c
diff options
context:
space:
mode:
authorJoe Gorse <jhgorse@gmail.com>2019-04-25 15:26:52 +0200
committerDavid Howells <dhowells@redhat.com>2019-05-07 17:48:44 +0200
commitb10494af4989d2d20679d0e3b7d1a45c2f8f8f1a (patch)
tree27a9fcdea021ddcb324da97695aa2efb8326ff69 /fs/afs/fsclient.c
parentafs: Get an AFS3 ACL as an xattr (diff)
downloadlinux-b10494af4989d2d20679d0e3b7d1a45c2f8f8f1a.tar.xz
linux-b10494af4989d2d20679d0e3b7d1a45c2f8f8f1a.zip
afs: implement acl setting
Implements the setting of ACLs in AFS by means of setting the afs.acl extended attribute on the file. Signed-off-by: Joe Gorse <jhgorse@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r--fs/afs/fsclient.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 283f486c59f4..7f1722b9e432 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -836,9 +836,10 @@ int afs_fs_create(struct afs_fs_cursor *fc,
}
/*
- * deliver reply data to an FS.RemoveFile or FS.RemoveDir
+ * Deliver reply data to any operation that returns file status and volume
+ * sync.
*/
-static int afs_deliver_fs_remove(struct afs_call *call)
+static int afs_deliver_fs_status_and_vol(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply[0];
const __be32 *bp;
@@ -868,14 +869,14 @@ static int afs_deliver_fs_remove(struct afs_call *call)
static const struct afs_call_type afs_RXFSRemoveFile = {
.name = "FS.RemoveFile",
.op = afs_FS_RemoveFile,
- .deliver = afs_deliver_fs_remove,
+ .deliver = afs_deliver_fs_status_and_vol,
.destructor = afs_flat_call_destructor,
};
static const struct afs_call_type afs_RXFSRemoveDir = {
.name = "FS.RemoveDir",
.op = afs_FS_RemoveDir,
- .deliver = afs_deliver_fs_remove,
+ .deliver = afs_deliver_fs_status_and_vol,
.destructor = afs_flat_call_destructor,
};
@@ -2513,3 +2514,55 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc)
afs_make_call(&fc->ac, call, GFP_KERNEL);
return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
}
+
+/*
+ * FS.StoreACL operation type
+ */
+static const struct afs_call_type afs_RXFSStoreACL = {
+ .name = "FS.StoreACL",
+ .op = afs_FS_StoreACL,
+ .deliver = afs_deliver_fs_status_and_vol,
+ .destructor = afs_flat_call_destructor,
+};
+
+/*
+ * Fetch the ACL for a file.
+ */
+int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl)
+{
+ struct afs_vnode *vnode = fc->vnode;
+ struct afs_call *call;
+ struct afs_net *net = afs_v2net(vnode);
+ size_t size;
+ __be32 *bp;
+
+ _enter(",%x,{%llx:%llu},,",
+ key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
+
+ size = round_up(acl->size, 4);
+ call = afs_alloc_flat_call(net, &afs_RXFSStoreACL,
+ 5 * 4 + size, (21 + 6) * 4);
+ if (!call) {
+ fc->ac.error = -ENOMEM;
+ return -ENOMEM;
+ }
+
+ call->key = fc->key;
+ call->reply[0] = vnode;
+ call->reply[2] = NULL; /* volsync */
+
+ /* marshall the parameters */
+ bp = call->request;
+ bp[0] = htonl(FSSTOREACL);
+ bp[1] = htonl(vnode->fid.vid);
+ bp[2] = htonl(vnode->fid.vnode);
+ bp[3] = htonl(vnode->fid.unique);
+ bp[4] = htonl(acl->size);
+ memcpy(&bp[5], acl->data, acl->size);
+ if (acl->size != size)
+ memset((void *)&bp[5] + acl->size, 0, size - acl->size);
+
+ trace_afs_make_fs_call(call, &vnode->fid);
+ afs_make_call(&fc->ac, call, GFP_KERNEL);
+ return afs_wait_for_call_to_complete(call, &fc->ac);
+}