aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorTiger Yang <tiger.yang@oracle.com>2008-11-13 22:17:41 -0500
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:34:20 -0500
commit89c38bd0ade3c567707ed8fce088b253b0369c50 (patch)
treeffc5bf6a8871efa8e7793c552d16ac9fb92f1334 /fs/ocfs2
parent060bc66dd5017460076d9e808e2198cd532c943d (diff)
ocfs2: add ocfs2_init_acl in mknod
We need to get the parent directories acls and let the new child inherit it. To this, we add additional calculations for data/metadata allocation. Signed-off-by: Tiger Yang <tiger.yang@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/acl.c59
-rw-r--r--fs/ocfs2/acl.h14
-rw-r--r--fs/ocfs2/namei.c23
-rw-r--r--fs/ocfs2/xattr.c79
-rw-r--r--fs/ocfs2/xattr.h3
5 files changed, 170 insertions, 8 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index df72256c4422..12dfb44c22e5 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -272,6 +272,65 @@ int ocfs2_acl_chmod(struct inode *inode)
272 return ret; 272 return ret;
273} 273}
274 274
275/*
276 * Initialize the ACLs of a new inode. If parent directory has default ACL,
277 * then clone to new inode. Called from ocfs2_mknod.
278 */
279int ocfs2_init_acl(handle_t *handle,
280 struct inode *inode,
281 struct inode *dir,
282 struct buffer_head *di_bh,
283 struct buffer_head *dir_bh,
284 struct ocfs2_alloc_context *meta_ac,
285 struct ocfs2_alloc_context *data_ac)
286{
287 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
288 struct posix_acl *acl = NULL;
289 int ret = 0;
290
291 if (!S_ISLNK(inode->i_mode)) {
292 if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
293 acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
294 dir_bh);
295 if (IS_ERR(acl))
296 return PTR_ERR(acl);
297 }
298 if (!acl)
299 inode->i_mode &= ~current->fs->umask;
300 }
301 if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
302 struct posix_acl *clone;
303 mode_t mode;
304
305 if (S_ISDIR(inode->i_mode)) {
306 ret = ocfs2_set_acl(handle, inode, di_bh,
307 ACL_TYPE_DEFAULT, acl,
308 meta_ac, data_ac);
309 if (ret)
310 goto cleanup;
311 }
312 clone = posix_acl_clone(acl, GFP_NOFS);
313 ret = -ENOMEM;
314 if (!clone)
315 goto cleanup;
316
317 mode = inode->i_mode;
318 ret = posix_acl_create_masq(clone, &mode);
319 if (ret >= 0) {
320 inode->i_mode = mode;
321 if (ret > 0) {
322 ret = ocfs2_set_acl(handle, inode,
323 di_bh, ACL_TYPE_ACCESS,
324 clone, meta_ac, data_ac);
325 }
326 }
327 posix_acl_release(clone);
328 }
329cleanup:
330 posix_acl_release(acl);
331 return ret;
332}
333
275static size_t ocfs2_xattr_list_acl_access(struct inode *inode, 334static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
276 char *list, 335 char *list,
277 size_t list_len, 336 size_t list_len,
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index 68ffd6436c50..8f6389ed4da5 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -30,6 +30,10 @@ struct ocfs2_acl_entry {
30 30
31extern int ocfs2_check_acl(struct inode *, int); 31extern int ocfs2_check_acl(struct inode *, int);
32extern int ocfs2_acl_chmod(struct inode *); 32extern int ocfs2_acl_chmod(struct inode *);
33extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
34 struct buffer_head *, struct buffer_head *,
35 struct ocfs2_alloc_context *,
36 struct ocfs2_alloc_context *);
33 37
34#else /* CONFIG_OCFS2_FS_POSIX_ACL*/ 38#else /* CONFIG_OCFS2_FS_POSIX_ACL*/
35 39
@@ -38,6 +42,16 @@ static inline int ocfs2_acl_chmod(struct inode *inode)
38{ 42{
39 return 0; 43 return 0;
40} 44}
45static inline int ocfs2_init_acl(handle_t *handle,
46 struct inode *inode,
47 struct inode *dir,
48 struct buffer_head *di_bh,
49 struct buffer_head *dir_bh,
50 struct ocfs2_alloc_context *meta_ac,
51 struct ocfs2_alloc_context *data_ac)
52{
53 return 0;
54}
41 55
42#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/ 56#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/
43 57
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 40da46b907fb..765514512096 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -61,6 +61,7 @@
61#include "sysfile.h" 61#include "sysfile.h"
62#include "uptodate.h" 62#include "uptodate.h"
63#include "xattr.h" 63#include "xattr.h"
64#include "acl.h"
64 65
65#include "buffer_head_io.h" 66#include "buffer_head_io.h"
66 67
@@ -302,14 +303,13 @@ static int ocfs2_mknod(struct inode *dir,
302 } 303 }
303 } 304 }
304 305
305 /* calculate meta data/clusters for setting security xattr */ 306 /* calculate meta data/clusters for setting security and acl xattr */
306 if (si.enable) { 307 status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode,
307 status = ocfs2_calc_security_init(dir, &si, &want_clusters, 308 &si, &want_clusters,
308 &xattr_credits, &xattr_ac); 309 &xattr_credits, &xattr_ac);
309 if (status < 0) { 310 if (status < 0) {
310 mlog_errno(status); 311 mlog_errno(status);
311 goto leave; 312 goto leave;
312 }
313 } 313 }
314 314
315 /* Reserve a cluster if creating an extent based directory. */ 315 /* Reserve a cluster if creating an extent based directory. */
@@ -363,6 +363,13 @@ static int ocfs2_mknod(struct inode *dir,
363 inc_nlink(dir); 363 inc_nlink(dir);
364 } 364 }
365 365
366 status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
367 xattr_ac, data_ac);
368 if (status < 0) {
369 mlog_errno(status);
370 goto leave;
371 }
372
366 if (si.enable) { 373 if (si.enable) {
367 status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, 374 status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
368 xattr_ac, data_ac); 375 xattr_ac, data_ac);
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 2e273c2cb831..3cc8385f9738 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -84,6 +84,10 @@ struct ocfs2_xattr_set_ctxt {
84#define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ 84#define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \
85 - sizeof(struct ocfs2_xattr_header) \ 85 - sizeof(struct ocfs2_xattr_header) \
86 - sizeof(__u32)) 86 - sizeof(__u32))
87#define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \
88 - sizeof(struct ocfs2_xattr_block) \
89 - sizeof(struct ocfs2_xattr_header) \
90 - sizeof(__u32))
87 91
88static struct ocfs2_xattr_def_value_root def_xv = { 92static struct ocfs2_xattr_def_value_root def_xv = {
89 .xv.xr_list.l_count = cpu_to_le16(1), 93 .xv.xr_list.l_count = cpu_to_le16(1),
@@ -402,6 +406,81 @@ int ocfs2_calc_security_init(struct inode *dir,
402 return ret; 406 return ret;
403} 407}
404 408
409int ocfs2_calc_xattr_init(struct inode *dir,
410 struct buffer_head *dir_bh,
411 int mode,
412 struct ocfs2_security_xattr_info *si,
413 int *want_clusters,
414 int *xattr_credits,
415 struct ocfs2_alloc_context **xattr_ac)
416{
417 int ret = 0;
418 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
419 int s_size = 0;
420 int a_size = 0;
421 int acl_len = 0;
422
423 if (si->enable)
424 s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
425 si->value_len);
426
427 if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
428 acl_len = ocfs2_xattr_get_nolock(dir, dir_bh,
429 OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT,
430 "", NULL, 0);
431 if (acl_len > 0) {
432 a_size = ocfs2_xattr_entry_real_size(0, acl_len);
433 if (S_ISDIR(mode))
434 a_size <<= 1;
435 } else if (acl_len != 0 && acl_len != -ENODATA) {
436 mlog_errno(ret);
437 return ret;
438 }
439 }
440
441 if (!(s_size + a_size))
442 return ret;
443
444 /*
445 * The max space of security xattr taken inline is
446 * 256(name) + 80(value) + 16(entry) = 352 bytes,
447 * The max space of acl xattr taken inline is
448 * 80(value) + 16(entry) * 2(if directory) = 192 bytes,
449 * when blocksize = 512, may reserve one more cluser for
450 * xattr bucket, otherwise reserve one metadata block
451 * for them is ok.
452 */
453 if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
454 (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) {
455 ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
456 if (ret) {
457 mlog_errno(ret);
458 return ret;
459 }
460 *xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
461 }
462
463 if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE &&
464 (s_size + a_size) > OCFS2_XATTR_FREE_IN_BLOCK(dir)) {
465 *want_clusters += 1;
466 *xattr_credits += ocfs2_blocks_per_xattr_bucket(dir->i_sb);
467 }
468
469 /* reserve clusters for xattr value which will be set in B tree*/
470 if (si->enable && si->value_len > OCFS2_XATTR_INLINE_SIZE)
471 *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb,
472 si->value_len);
473 if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL &&
474 acl_len > OCFS2_XATTR_INLINE_SIZE) {
475 *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb, acl_len);
476 if (S_ISDIR(mode))
477 *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb,
478 acl_len);
479 }
480
481 return ret;
482}
483
405static int ocfs2_xattr_extend_allocation(struct inode *inode, 484static int ocfs2_xattr_extend_allocation(struct inode *inode,
406 u32 clusters_to_add, 485 u32 clusters_to_add,
407 struct buffer_head *xattr_bh, 486 struct buffer_head *xattr_bh,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index 6163df336d8c..9a67e7d8f812 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -66,5 +66,8 @@ int ocfs2_init_security_set(handle_t *, struct inode *,
66int ocfs2_calc_security_init(struct inode *, 66int ocfs2_calc_security_init(struct inode *,
67 struct ocfs2_security_xattr_info *, 67 struct ocfs2_security_xattr_info *,
68 int *, int *, struct ocfs2_alloc_context **); 68 int *, int *, struct ocfs2_alloc_context **);
69int ocfs2_calc_xattr_init(struct inode *, struct buffer_head *,
70 int, struct ocfs2_security_xattr_info *,
71 int *, int *, struct ocfs2_alloc_context **);
69 72
70#endif /* OCFS2_XATTR_H */ 73#endif /* OCFS2_XATTR_H */