diff options
author | Joe Gorse <jhgorse@gmail.com> | 2019-04-25 15:26:52 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-05-07 17:48:44 +0200 |
commit | b10494af4989d2d20679d0e3b7d1a45c2f8f8f1a (patch) | |
tree | 27a9fcdea021ddcb324da97695aa2efb8326ff69 /fs/afs/fsclient.c | |
parent | afs: Get an AFS3 ACL as an xattr (diff) | |
download | linux-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.c | 61 |
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); +} |