Commit b10494af authored by Joe Gorse's avatar Joe Gorse Committed by David Howells
Browse files

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: default avatarJoe Gorse <jhgorse@gmail.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 260f082b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+57 −4
Original line number Diff line number Diff line
@@ -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);
}
+1 −0
Original line number Diff line number Diff line
@@ -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
+50 −2
Original line number Diff line number Diff line
@@ -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,
	.set    = afs_xattr_set_acl,
};

/*
+1 −0
Original line number Diff line number Diff line
@@ -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 */