Skip to content

Commit

Permalink
afs: implement acl setting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Joe Gorse authored and David Howells committed May 7, 2019
1 parent 260f082 commit b10494a
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 6 deletions.
1 change: 1 addition & 0 deletions fs/afs/afs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum AFS_FS_Operations {
FSFETCHACL = 131, /* AFS Fetch file ACL */
FSFETCHSTATUS = 132, /* AFS Fetch file status */
FSSTOREDATA = 133, /* AFS Store file data */
FSSTOREACL = 134, /* AFS Store file ACL */
FSSTORESTATUS = 135, /* AFS Store file status */
FSREMOVEFILE = 136, /* AFS Remove a file */
FSCREATEFILE = 137, /* AFS Create a file */
Expand Down
61 changes: 57 additions & 4 deletions fs/afs/fsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
};

Expand Down Expand Up @@ -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);
}
1 change: 1 addition & 0 deletions fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ struct afs_acl {
};

extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *);
extern int afs_fs_store_acl(struct afs_fs_cursor *, const struct afs_acl *);

/*
* fs_probe.c
Expand Down
52 changes: 50 additions & 2 deletions fs/afs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,57 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
return ret;
}

/*
* Set a file's AFS3 ACL.
*/
static int afs_xattr_set_acl(const struct xattr_handler *handler,
struct dentry *dentry,
struct inode *inode, const char *name,
const void *buffer, size_t size, int flags)
{
struct afs_fs_cursor fc;
struct afs_vnode *vnode = AFS_FS_I(inode);
struct afs_acl *acl = NULL;
struct key *key;
int ret;

if (flags == XATTR_CREATE)
return -EINVAL;

key = afs_request_key(vnode->volume->cell);
if (IS_ERR(key))
return PTR_ERR(key);

acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
if (!acl) {
key_put(key);
return -ENOMEM;
}

acl->size = size;
memcpy(acl->data, buffer, size);

ret = -ERESTARTSYS;
if (afs_begin_vnode_operation(&fc, vnode, key)) {
while (afs_select_fileserver(&fc)) {
fc.cb_break = afs_calc_vnode_cb_break(vnode);
afs_fs_store_acl(&fc, acl);
}

afs_check_for_remote_deletion(&fc, fc.vnode);
afs_vnode_commit_status(&fc, vnode, fc.cb_break);
ret = afs_end_vnode_operation(&fc);
}

kfree(acl);
key_put(key);
return ret;
}

static const struct xattr_handler afs_xattr_afs_acl_handler = {
.name = "afs.acl",
.get = afs_xattr_get_acl,
.name = "afs.acl",
.get = afs_xattr_get_acl,
.set = afs_xattr_set_acl,
};

/*
Expand Down
1 change: 1 addition & 0 deletions include/trace/events/afs.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum afs_fs_operation {
afs_FS_FetchACL = 131, /* AFS Fetch file ACL */
afs_FS_FetchStatus = 132, /* AFS Fetch file status */
afs_FS_StoreData = 133, /* AFS Store file data */
afs_FS_StoreACL = 134, /* AFS Store file ACL */
afs_FS_StoreStatus = 135, /* AFS Store file status */
afs_FS_RemoveFile = 136, /* AFS Remove a file */
afs_FS_CreateFile = 137, /* AFS Create a file */
Expand Down

0 comments on commit b10494a

Please sign in to comment.