]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/ocfs2-add-POSIX-ACL-API.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / ocfs2-add-POSIX-ACL-API.patch
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
4 Patch-mainline: 2.6.29
5
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
8 attribute entry.
9
10 Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
11 Signed-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
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 := \
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
38 diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
39 new file mode 100644
40 index 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 +};
422 diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
423 new file mode 100644
424 index 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 */
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 */
466 };
467
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 = {
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 };
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;
508 +#endif
509 extern struct xattr_handler *ocfs2_xattr_handlers[];
510
511 ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);
512 --
513 1.5.6
514