afs: Implement YFS ACL setting
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 <dhowells@redhat.com>
This commit is contained in:
parent
ae46578b96
commit
f5e4546347
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue