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>
This commit is contained in:
parent
260f082bae
commit
b10494af49
|
@ -20,6 +20,7 @@ enum AFS_FS_Operations {
|
||||||
FSFETCHACL = 131, /* AFS Fetch file ACL */
|
FSFETCHACL = 131, /* AFS Fetch file ACL */
|
||||||
FSFETCHSTATUS = 132, /* AFS Fetch file status */
|
FSFETCHSTATUS = 132, /* AFS Fetch file status */
|
||||||
FSSTOREDATA = 133, /* AFS Store file data */
|
FSSTOREDATA = 133, /* AFS Store file data */
|
||||||
|
FSSTOREACL = 134, /* AFS Store file ACL */
|
||||||
FSSTORESTATUS = 135, /* AFS Store file status */
|
FSSTORESTATUS = 135, /* AFS Store file status */
|
||||||
FSREMOVEFILE = 136, /* AFS Remove a file */
|
FSREMOVEFILE = 136, /* AFS Remove a file */
|
||||||
FSCREATEFILE = 137, /* AFS Create a file */
|
FSCREATEFILE = 137, /* AFS Create a file */
|
||||||
|
|
|
@ -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];
|
struct afs_vnode *vnode = call->reply[0];
|
||||||
const __be32 *bp;
|
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 = {
|
static const struct afs_call_type afs_RXFSRemoveFile = {
|
||||||
.name = "FS.RemoveFile",
|
.name = "FS.RemoveFile",
|
||||||
.op = afs_FS_RemoveFile,
|
.op = afs_FS_RemoveFile,
|
||||||
.deliver = afs_deliver_fs_remove,
|
.deliver = afs_deliver_fs_status_and_vol,
|
||||||
.destructor = afs_flat_call_destructor,
|
.destructor = afs_flat_call_destructor,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct afs_call_type afs_RXFSRemoveDir = {
|
static const struct afs_call_type afs_RXFSRemoveDir = {
|
||||||
.name = "FS.RemoveDir",
|
.name = "FS.RemoveDir",
|
||||||
.op = afs_FS_RemoveDir,
|
.op = afs_FS_RemoveDir,
|
||||||
.deliver = afs_deliver_fs_remove,
|
.deliver = afs_deliver_fs_status_and_vol,
|
||||||
.destructor = afs_flat_call_destructor,
|
.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);
|
afs_make_call(&fc->ac, call, GFP_KERNEL);
|
||||||
return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -983,6 +983,7 @@ struct afs_acl {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *);
|
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
|
* fs_probe.c
|
||||||
|
|
|
@ -80,9 +80,57 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
|
||||||
return ret;
|
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 = {
|
static const struct xattr_handler afs_xattr_afs_acl_handler = {
|
||||||
.name = "afs.acl",
|
.name = "afs.acl",
|
||||||
.get = afs_xattr_get_acl,
|
.get = afs_xattr_get_acl,
|
||||||
|
.set = afs_xattr_set_acl,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -36,6 +36,7 @@ enum afs_fs_operation {
|
||||||
afs_FS_FetchACL = 131, /* AFS Fetch file ACL */
|
afs_FS_FetchACL = 131, /* AFS Fetch file ACL */
|
||||||
afs_FS_FetchStatus = 132, /* AFS Fetch file status */
|
afs_FS_FetchStatus = 132, /* AFS Fetch file status */
|
||||||
afs_FS_StoreData = 133, /* AFS Store file data */
|
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_StoreStatus = 135, /* AFS Store file status */
|
||||||
afs_FS_RemoveFile = 136, /* AFS Remove a file */
|
afs_FS_RemoveFile = 136, /* AFS Remove a file */
|
||||||
afs_FS_CreateFile = 137, /* AFS Create a file */
|
afs_FS_CreateFile = 137, /* AFS Create a file */
|
||||||
|
|
Loading…
Reference in New Issue