]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/ocfs2-add-POSIX-ACL-API.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / ocfs2-add-POSIX-ACL-API.patch
CommitLineData
2cb7cef9
BS
1From: Tiger Yang <tiger.yang@oracle.com>
2Date: Fri, 14 Nov 2008 11:17:04 +0800
3Subject: ocfs2: add POSIX ACL API
4Patch-mainline: 2.6.29
5
6This patch adds POSIX ACL(access control lists) APIs in ocfs2. We convert
7struct posix_acl to many ocfs2_acl_entry and regard them as an extended
8attribute entry.
9
10Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
11Signed-off-by: Mark Fasheh <mfasheh@suse.com>
12---
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
22
23diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
24index 589dcdf..e9ef5d1 100644
25--- a/fs/ocfs2/Makefile
26+++ b/fs/ocfs2/Makefile
27@@ -37,6 +37,10 @@ ocfs2-objs := \
28 ver.o \
29 xattr.o
30
31+ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y)
32+ocfs2-objs += acl.o
33+endif
34+
35 ocfs2_stackglue-objs := stackglue.o
36 ocfs2_stack_o2cb-objs := stack_o2cb.o
37 ocfs2_stack_user-objs := stack_user.o
38diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
39new file mode 100644
40index 0000000..62d0faa
41--- /dev/null
42+++ b/fs/ocfs2/acl.c
43@@ -0,0 +1,378 @@
44+/* -*- mode: c; c-basic-offset: 8; -*-
45+ * vim: noexpandtab sw=8 ts=8 sts=0:
46+ *
47+ * acl.c
48+ *
49+ * Copyright (C) 2004, 2008 Oracle. All rights reserved.
50+ *
51+ * CREDITS:
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>
54+ *
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.
58+ *
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.
63+ */
64+
65+#include <linux/init.h>
66+#include <linux/module.h>
67+#include <linux/string.h>
68+
69+#define MLOG_MASK_PREFIX ML_INODE
70+#include <cluster/masklog.h>
71+
72+#include "ocfs2.h"
73+#include "alloc.h"
74+#include "dlmglue.h"
75+#include "file.h"
76+#include "ocfs2_fs.h"
77+
78+#include "xattr.h"
79+#include "acl.h"
80+
81+/*
82+ * Convert from xattr value to acl struct.
83+ */
84+static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size)
85+{
86+ int n, count;
87+ struct posix_acl *acl;
88+
89+ if (!value)
90+ return NULL;
91+ if (size < sizeof(struct posix_acl_entry))
92+ return ERR_PTR(-EINVAL);
93+
94+ count = size / sizeof(struct posix_acl_entry);
95+ if (count < 0)
96+ return ERR_PTR(-EINVAL);
97+ if (count == 0)
98+ return NULL;
99+
100+ acl = posix_acl_alloc(count, GFP_NOFS);
101+ if (!acl)
102+ return ERR_PTR(-ENOMEM);
103+ for (n = 0; n < count; n++) {
104+ struct ocfs2_acl_entry *entry =
105+ (struct ocfs2_acl_entry *)value;
106+
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);
111+
112+ }
113+ return acl;
114+}
115+
116+/*
117+ * Convert acl struct to xattr value.
118+ */
119+static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size)
120+{
121+ struct ocfs2_acl_entry *entry = NULL;
122+ char *ocfs2_acl;
123+ size_t n;
124+
125+ *size = acl->a_count * sizeof(struct posix_acl_entry);
126+
127+ ocfs2_acl = kmalloc(*size, GFP_NOFS);
128+ if (!ocfs2_acl)
129+ return ERR_PTR(-ENOMEM);
130+
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);
136+ }
137+ return ocfs2_acl;
138+}
139+
140+static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode,
141+ int type,
142+ struct buffer_head *di_bh)
143+{
144+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
145+ int name_index;
146+ char *value = NULL;
147+ struct posix_acl *acl;
148+ int retval;
149+
150+ if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
151+ return NULL;
152+
153+ switch (type) {
154+ case ACL_TYPE_ACCESS:
155+ name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
156+ break;
157+ case ACL_TYPE_DEFAULT:
158+ name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
159+ break;
160+ default:
161+ return ERR_PTR(-EINVAL);
162+ }
163+
164+ retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0);
165+ if (retval > 0) {
166+ value = kmalloc(retval, GFP_NOFS);
167+ if (!value)
168+ return ERR_PTR(-ENOMEM);
169+ retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
170+ "", value, retval);
171+ }
172+
173+ if (retval > 0)
174+ acl = ocfs2_acl_from_xattr(value, retval);
175+ else if (retval == -ENODATA || retval == 0)
176+ acl = NULL;
177+ else
178+ acl = ERR_PTR(retval);
179+
180+ kfree(value);
181+
182+ return acl;
183+}
184+
185+
186+/*
187+ * Get posix acl.
188+ */
189+static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
190+{
191+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
192+ struct buffer_head *di_bh = NULL;
193+ struct posix_acl *acl;
194+ int ret;
195+
196+ if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
197+ return NULL;
198+
199+ ret = ocfs2_inode_lock(inode, &di_bh, 0);
200+ if (ret < 0) {
201+ mlog_errno(ret);
202+ acl = ERR_PTR(ret);
203+ return acl;
204+ }
205+
206+ acl = ocfs2_get_acl_nolock(inode, type, di_bh);
207+
208+ ocfs2_inode_unlock(inode, 0);
209+
210+ brelse(di_bh);
211+
212+ return acl;
213+}
214+
215+/*
216+ * Set the access or default ACL of an inode.
217+ */
218+static int ocfs2_set_acl(handle_t *handle,
219+ struct inode *inode,
220+ struct buffer_head *di_bh,
221+ int type,
222+ struct posix_acl *acl,
223+ struct ocfs2_alloc_context *meta_ac,
224+ struct ocfs2_alloc_context *data_ac)
225+{
226+ int name_index;
227+ void *value = NULL;
228+ size_t size = 0;
229+ int ret;
230+
231+ if (S_ISLNK(inode->i_mode))
232+ return -EOPNOTSUPP;
233+
234+ switch (type) {
235+ case ACL_TYPE_ACCESS:
236+ name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
237+ if (acl) {
238+ mode_t mode = inode->i_mode;
239+ ret = posix_acl_equiv_mode(acl, &mode);
240+ if (ret < 0)
241+ return ret;
242+ else {
243+ inode->i_mode = mode;
244+ if (ret == 0)
245+ acl = NULL;
246+ }
247+ }
248+ break;
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;
253+ break;
254+ default:
255+ return -EINVAL;
256+ }
257+
258+ if (acl) {
259+ value = ocfs2_acl_to_xattr(acl, &size);
260+ if (IS_ERR(value))
261+ return (int)PTR_ERR(value);
262+ }
263+
264+ if (handle)
265+ ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index,
266+ "", value, size, 0,
267+ meta_ac, data_ac);
268+ else
269+ ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0);
270+
271+ kfree(value);
272+
273+ return ret;
274+}
275+
276+static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
277+ char *list,
278+ size_t list_len,
279+ const char *name,
280+ size_t name_len)
281+{
282+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
283+ const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
284+
285+ if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
286+ return 0;
287+
288+ if (list && size <= list_len)
289+ memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
290+ return size;
291+}
292+
293+static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
294+ char *list,
295+ size_t list_len,
296+ const char *name,
297+ size_t name_len)
298+{
299+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
300+ const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
301+
302+ if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
303+ return 0;
304+
305+ if (list && size <= list_len)
306+ memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
307+ return size;
308+}
309+
310+static int ocfs2_xattr_get_acl(struct inode *inode,
311+ int type,
312+ void *buffer,
313+ size_t size)
314+{
315+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
316+ struct posix_acl *acl;
317+ int ret;
318+
319+ if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
320+ return -EOPNOTSUPP;
321+
322+ acl = ocfs2_get_acl(inode, type);
323+ if (IS_ERR(acl))
324+ return PTR_ERR(acl);
325+ if (acl == NULL)
326+ return -ENODATA;
327+ ret = posix_acl_to_xattr(acl, buffer, size);
328+ posix_acl_release(acl);
329+
330+ return ret;
331+}
332+
333+static int ocfs2_xattr_get_acl_access(struct inode *inode,
334+ const char *name,
335+ void *buffer,
336+ size_t size)
337+{
338+ if (strcmp(name, "") != 0)
339+ return -EINVAL;
340+ return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
341+}
342+
343+static int ocfs2_xattr_get_acl_default(struct inode *inode,
344+ const char *name,
345+ void *buffer,
346+ size_t size)
347+{
348+ if (strcmp(name, "") != 0)
349+ return -EINVAL;
350+ return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
351+}
352+
353+static int ocfs2_xattr_set_acl(struct inode *inode,
354+ int type,
355+ const void *value,
356+ size_t size)
357+{
358+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
359+ struct posix_acl *acl;
360+ int ret = 0;
361+
362+ if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
363+ return -EOPNOTSUPP;
364+
365+ if (!is_owner_or_cap(inode))
366+ return -EPERM;
367+
368+ if (value) {
369+ acl = posix_acl_from_xattr(value, size);
370+ if (IS_ERR(acl))
371+ return PTR_ERR(acl);
372+ else if (acl) {
373+ ret = posix_acl_valid(acl);
374+ if (ret)
375+ goto cleanup;
376+ }
377+ } else
378+ acl = NULL;
379+
380+ ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
381+
382+cleanup:
383+ posix_acl_release(acl);
384+ return ret;
385+}
386+
387+static int ocfs2_xattr_set_acl_access(struct inode *inode,
388+ const char *name,
389+ const void *value,
390+ size_t size,
391+ int flags)
392+{
393+ if (strcmp(name, "") != 0)
394+ return -EINVAL;
395+ return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
396+}
397+
398+static int ocfs2_xattr_set_acl_default(struct inode *inode,
399+ const char *name,
400+ const void *value,
401+ size_t size,
402+ int flags)
403+{
404+ if (strcmp(name, "") != 0)
405+ return -EINVAL;
406+ return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
407+}
408+
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,
414+};
415+
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,
421+};
422diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
423new file mode 100644
424index 0000000..1b39f3e
425--- /dev/null
426+++ b/fs/ocfs2/acl.h
427@@ -0,0 +1,29 @@
428+/* -*- mode: c; c-basic-offset: 8; -*-
429+ * vim: noexpandtab sw=8 ts=8 sts=0:
430+ *
431+ * acl.h
432+ *
433+ * Copyright (C) 2004, 2008 Oracle. All rights reserved.
434+ *
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.
438+ *
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.
443+ */
444+
445+#ifndef OCFS2_ACL_H
446+#define OCFS2_ACL_H
447+
448+#include <linux/posix_acl_xattr.h>
449+
450+struct ocfs2_acl_entry {
451+ __le16 e_tag;
452+ __le16 e_perm;
453+ __le32 e_id;
454+};
455+
456+#endif /* OCFS2_ACL_H */
457diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
458index 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 */
466 };
467
468 #define OCFS2_OSB_SOFT_RO 0x0001
469diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
470index 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 = {
474
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,
480+#endif
481 &ocfs2_xattr_trusted_handler,
482 &ocfs2_xattr_security_handler,
483 NULL
484@@ -98,6 +102,12 @@ struct xattr_handler *ocfs2_xattr_handlers[] = {
485
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,
493+#endif
494 [OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler,
495 [OCFS2_XATTR_INDEX_SECURITY] = &ocfs2_xattr_security_handler,
496 };
497diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
498index 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;
508+#endif
509 extern struct xattr_handler *ocfs2_xattr_handlers[];
510
511 ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);
512--
5131.5.6
514