1 From: Tiger Yang <tiger.yang@oracle.com>
2 Date: Fri, 14 Nov 2008 11:17:04 +0800
3 Subject: ocfs2: add POSIX ACL API
6 This patch adds POSIX ACL(access control lists) APIs in ocfs2. We convert
7 struct posix_acl to many ocfs2_acl_entry and regard them as an extended
10 Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
11 Signed-off-by: Mark Fasheh <mfasheh@suse.com>
13 fs/ocfs2/Makefile | 4 +
14 fs/ocfs2/acl.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++++++
15 fs/ocfs2/acl.h | 29 ++++
16 fs/ocfs2/ocfs2.h | 1 +
17 fs/ocfs2/xattr.c | 10 ++
18 fs/ocfs2/xattr.h | 4 +
19 6 files changed, 426 insertions(+), 0 deletions(-)
20 create mode 100644 fs/ocfs2/acl.c
21 create mode 100644 fs/ocfs2/acl.h
23 diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
24 index 589dcdf..e9ef5d1 100644
25 --- a/fs/ocfs2/Makefile
26 +++ b/fs/ocfs2/Makefile
27 @@ -37,6 +37,10 @@ ocfs2-objs := \
31 +ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y)
35 ocfs2_stackglue-objs := stackglue.o
36 ocfs2_stack_o2cb-objs := stack_o2cb.o
37 ocfs2_stack_user-objs := stack_user.o
38 diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
40 index 0000000..62d0faa
44 +/* -*- mode: c; c-basic-offset: 8; -*-
45 + * vim: noexpandtab sw=8 ts=8 sts=0:
49 + * Copyright (C) 2004, 2008 Oracle. All rights reserved.
52 + * Lots of code in this file is copy from linux/fs/ext3/acl.c.
53 + * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
55 + * This program is free software; you can redistribute it and/or
56 + * modify it under the terms of the GNU General Public
57 + * License version 2 as published by the Free Software Foundation.
59 + * This program is distributed in the hope that it will be useful,
60 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
61 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
62 + * General Public License for more details.
65 +#include <linux/init.h>
66 +#include <linux/module.h>
67 +#include <linux/string.h>
69 +#define MLOG_MASK_PREFIX ML_INODE
70 +#include <cluster/masklog.h>
76 +#include "ocfs2_fs.h"
82 + * Convert from xattr value to acl struct.
84 +static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size)
87 + struct posix_acl *acl;
91 + if (size < sizeof(struct posix_acl_entry))
92 + return ERR_PTR(-EINVAL);
94 + count = size / sizeof(struct posix_acl_entry);
96 + return ERR_PTR(-EINVAL);
100 + acl = posix_acl_alloc(count, GFP_NOFS);
102 + return ERR_PTR(-ENOMEM);
103 + for (n = 0; n < count; n++) {
104 + struct ocfs2_acl_entry *entry =
105 + (struct ocfs2_acl_entry *)value;
107 + acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
108 + acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
109 + acl->a_entries[n].e_id = le32_to_cpu(entry->e_id);
110 + value += sizeof(struct posix_acl_entry);
117 + * Convert acl struct to xattr value.
119 +static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size)
121 + struct ocfs2_acl_entry *entry = NULL;
125 + *size = acl->a_count * sizeof(struct posix_acl_entry);
127 + ocfs2_acl = kmalloc(*size, GFP_NOFS);
129 + return ERR_PTR(-ENOMEM);
131 + entry = (struct ocfs2_acl_entry *)ocfs2_acl;
132 + for (n = 0; n < acl->a_count; n++, entry++) {
133 + entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);
134 + entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
135 + entry->e_id = cpu_to_le32(acl->a_entries[n].e_id);
140 +static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode,
142 + struct buffer_head *di_bh)
144 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
146 + char *value = NULL;
147 + struct posix_acl *acl;
150 + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
154 + case ACL_TYPE_ACCESS:
155 + name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
157 + case ACL_TYPE_DEFAULT:
158 + name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
161 + return ERR_PTR(-EINVAL);
164 + retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0);
166 + value = kmalloc(retval, GFP_NOFS);
168 + return ERR_PTR(-ENOMEM);
169 + retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
170 + "", value, retval);
174 + acl = ocfs2_acl_from_xattr(value, retval);
175 + else if (retval == -ENODATA || retval == 0)
178 + acl = ERR_PTR(retval);
189 +static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
191 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
192 + struct buffer_head *di_bh = NULL;
193 + struct posix_acl *acl;
196 + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
199 + ret = ocfs2_inode_lock(inode, &di_bh, 0);
202 + acl = ERR_PTR(ret);
206 + acl = ocfs2_get_acl_nolock(inode, type, di_bh);
208 + ocfs2_inode_unlock(inode, 0);
216 + * Set the access or default ACL of an inode.
218 +static int ocfs2_set_acl(handle_t *handle,
219 + struct inode *inode,
220 + struct buffer_head *di_bh,
222 + struct posix_acl *acl,
223 + struct ocfs2_alloc_context *meta_ac,
224 + struct ocfs2_alloc_context *data_ac)
227 + void *value = NULL;
231 + if (S_ISLNK(inode->i_mode))
232 + return -EOPNOTSUPP;
235 + case ACL_TYPE_ACCESS:
236 + name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
238 + mode_t mode = inode->i_mode;
239 + ret = posix_acl_equiv_mode(acl, &mode);
243 + inode->i_mode = mode;
249 + case ACL_TYPE_DEFAULT:
250 + name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
251 + if (!S_ISDIR(inode->i_mode))
252 + return acl ? -EACCES : 0;
259 + value = ocfs2_acl_to_xattr(acl, &size);
261 + return (int)PTR_ERR(value);
265 + ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index,
266 + "", value, size, 0,
269 + ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0);
276 +static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
282 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
283 + const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
285 + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
288 + if (list && size <= list_len)
289 + memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
293 +static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
299 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
300 + const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
302 + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
305 + if (list && size <= list_len)
306 + memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
310 +static int ocfs2_xattr_get_acl(struct inode *inode,
315 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
316 + struct posix_acl *acl;
319 + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
320 + return -EOPNOTSUPP;
322 + acl = ocfs2_get_acl(inode, type);
324 + return PTR_ERR(acl);
327 + ret = posix_acl_to_xattr(acl, buffer, size);
328 + posix_acl_release(acl);
333 +static int ocfs2_xattr_get_acl_access(struct inode *inode,
338 + if (strcmp(name, "") != 0)
340 + return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
343 +static int ocfs2_xattr_get_acl_default(struct inode *inode,
348 + if (strcmp(name, "") != 0)
350 + return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
353 +static int ocfs2_xattr_set_acl(struct inode *inode,
358 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
359 + struct posix_acl *acl;
362 + if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
363 + return -EOPNOTSUPP;
365 + if (!is_owner_or_cap(inode))
369 + acl = posix_acl_from_xattr(value, size);
371 + return PTR_ERR(acl);
373 + ret = posix_acl_valid(acl);
380 + ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
383 + posix_acl_release(acl);
387 +static int ocfs2_xattr_set_acl_access(struct inode *inode,
393 + if (strcmp(name, "") != 0)
395 + return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
398 +static int ocfs2_xattr_set_acl_default(struct inode *inode,
404 + if (strcmp(name, "") != 0)
406 + return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
409 +struct xattr_handler ocfs2_xattr_acl_access_handler = {
410 + .prefix = POSIX_ACL_XATTR_ACCESS,
411 + .list = ocfs2_xattr_list_acl_access,
412 + .get = ocfs2_xattr_get_acl_access,
413 + .set = ocfs2_xattr_set_acl_access,
416 +struct xattr_handler ocfs2_xattr_acl_default_handler = {
417 + .prefix = POSIX_ACL_XATTR_DEFAULT,
418 + .list = ocfs2_xattr_list_acl_default,
419 + .get = ocfs2_xattr_get_acl_default,
420 + .set = ocfs2_xattr_set_acl_default,
422 diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
424 index 0000000..1b39f3e
428 +/* -*- mode: c; c-basic-offset: 8; -*-
429 + * vim: noexpandtab sw=8 ts=8 sts=0:
433 + * Copyright (C) 2004, 2008 Oracle. All rights reserved.
435 + * This program is free software; you can redistribute it and/or
436 + * modify it under the terms of the GNU General Public
437 + * License version 2 as published by the Free Software Foundation.
439 + * This program is distributed in the hope that it will be useful,
440 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
441 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
442 + * General Public License for more details.
448 +#include <linux/posix_acl_xattr.h>
450 +struct ocfs2_acl_entry {
456 +#endif /* OCFS2_ACL_H */
457 diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
458 index 3fed9e3..25d07ff 100644
459 --- a/fs/ocfs2/ocfs2.h
460 +++ b/fs/ocfs2/ocfs2.h
461 @@ -195,6 +195,7 @@ enum ocfs2_mount_options
462 OCFS2_MOUNT_LOCALFLOCKS = 1 << 5, /* No cluster aware user file locks */
463 OCFS2_MOUNT_NOUSERXATTR = 1 << 6, /* No user xattr */
464 OCFS2_MOUNT_INODE64 = 1 << 7, /* Allow inode numbers > 2^32 */
465 + OCFS2_MOUNT_POSIX_ACL = 1 << 8, /* POSIX access control lists */
468 #define OCFS2_OSB_SOFT_RO 0x0001
469 diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
470 index ba9b870..2e273c2 100644
471 --- a/fs/ocfs2/xattr.c
472 +++ b/fs/ocfs2/xattr.c
473 @@ -91,6 +91,10 @@ static struct ocfs2_xattr_def_value_root def_xv = {
475 struct xattr_handler *ocfs2_xattr_handlers[] = {
476 &ocfs2_xattr_user_handler,
477 +#ifdef CONFIG_OCFS2_FS_POSIX_ACL
478 + &ocfs2_xattr_acl_access_handler,
479 + &ocfs2_xattr_acl_default_handler,
481 &ocfs2_xattr_trusted_handler,
482 &ocfs2_xattr_security_handler,
484 @@ -98,6 +102,12 @@ struct xattr_handler *ocfs2_xattr_handlers[] = {
486 static struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
487 [OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler,
488 +#ifdef CONFIG_OCFS2_FS_POSIX_ACL
489 + [OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]
490 + = &ocfs2_xattr_acl_access_handler,
491 + [OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]
492 + = &ocfs2_xattr_acl_default_handler,
494 [OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler,
495 [OCFS2_XATTR_INDEX_SECURITY] = &ocfs2_xattr_security_handler,
497 diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
498 index 86aa10f..6163df3 100644
499 --- a/fs/ocfs2/xattr.h
500 +++ b/fs/ocfs2/xattr.h
501 @@ -40,6 +40,10 @@ struct ocfs2_security_xattr_info {
502 extern struct xattr_handler ocfs2_xattr_user_handler;
503 extern struct xattr_handler ocfs2_xattr_trusted_handler;
504 extern struct xattr_handler ocfs2_xattr_security_handler;
505 +#ifdef CONFIG_OCFS2_FS_POSIX_ACL
506 +extern struct xattr_handler ocfs2_xattr_acl_access_handler;
507 +extern struct xattr_handler ocfs2_xattr_acl_default_handler;
509 extern struct xattr_handler *ocfs2_xattr_handlers[];
511 ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);