diff options
author | Tiger Yang <tiger.yang@oracle.com> | 2008-11-13 22:17:41 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:20 -0500 |
commit | 89c38bd0ade3c567707ed8fce088b253b0369c50 (patch) | |
tree | ffc5bf6a8871efa8e7793c552d16ac9fb92f1334 /fs/ocfs2 | |
parent | 060bc66dd5017460076d9e808e2198cd532c943d (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.c | 59 | ||||
-rw-r--r-- | fs/ocfs2/acl.h | 14 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 23 | ||||
-rw-r--r-- | fs/ocfs2/xattr.c | 79 | ||||
-rw-r--r-- | fs/ocfs2/xattr.h | 3 |
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 | */ | ||
279 | int 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 | } | ||
329 | cleanup: | ||
330 | posix_acl_release(acl); | ||
331 | return ret; | ||
332 | } | ||
333 | |||
275 | static size_t ocfs2_xattr_list_acl_access(struct inode *inode, | 334 | static 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 | ||
31 | extern int ocfs2_check_acl(struct inode *, int); | 31 | extern int ocfs2_check_acl(struct inode *, int); |
32 | extern int ocfs2_acl_chmod(struct inode *); | 32 | extern int ocfs2_acl_chmod(struct inode *); |
33 | extern 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 | } |
45 | static 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 | ||
88 | static struct ocfs2_xattr_def_value_root def_xv = { | 92 | static 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 | ||
409 | int 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 | |||
405 | static int ocfs2_xattr_extend_allocation(struct inode *inode, | 484 | static 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 *, | |||
66 | int ocfs2_calc_security_init(struct inode *, | 66 | int 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 **); |
69 | int 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 */ |