Skip to content

Commit

Permalink
afs: Implement YFS ACL setting
Browse files Browse the repository at this point in the history
Implement the setting of YFS ACLs in AFS through the interface of setting
the afs.yfs.acl extended attribute on the file.

Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed May 7, 2019
1 parent ae46578 commit f5e4546
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 5 deletions.
1 change: 1 addition & 0 deletions fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,7 @@ struct yfs_acl {

extern void yfs_free_opaque_acl(struct yfs_acl *);
extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, unsigned int);
extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *);

/*
* Miscellaneous inline functions.
Expand Down
49 changes: 49 additions & 0 deletions fs/afs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,58 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
return ret;
}

/*
* Set a file's YFS ACL.
*/
static int afs_xattr_set_yfs(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 ||
strcmp(name, "acl") != 0)
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);
yfs_fs_store_opaque_acl2(&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_yfs_handler = {
.prefix = "afs.yfs.",
.get = afs_xattr_get_yfs,
.set = afs_xattr_set_yfs,
};

/*
Expand Down
67 changes: 62 additions & 5 deletions fs/afs/yfsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1768,9 +1768,10 @@ int yfs_fs_get_volume_status(struct afs_fs_cursor *fc,
}

/*
* Deliver reply data to an YFS.SetLock, YFS.ExtendLock or YFS.ReleaseLock
* Deliver reply data to operations that just return a file status and a volume
* sync record.
*/
static int yfs_deliver_fs_xxxx_lock(struct afs_call *call)
static int yfs_deliver_status_and_volsync(struct afs_call *call)
{
struct afs_vnode *vnode = call->reply[0];
const __be32 *bp;
Expand Down Expand Up @@ -1800,7 +1801,7 @@ static int yfs_deliver_fs_xxxx_lock(struct afs_call *call)
static const struct afs_call_type yfs_RXYFSSetLock = {
.name = "YFS.SetLock",
.op = yfs_FS_SetLock,
.deliver = yfs_deliver_fs_xxxx_lock,
.deliver = yfs_deliver_status_and_volsync,
.done = afs_lock_op_done,
.destructor = afs_flat_call_destructor,
};
Expand All @@ -1811,7 +1812,7 @@ static const struct afs_call_type yfs_RXYFSSetLock = {
static const struct afs_call_type yfs_RXYFSExtendLock = {
.name = "YFS.ExtendLock",
.op = yfs_FS_ExtendLock,
.deliver = yfs_deliver_fs_xxxx_lock,
.deliver = yfs_deliver_status_and_volsync,
.done = afs_lock_op_done,
.destructor = afs_flat_call_destructor,
};
Expand All @@ -1822,7 +1823,7 @@ static const struct afs_call_type yfs_RXYFSExtendLock = {
static const struct afs_call_type yfs_RXYFSReleaseLock = {
.name = "YFS.ReleaseLock",
.op = yfs_FS_ReleaseLock,
.deliver = yfs_deliver_fs_xxxx_lock,
.deliver = yfs_deliver_status_and_volsync,
.destructor = afs_flat_call_destructor,
};

Expand Down Expand Up @@ -2392,3 +2393,59 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
fc->ac.error = -ENOMEM;
return ERR_PTR(-ENOMEM);
}

/*
* YFS.StoreOpaqueACL2 operation type
*/
static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = {
.name = "YFS.StoreOpaqueACL2",
.op = yfs_FS_StoreOpaqueACL2,
.deliver = yfs_deliver_status_and_volsync,
.destructor = afs_flat_call_destructor,
};

/*
* Fetch the YFS ACL for a file.
*/
int yfs_fs_store_opaque_acl2(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, &yfs_RXYFSStoreStatus,
sizeof(__be32) * 2 +
sizeof(struct yfs_xdr_YFSFid) +
sizeof(__be32) + size,
sizeof(struct yfs_xdr_YFSFetchStatus) +
sizeof(struct yfs_xdr_YFSVolSync));
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 = xdr_encode_u32(bp, YFSSTOREOPAQUEACL2);
bp = xdr_encode_u32(bp, 0); /* RPC flags */
bp = xdr_encode_YFSFid(bp, &vnode->fid);
bp = xdr_encode_u32(bp, acl->size);
memcpy(bp, acl->data, acl->size);
if (acl->size != size)
memset((void *)bp + acl->size, 0, size - acl->size);
yfs_check_req(call, bp);

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);
}

0 comments on commit f5e4546

Please sign in to comment.