diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/reiserfs/inode.c | 3 | ||||
-rw-r--r-- | fs/reiserfs/namei.c | 14 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 39 | ||||
-rw-r--r-- | fs/reiserfs/xattr_acl.c | 105 |
4 files changed, 115 insertions, 46 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 50a73e7afdc8..995f6975cae1 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -1914,9 +1914,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1914 | goto out_inserted_sd; | 1914 | goto out_inserted_sd; |
1915 | } | 1915 | } |
1916 | 1916 | ||
1917 | /* XXX CHECK THIS */ | ||
1918 | if (reiserfs_posixacl(inode->i_sb)) { | 1917 | if (reiserfs_posixacl(inode->i_sb)) { |
1919 | retval = reiserfs_inherit_default_acl(dir, dentry, inode); | 1918 | retval = reiserfs_inherit_default_acl(th, dir, dentry, inode); |
1920 | if (retval) { | 1919 | if (retval) { |
1921 | err = retval; | 1920 | err = retval; |
1922 | reiserfs_check_path(&path_to_key); | 1921 | reiserfs_check_path(&path_to_key); |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index ddf1bcd41c87..d9c1c8bd2950 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -598,15 +598,13 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
598 | 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + | 598 | 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + |
599 | REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); | 599 | REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); |
600 | struct reiserfs_transaction_handle th; | 600 | struct reiserfs_transaction_handle th; |
601 | int locked; | ||
602 | 601 | ||
603 | if (!(inode = new_inode(dir->i_sb))) { | 602 | if (!(inode = new_inode(dir->i_sb))) { |
604 | return -ENOMEM; | 603 | return -ENOMEM; |
605 | } | 604 | } |
606 | new_inode_init(inode, dir, mode); | 605 | new_inode_init(inode, dir, mode); |
607 | 606 | ||
608 | locked = reiserfs_cache_default_acl(dir); | 607 | jbegin_count += reiserfs_cache_default_acl(dir); |
609 | |||
610 | reiserfs_write_lock(dir->i_sb); | 608 | reiserfs_write_lock(dir->i_sb); |
611 | 609 | ||
612 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 610 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
@@ -662,7 +660,6 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
662 | JOURNAL_PER_BALANCE_CNT * 3 + | 660 | JOURNAL_PER_BALANCE_CNT * 3 + |
663 | 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + | 661 | 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + |
664 | REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); | 662 | REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); |
665 | int locked; | ||
666 | 663 | ||
667 | if (!new_valid_dev(rdev)) | 664 | if (!new_valid_dev(rdev)) |
668 | return -EINVAL; | 665 | return -EINVAL; |
@@ -672,8 +669,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
672 | } | 669 | } |
673 | new_inode_init(inode, dir, mode); | 670 | new_inode_init(inode, dir, mode); |
674 | 671 | ||
675 | locked = reiserfs_cache_default_acl(dir); | 672 | jbegin_count += reiserfs_cache_default_acl(dir); |
676 | |||
677 | reiserfs_write_lock(dir->i_sb); | 673 | reiserfs_write_lock(dir->i_sb); |
678 | 674 | ||
679 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 675 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
@@ -732,7 +728,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
732 | JOURNAL_PER_BALANCE_CNT * 3 + | 728 | JOURNAL_PER_BALANCE_CNT * 3 + |
733 | 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + | 729 | 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + |
734 | REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); | 730 | REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); |
735 | int locked; | ||
736 | 731 | ||
737 | #ifdef DISPLACE_NEW_PACKING_LOCALITIES | 732 | #ifdef DISPLACE_NEW_PACKING_LOCALITIES |
738 | /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ | 733 | /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ |
@@ -744,8 +739,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
744 | } | 739 | } |
745 | new_inode_init(inode, dir, mode); | 740 | new_inode_init(inode, dir, mode); |
746 | 741 | ||
747 | locked = reiserfs_cache_default_acl(dir); | 742 | jbegin_count += reiserfs_cache_default_acl(dir); |
748 | |||
749 | reiserfs_write_lock(dir->i_sb); | 743 | reiserfs_write_lock(dir->i_sb); |
750 | 744 | ||
751 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 745 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
@@ -1034,8 +1028,6 @@ static int reiserfs_symlink(struct inode *parent_dir, | |||
1034 | memcpy(name, symname, strlen(symname)); | 1028 | memcpy(name, symname, strlen(symname)); |
1035 | padd_item(name, item_len, strlen(symname)); | 1029 | padd_item(name, item_len, strlen(symname)); |
1036 | 1030 | ||
1037 | /* We would inherit the default ACL here, but symlinks don't get ACLs */ | ||
1038 | |||
1039 | retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); | 1031 | retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); |
1040 | if (retval) { | 1032 | if (retval) { |
1041 | drop_new_inode(inode); | 1033 | drop_new_inode(inode); |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index d3ce27436605..c2e3a92aaf2b 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -632,8 +632,9 @@ out_dput: | |||
632 | * inode->i_mutex: down | 632 | * inode->i_mutex: down |
633 | */ | 633 | */ |
634 | int | 634 | int |
635 | __reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | 635 | reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, |
636 | size_t buffer_size, int flags) | 636 | struct inode *inode, const char *name, |
637 | const void *buffer, size_t buffer_size, int flags) | ||
637 | { | 638 | { |
638 | int err = 0; | 639 | int err = 0; |
639 | struct dentry *dentry; | 640 | struct dentry *dentry; |
@@ -723,14 +724,34 @@ out_unlock: | |||
723 | return err; | 724 | return err; |
724 | } | 725 | } |
725 | 726 | ||
726 | int | 727 | /* We need to start a transaction to maintain lock ordering */ |
727 | reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | 728 | int reiserfs_xattr_set(struct inode *inode, const char *name, |
728 | size_t buffer_size, int flags) | 729 | const void *buffer, size_t buffer_size, int flags) |
729 | { | 730 | { |
730 | int err = __reiserfs_xattr_set(inode, name, buffer, buffer_size, flags); | 731 | |
731 | if (err == -ENODATA) | 732 | struct reiserfs_transaction_handle th; |
732 | err = 0; | 733 | int error, error2; |
733 | return err; | 734 | size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size); |
735 | |||
736 | if (!(flags & XATTR_REPLACE)) | ||
737 | jbegin_count += reiserfs_xattr_jcreate_nblocks(inode); | ||
738 | |||
739 | reiserfs_write_lock(inode->i_sb); | ||
740 | error = journal_begin(&th, inode->i_sb, jbegin_count); | ||
741 | if (error) { | ||
742 | reiserfs_write_unlock(inode->i_sb); | ||
743 | return error; | ||
744 | } | ||
745 | |||
746 | error = reiserfs_xattr_set_handle(&th, inode, name, | ||
747 | buffer, buffer_size, flags); | ||
748 | |||
749 | error2 = journal_end(&th, inode->i_sb, jbegin_count); | ||
750 | if (error == 0) | ||
751 | error = error2; | ||
752 | reiserfs_write_unlock(inode->i_sb); | ||
753 | |||
754 | return error; | ||
734 | } | 755 | } |
735 | 756 | ||
736 | /* | 757 | /* |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index bfecf7553002..d423416d93d1 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -10,15 +10,17 @@ | |||
10 | #include <linux/reiserfs_acl.h> | 10 | #include <linux/reiserfs_acl.h> |
11 | #include <asm/uaccess.h> | 11 | #include <asm/uaccess.h> |
12 | 12 | ||
13 | static int reiserfs_set_acl(struct inode *inode, int type, | 13 | static int reiserfs_set_acl(struct reiserfs_transaction_handle *th, |
14 | struct inode *inode, int type, | ||
14 | struct posix_acl *acl); | 15 | struct posix_acl *acl); |
15 | 16 | ||
16 | static int | 17 | static int |
17 | xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) | 18 | xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) |
18 | { | 19 | { |
19 | struct posix_acl *acl; | 20 | struct posix_acl *acl; |
20 | int error; | 21 | int error, error2; |
21 | 22 | struct reiserfs_transaction_handle th; | |
23 | size_t jcreate_blocks; | ||
22 | if (!reiserfs_posixacl(inode->i_sb)) | 24 | if (!reiserfs_posixacl(inode->i_sb)) |
23 | return -EOPNOTSUPP; | 25 | return -EOPNOTSUPP; |
24 | if (!is_owner_or_cap(inode)) | 26 | if (!is_owner_or_cap(inode)) |
@@ -36,7 +38,21 @@ xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) | |||
36 | } else | 38 | } else |
37 | acl = NULL; | 39 | acl = NULL; |
38 | 40 | ||
39 | error = reiserfs_set_acl(inode, type, acl); | 41 | /* Pessimism: We can't assume that anything from the xattr root up |
42 | * has been created. */ | ||
43 | |||
44 | jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) + | ||
45 | reiserfs_xattr_nblocks(inode, size) * 2; | ||
46 | |||
47 | reiserfs_write_lock(inode->i_sb); | ||
48 | error = journal_begin(&th, inode->i_sb, jcreate_blocks); | ||
49 | if (error == 0) { | ||
50 | error = reiserfs_set_acl(&th, inode, type, acl); | ||
51 | error2 = journal_end(&th, inode->i_sb, jcreate_blocks); | ||
52 | if (error2) | ||
53 | error = error2; | ||
54 | } | ||
55 | reiserfs_write_unlock(inode->i_sb); | ||
40 | 56 | ||
41 | release_and_out: | 57 | release_and_out: |
42 | posix_acl_release(acl); | 58 | posix_acl_release(acl); |
@@ -266,7 +282,8 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) | |||
266 | * BKL held [before 2.5.x] | 282 | * BKL held [before 2.5.x] |
267 | */ | 283 | */ |
268 | static int | 284 | static int |
269 | reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | 285 | reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, |
286 | int type, struct posix_acl *acl) | ||
270 | { | 287 | { |
271 | char *name; | 288 | char *name; |
272 | void *value = NULL; | 289 | void *value = NULL; |
@@ -310,7 +327,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
310 | return (int)PTR_ERR(value); | 327 | return (int)PTR_ERR(value); |
311 | } | 328 | } |
312 | 329 | ||
313 | error = __reiserfs_xattr_set(inode, name, value, size, 0); | 330 | error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0); |
314 | 331 | ||
315 | /* | 332 | /* |
316 | * Ensure that the inode gets dirtied if we're only using | 333 | * Ensure that the inode gets dirtied if we're only using |
@@ -337,7 +354,8 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
337 | /* dir->i_mutex: locked, | 354 | /* dir->i_mutex: locked, |
338 | * inode is new and not released into the wild yet */ | 355 | * inode is new and not released into the wild yet */ |
339 | int | 356 | int |
340 | reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, | 357 | reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, |
358 | struct inode *dir, struct dentry *dentry, | ||
341 | struct inode *inode) | 359 | struct inode *inode) |
342 | { | 360 | { |
343 | struct posix_acl *acl; | 361 | struct posix_acl *acl; |
@@ -374,7 +392,8 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, | |||
374 | 392 | ||
375 | /* Copy the default ACL to the default ACL of a new directory */ | 393 | /* Copy the default ACL to the default ACL of a new directory */ |
376 | if (S_ISDIR(inode->i_mode)) { | 394 | if (S_ISDIR(inode->i_mode)) { |
377 | err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); | 395 | err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT, |
396 | acl); | ||
378 | if (err) | 397 | if (err) |
379 | goto cleanup; | 398 | goto cleanup; |
380 | } | 399 | } |
@@ -395,9 +414,9 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, | |||
395 | 414 | ||
396 | /* If we need an ACL.. */ | 415 | /* If we need an ACL.. */ |
397 | if (need_acl > 0) { | 416 | if (need_acl > 0) { |
398 | err = | 417 | err = reiserfs_set_acl(th, inode, |
399 | reiserfs_set_acl(inode, ACL_TYPE_ACCESS, | 418 | ACL_TYPE_ACCESS, |
400 | acl_copy); | 419 | acl_copy); |
401 | if (err) | 420 | if (err) |
402 | goto cleanup_copy; | 421 | goto cleanup_copy; |
403 | } | 422 | } |
@@ -415,21 +434,45 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, | |||
415 | return err; | 434 | return err; |
416 | } | 435 | } |
417 | 436 | ||
418 | /* Looks up and caches the result of the default ACL. | 437 | /* This is used to cache the default acl before a new object is created. |
419 | * We do this so that we don't need to carry the xattr_sem into | 438 | * The biggest reason for this is to get an idea of how many blocks will |
420 | * reiserfs_new_inode if we don't need to */ | 439 | * actually be required for the create operation if we must inherit an ACL. |
440 | * An ACL write can add up to 3 object creations and an additional file write | ||
441 | * so we'd prefer not to reserve that many blocks in the journal if we can. | ||
442 | * It also has the advantage of not loading the ACL with a transaction open, | ||
443 | * this may seem silly, but if the owner of the directory is doing the | ||
444 | * creation, the ACL may not be loaded since the permissions wouldn't require | ||
445 | * it. | ||
446 | * We return the number of blocks required for the transaction. | ||
447 | */ | ||
421 | int reiserfs_cache_default_acl(struct inode *inode) | 448 | int reiserfs_cache_default_acl(struct inode *inode) |
422 | { | 449 | { |
423 | int ret = 0; | 450 | struct posix_acl *acl; |
424 | if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) { | 451 | int nblocks = 0; |
425 | struct posix_acl *acl; | 452 | |
426 | acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); | 453 | if (IS_PRIVATE(inode)) |
427 | ret = (acl && !IS_ERR(acl)); | 454 | return 0; |
428 | if (ret) | 455 | |
429 | posix_acl_release(acl); | 456 | acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); |
457 | |||
458 | if (acl && !IS_ERR(acl)) { | ||
459 | int size = reiserfs_acl_size(acl->a_count); | ||
460 | |||
461 | /* Other xattrs can be created during inode creation. We don't | ||
462 | * want to claim too many blocks, so we check to see if we | ||
463 | * we need to create the tree to the xattrs, and then we | ||
464 | * just want two files. */ | ||
465 | nblocks = reiserfs_xattr_jcreate_nblocks(inode); | ||
466 | nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); | ||
467 | |||
468 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | ||
469 | |||
470 | /* We need to account for writes + bitmaps for two files */ | ||
471 | nblocks += reiserfs_xattr_nblocks(inode, size) * 4; | ||
472 | posix_acl_release(acl); | ||
430 | } | 473 | } |
431 | 474 | ||
432 | return ret; | 475 | return nblocks; |
433 | } | 476 | } |
434 | 477 | ||
435 | int reiserfs_acl_chmod(struct inode *inode) | 478 | int reiserfs_acl_chmod(struct inode *inode) |
@@ -455,8 +498,22 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
455 | if (!clone) | 498 | if (!clone) |
456 | return -ENOMEM; | 499 | return -ENOMEM; |
457 | error = posix_acl_chmod_masq(clone, inode->i_mode); | 500 | error = posix_acl_chmod_masq(clone, inode->i_mode); |
458 | if (!error) | 501 | if (!error) { |
459 | error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | 502 | struct reiserfs_transaction_handle th; |
503 | size_t size = reiserfs_xattr_nblocks(inode, | ||
504 | reiserfs_acl_size(clone->a_count)); | ||
505 | reiserfs_write_lock(inode->i_sb); | ||
506 | error = journal_begin(&th, inode->i_sb, size * 2); | ||
507 | if (!error) { | ||
508 | int error2; | ||
509 | error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, | ||
510 | clone); | ||
511 | error2 = journal_end(&th, inode->i_sb, size * 2); | ||
512 | if (error2) | ||
513 | error = error2; | ||
514 | } | ||
515 | reiserfs_write_unlock(inode->i_sb); | ||
516 | } | ||
460 | posix_acl_release(clone); | 517 | posix_acl_release(clone); |
461 | return error; | 518 | return error; |
462 | } | 519 | } |