diff options
author | Jeff Mahoney <jeffm@suse.com> | 2009-03-30 14:02:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-30 15:16:38 -0400 |
commit | d984561b326cd0fe0d1183d11b9b4fa1d011d21d (patch) | |
tree | e0487588581bccaa2b875529ed84ec5a4a254ab9 /fs/reiserfs | |
parent | 6c17675e1e02ebde220ef639a3fb1333928ec2f4 (diff) |
reiserfs: eliminate per-super xattr lock
With the switch to using inode->i_mutex locking during lookups/creation
in the xattr root, the per-super xattr lock is no longer needed.
This patch removes it.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/inode.c | 14 | ||||
-rw-r--r-- | fs/reiserfs/namei.c | 29 | ||||
-rw-r--r-- | fs/reiserfs/super.c | 4 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 70 | ||||
-rw-r--r-- | fs/reiserfs/xattr_acl.c | 74 |
5 files changed, 69 insertions, 122 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index cd42a8658086..50a73e7afdc8 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -1957,19 +1957,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1957 | inode->i_nlink = 0; | 1957 | inode->i_nlink = 0; |
1958 | th->t_trans_id = 0; /* so the caller can't use this handle later */ | 1958 | th->t_trans_id = 0; /* so the caller can't use this handle later */ |
1959 | unlock_new_inode(inode); /* OK to do even if we hadn't locked it */ | 1959 | unlock_new_inode(inode); /* OK to do even if we hadn't locked it */ |
1960 | 1960 | iput(inode); | |
1961 | /* If we were inheriting an ACL, we need to release the lock so that | ||
1962 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking | ||
1963 | * code really needs to be reworked, but this will take care of it | ||
1964 | * for now. -jeffm */ | ||
1965 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1966 | if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) { | ||
1967 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
1968 | iput(inode); | ||
1969 | reiserfs_write_lock_xattrs(dir->i_sb); | ||
1970 | } else | ||
1971 | #endif | ||
1972 | iput(inode); | ||
1973 | return err; | 1961 | return err; |
1974 | } | 1962 | } |
1975 | 1963 | ||
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index c8430f1c824f..ddf1bcd41c87 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -609,9 +609,6 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
609 | 609 | ||
610 | reiserfs_write_lock(dir->i_sb); | 610 | reiserfs_write_lock(dir->i_sb); |
611 | 611 | ||
612 | if (locked) | ||
613 | reiserfs_write_lock_xattrs(dir->i_sb); | ||
614 | |||
615 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 612 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
616 | if (retval) { | 613 | if (retval) { |
617 | drop_new_inode(inode); | 614 | drop_new_inode(inode); |
@@ -624,11 +621,6 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
624 | if (retval) | 621 | if (retval) |
625 | goto out_failed; | 622 | goto out_failed; |
626 | 623 | ||
627 | if (locked) { | ||
628 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
629 | locked = 0; | ||
630 | } | ||
631 | |||
632 | inode->i_op = &reiserfs_file_inode_operations; | 624 | inode->i_op = &reiserfs_file_inode_operations; |
633 | inode->i_fop = &reiserfs_file_operations; | 625 | inode->i_fop = &reiserfs_file_operations; |
634 | inode->i_mapping->a_ops = &reiserfs_address_space_operations; | 626 | inode->i_mapping->a_ops = &reiserfs_address_space_operations; |
@@ -655,8 +647,6 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
655 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 647 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
656 | 648 | ||
657 | out_failed: | 649 | out_failed: |
658 | if (locked) | ||
659 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
660 | reiserfs_write_unlock(dir->i_sb); | 650 | reiserfs_write_unlock(dir->i_sb); |
661 | return retval; | 651 | return retval; |
662 | } | 652 | } |
@@ -686,9 +676,6 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
686 | 676 | ||
687 | reiserfs_write_lock(dir->i_sb); | 677 | reiserfs_write_lock(dir->i_sb); |
688 | 678 | ||
689 | if (locked) | ||
690 | reiserfs_write_lock_xattrs(dir->i_sb); | ||
691 | |||
692 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 679 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
693 | if (retval) { | 680 | if (retval) { |
694 | drop_new_inode(inode); | 681 | drop_new_inode(inode); |
@@ -702,11 +689,6 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
702 | goto out_failed; | 689 | goto out_failed; |
703 | } | 690 | } |
704 | 691 | ||
705 | if (locked) { | ||
706 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
707 | locked = 0; | ||
708 | } | ||
709 | |||
710 | inode->i_op = &reiserfs_special_inode_operations; | 692 | inode->i_op = &reiserfs_special_inode_operations; |
711 | init_special_inode(inode, inode->i_mode, rdev); | 693 | init_special_inode(inode, inode->i_mode, rdev); |
712 | 694 | ||
@@ -736,8 +718,6 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
736 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 718 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
737 | 719 | ||
738 | out_failed: | 720 | out_failed: |
739 | if (locked) | ||
740 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
741 | reiserfs_write_unlock(dir->i_sb); | 721 | reiserfs_write_unlock(dir->i_sb); |
742 | return retval; | 722 | return retval; |
743 | } | 723 | } |
@@ -767,8 +747,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
767 | locked = reiserfs_cache_default_acl(dir); | 747 | locked = reiserfs_cache_default_acl(dir); |
768 | 748 | ||
769 | reiserfs_write_lock(dir->i_sb); | 749 | reiserfs_write_lock(dir->i_sb); |
770 | if (locked) | ||
771 | reiserfs_write_lock_xattrs(dir->i_sb); | ||
772 | 750 | ||
773 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 751 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
774 | if (retval) { | 752 | if (retval) { |
@@ -790,11 +768,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
790 | goto out_failed; | 768 | goto out_failed; |
791 | } | 769 | } |
792 | 770 | ||
793 | if (locked) { | ||
794 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
795 | locked = 0; | ||
796 | } | ||
797 | |||
798 | reiserfs_update_inode_transaction(inode); | 771 | reiserfs_update_inode_transaction(inode); |
799 | reiserfs_update_inode_transaction(dir); | 772 | reiserfs_update_inode_transaction(dir); |
800 | 773 | ||
@@ -824,8 +797,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
824 | unlock_new_inode(inode); | 797 | unlock_new_inode(inode); |
825 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 798 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
826 | out_failed: | 799 | out_failed: |
827 | if (locked) | ||
828 | reiserfs_write_unlock_xattrs(dir->i_sb); | ||
829 | reiserfs_write_unlock(dir->i_sb); | 800 | reiserfs_write_unlock(dir->i_sb); |
830 | return retval; | 801 | return retval; |
831 | } | 802 | } |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index fc7cb4661ee0..6d10f81b4fc1 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1646,10 +1646,6 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1646 | REISERFS_SB(s)->s_alloc_options.preallocmin = 0; | 1646 | REISERFS_SB(s)->s_alloc_options.preallocmin = 0; |
1647 | /* Preallocate by 16 blocks (17-1) at once */ | 1647 | /* Preallocate by 16 blocks (17-1) at once */ |
1648 | REISERFS_SB(s)->s_alloc_options.preallocsize = 17; | 1648 | REISERFS_SB(s)->s_alloc_options.preallocsize = 17; |
1649 | #ifdef CONFIG_REISERFS_FS_XATTR | ||
1650 | /* Initialize the rwsem for xattr dir */ | ||
1651 | init_rwsem(&REISERFS_SB(s)->xattr_dir_sem); | ||
1652 | #endif | ||
1653 | /* setup default block allocator options */ | 1649 | /* setup default block allocator options */ |
1654 | reiserfs_init_alloc_options(s); | 1650 | reiserfs_init_alloc_options(s); |
1655 | 1651 | ||
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 57920a4df7a4..62c98829c545 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -27,6 +27,12 @@ | |||
27 | * these are special cases for filesystem ACLs, they are interpreted by the | 27 | * these are special cases for filesystem ACLs, they are interpreted by the |
28 | * kernel, in addition, they are negatively and positively cached and attached | 28 | * kernel, in addition, they are negatively and positively cached and attached |
29 | * to the inode so that unnecessary lookups are avoided. | 29 | * to the inode so that unnecessary lookups are avoided. |
30 | * | ||
31 | * Locking works like so: | ||
32 | * The xattr root (/.reiserfs_priv/xattrs) is protected by its i_mutex. | ||
33 | * The xattr dir (/.reiserfs_priv/xattrs/<oid>.<gen>) is protected by | ||
34 | * inode->xattr_sem. | ||
35 | * The xattrs themselves are likewise protected by the xattr_sem. | ||
30 | */ | 36 | */ |
31 | 37 | ||
32 | #include <linux/reiserfs_fs.h> | 38 | #include <linux/reiserfs_fs.h> |
@@ -392,16 +398,17 @@ reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, | |||
392 | /* This is called w/ inode->i_mutex downed */ | 398 | /* This is called w/ inode->i_mutex downed */ |
393 | int reiserfs_delete_xattrs(struct inode *inode) | 399 | int reiserfs_delete_xattrs(struct inode *inode) |
394 | { | 400 | { |
395 | struct dentry *dir, *root; | ||
396 | int err = 0; | 401 | int err = 0; |
402 | struct dentry *dir, *root; | ||
403 | struct reiserfs_transaction_handle th; | ||
404 | int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + | ||
405 | 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); | ||
397 | 406 | ||
398 | /* Skip out, an xattr has no xattrs associated with it */ | 407 | /* Skip out, an xattr has no xattrs associated with it */ |
399 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) | 408 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) |
400 | return 0; | 409 | return 0; |
401 | 410 | ||
402 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
403 | dir = open_xa_dir(inode, XATTR_REPLACE); | 411 | dir = open_xa_dir(inode, XATTR_REPLACE); |
404 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
405 | if (IS_ERR(dir)) { | 412 | if (IS_ERR(dir)) { |
406 | err = PTR_ERR(dir); | 413 | err = PTR_ERR(dir); |
407 | goto out; | 414 | goto out; |
@@ -416,18 +423,26 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
416 | if (err) | 423 | if (err) |
417 | goto out_dir; | 424 | goto out_dir; |
418 | 425 | ||
419 | /* Leftovers besides . and .. -- that's not good. */ | 426 | /* We start a transaction here to avoid a ABBA situation |
420 | if (dir->d_inode->i_nlink <= 2) { | 427 | * between the xattr root's i_mutex and the journal lock. |
421 | root = open_xa_root(inode->i_sb, XATTR_REPLACE); | 428 | * Inode creation will inherit an ACL, which requires a |
422 | reiserfs_write_lock_xattrs(inode->i_sb); | 429 | * lookup. The lookup locks the xattr root i_mutex with a |
430 | * transaction open. Inode deletion takes teh xattr root | ||
431 | * i_mutex to delete the directory and then starts a | ||
432 | * transaction inside it. Boom. This doesn't incur much | ||
433 | * additional overhead since the reiserfs_rmdir transaction | ||
434 | * will just nest inside the outer transaction. */ | ||
435 | err = journal_begin(&th, inode->i_sb, blocks); | ||
436 | if (!err) { | ||
437 | int jerror; | ||
438 | root = dget(dir->d_parent); | ||
423 | mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_XATTR); | 439 | mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_XATTR); |
424 | err = xattr_rmdir(root->d_inode, dir); | 440 | err = xattr_rmdir(root->d_inode, dir); |
441 | jerror = journal_end(&th, inode->i_sb, blocks); | ||
425 | mutex_unlock(&root->d_inode->i_mutex); | 442 | mutex_unlock(&root->d_inode->i_mutex); |
426 | reiserfs_write_unlock_xattrs(inode->i_sb); | ||
427 | dput(root); | 443 | dput(root); |
428 | } else { | 444 | |
429 | reiserfs_warning(inode->i_sb, "jdm-20006", | 445 | err = jerror ?: err; |
430 | "Couldn't remove all entries in directory"); | ||
431 | } | 446 | } |
432 | 447 | ||
433 | out_dir: | 448 | out_dir: |
@@ -437,6 +452,9 @@ out: | |||
437 | if (!err) | 452 | if (!err) |
438 | REISERFS_I(inode)->i_flags = | 453 | REISERFS_I(inode)->i_flags = |
439 | REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | 454 | REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; |
455 | else | ||
456 | reiserfs_warning(inode->i_sb, "jdm-20004", | ||
457 | "Couldn't remove all xattrs (%d)\n", err); | ||
440 | return err; | 458 | return err; |
441 | } | 459 | } |
442 | 460 | ||
@@ -485,9 +503,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | |||
485 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) | 503 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) |
486 | return 0; | 504 | return 0; |
487 | 505 | ||
488 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
489 | dir = open_xa_dir(inode, XATTR_REPLACE); | 506 | dir = open_xa_dir(inode, XATTR_REPLACE); |
490 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
491 | if (IS_ERR(dir)) { | 507 | if (IS_ERR(dir)) { |
492 | if (PTR_ERR(dir) != -ENODATA) | 508 | if (PTR_ERR(dir) != -ENODATA) |
493 | err = PTR_ERR(dir); | 509 | err = PTR_ERR(dir); |
@@ -731,6 +747,11 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
731 | goto out; | 747 | goto out; |
732 | } | 748 | } |
733 | 749 | ||
750 | /* protect against concurrent access. xattrs are backed by | ||
751 | * regular files, but they're not regular files. The updates | ||
752 | * must be atomic from the perspective of the user. */ | ||
753 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); | ||
754 | |||
734 | isize = i_size_read(dentry->d_inode); | 755 | isize = i_size_read(dentry->d_inode); |
735 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 756 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; |
736 | 757 | ||
@@ -798,6 +819,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
798 | } | 819 | } |
799 | 820 | ||
800 | out_dput: | 821 | out_dput: |
822 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
801 | dput(dentry); | 823 | dput(dentry); |
802 | 824 | ||
803 | out: | 825 | out: |
@@ -834,7 +856,6 @@ int reiserfs_xattr_del(struct inode *inode, const char *name) | |||
834 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *); | 856 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *); |
835 | /* | 857 | /* |
836 | * Inode operation getxattr() | 858 | * Inode operation getxattr() |
837 | * Preliminary locking: we down dentry->d_inode->i_mutex | ||
838 | */ | 859 | */ |
839 | ssize_t | 860 | ssize_t |
840 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, | 861 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, |
@@ -848,9 +869,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, | |||
848 | return -EOPNOTSUPP; | 869 | return -EOPNOTSUPP; |
849 | 870 | ||
850 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 871 | reiserfs_read_lock_xattr_i(dentry->d_inode); |
851 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
852 | err = xah->get(dentry->d_inode, name, buffer, size); | 872 | err = xah->get(dentry->d_inode, name, buffer, size); |
853 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
854 | reiserfs_read_unlock_xattr_i(dentry->d_inode); | 873 | reiserfs_read_unlock_xattr_i(dentry->d_inode); |
855 | return err; | 874 | return err; |
856 | } | 875 | } |
@@ -866,23 +885,13 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
866 | { | 885 | { |
867 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 886 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); |
868 | int err; | 887 | int err; |
869 | int lock; | ||
870 | 888 | ||
871 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 889 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || |
872 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 890 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) |
873 | return -EOPNOTSUPP; | 891 | return -EOPNOTSUPP; |
874 | 892 | ||
875 | reiserfs_write_lock_xattr_i(dentry->d_inode); | 893 | reiserfs_write_lock_xattr_i(dentry->d_inode); |
876 | lock = !has_xattr_dir(dentry->d_inode); | ||
877 | if (lock) | ||
878 | reiserfs_write_lock_xattrs(dentry->d_sb); | ||
879 | else | ||
880 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
881 | err = xah->set(dentry->d_inode, name, value, size, flags); | 894 | err = xah->set(dentry->d_inode, name, value, size, flags); |
882 | if (lock) | ||
883 | reiserfs_write_unlock_xattrs(dentry->d_sb); | ||
884 | else | ||
885 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
886 | reiserfs_write_unlock_xattr_i(dentry->d_inode); | 895 | reiserfs_write_unlock_xattr_i(dentry->d_inode); |
887 | return err; | 896 | return err; |
888 | } | 897 | } |
@@ -902,8 +911,6 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name) | |||
902 | return -EOPNOTSUPP; | 911 | return -EOPNOTSUPP; |
903 | 912 | ||
904 | reiserfs_write_lock_xattr_i(dentry->d_inode); | 913 | reiserfs_write_lock_xattr_i(dentry->d_inode); |
905 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
906 | |||
907 | /* Deletion pre-operation */ | 914 | /* Deletion pre-operation */ |
908 | if (xah->del) { | 915 | if (xah->del) { |
909 | err = xah->del(dentry->d_inode, name); | 916 | err = xah->del(dentry->d_inode, name); |
@@ -917,7 +924,6 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name) | |||
917 | mark_inode_dirty(dentry->d_inode); | 924 | mark_inode_dirty(dentry->d_inode); |
918 | 925 | ||
919 | out: | 926 | out: |
920 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
921 | reiserfs_write_unlock_xattr_i(dentry->d_inode); | 927 | reiserfs_write_unlock_xattr_i(dentry->d_inode); |
922 | return err; | 928 | return err; |
923 | } | 929 | } |
@@ -966,8 +972,6 @@ reiserfs_listxattr_filler(void *buf, const char *name, int namelen, | |||
966 | 972 | ||
967 | /* | 973 | /* |
968 | * Inode operation listxattr() | 974 | * Inode operation listxattr() |
969 | * | ||
970 | * Preliminary locking: we down dentry->d_inode->i_mutex | ||
971 | */ | 975 | */ |
972 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | 976 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) |
973 | { | 977 | { |
@@ -983,9 +987,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
983 | return -EOPNOTSUPP; | 987 | return -EOPNOTSUPP; |
984 | 988 | ||
985 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 989 | reiserfs_read_lock_xattr_i(dentry->d_inode); |
986 | reiserfs_read_lock_xattrs(dentry->d_sb); | ||
987 | dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); | 990 | dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); |
988 | reiserfs_read_unlock_xattrs(dentry->d_sb); | ||
989 | if (IS_ERR(dir)) { | 991 | if (IS_ERR(dir)) { |
990 | err = PTR_ERR(dir); | 992 | err = PTR_ERR(dir); |
991 | if (err == -ENODATA) | 993 | if (err == -ENODATA) |
@@ -1114,11 +1116,9 @@ static int reiserfs_check_acl(struct inode *inode, int mask) | |||
1114 | int error = -EAGAIN; /* do regular unix permission checks by default */ | 1116 | int error = -EAGAIN; /* do regular unix permission checks by default */ |
1115 | 1117 | ||
1116 | reiserfs_read_lock_xattr_i(inode); | 1118 | reiserfs_read_lock_xattr_i(inode); |
1117 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
1118 | 1119 | ||
1119 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | 1120 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); |
1120 | 1121 | ||
1121 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
1122 | reiserfs_read_unlock_xattr_i(inode); | 1122 | reiserfs_read_unlock_xattr_i(inode); |
1123 | 1123 | ||
1124 | if (acl) { | 1124 | if (acl) { |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 9128e4d5ba64..d63b2c5850c3 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -172,6 +172,29 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size) | |||
172 | return ERR_PTR(-EINVAL); | 172 | return ERR_PTR(-EINVAL); |
173 | } | 173 | } |
174 | 174 | ||
175 | static inline void iset_acl(struct inode *inode, struct posix_acl **i_acl, | ||
176 | struct posix_acl *acl) | ||
177 | { | ||
178 | spin_lock(&inode->i_lock); | ||
179 | if (*i_acl != ERR_PTR(-ENODATA)) | ||
180 | posix_acl_release(*i_acl); | ||
181 | *i_acl = posix_acl_dup(acl); | ||
182 | spin_unlock(&inode->i_lock); | ||
183 | } | ||
184 | |||
185 | static inline struct posix_acl *iget_acl(struct inode *inode, | ||
186 | struct posix_acl **i_acl) | ||
187 | { | ||
188 | struct posix_acl *acl = ERR_PTR(-ENODATA); | ||
189 | |||
190 | spin_lock(&inode->i_lock); | ||
191 | if (*i_acl != ERR_PTR(-ENODATA)) | ||
192 | acl = posix_acl_dup(*i_acl); | ||
193 | spin_unlock(&inode->i_lock); | ||
194 | |||
195 | return acl; | ||
196 | } | ||
197 | |||
175 | /* | 198 | /* |
176 | * Inode operation get_posix_acl(). | 199 | * Inode operation get_posix_acl(). |
177 | * | 200 | * |
@@ -199,11 +222,11 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) | |||
199 | return ERR_PTR(-EINVAL); | 222 | return ERR_PTR(-EINVAL); |
200 | } | 223 | } |
201 | 224 | ||
202 | if (IS_ERR(*p_acl)) { | 225 | acl = iget_acl(inode, p_acl); |
203 | if (PTR_ERR(*p_acl) == -ENODATA) | 226 | if (acl && !IS_ERR(acl)) |
204 | return NULL; | 227 | return acl; |
205 | } else if (*p_acl != NULL) | 228 | else if (PTR_ERR(acl) == -ENODATA) |
206 | return posix_acl_dup(*p_acl); | 229 | return NULL; |
207 | 230 | ||
208 | size = reiserfs_xattr_get(inode, name, NULL, 0); | 231 | size = reiserfs_xattr_get(inode, name, NULL, 0); |
209 | if (size < 0) { | 232 | if (size < 0) { |
@@ -229,7 +252,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) | |||
229 | } else { | 252 | } else { |
230 | acl = posix_acl_from_disk(value, retval); | 253 | acl = posix_acl_from_disk(value, retval); |
231 | if (!IS_ERR(acl)) | 254 | if (!IS_ERR(acl)) |
232 | *p_acl = posix_acl_dup(acl); | 255 | iset_acl(inode, p_acl, acl); |
233 | } | 256 | } |
234 | 257 | ||
235 | kfree(value); | 258 | kfree(value); |
@@ -300,16 +323,8 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
300 | 323 | ||
301 | kfree(value); | 324 | kfree(value); |
302 | 325 | ||
303 | if (!error) { | 326 | if (!error) |
304 | /* Release the old one */ | 327 | iset_acl(inode, p_acl, acl); |
305 | if (!IS_ERR(*p_acl) && *p_acl) | ||
306 | posix_acl_release(*p_acl); | ||
307 | |||
308 | if (acl == NULL) | ||
309 | *p_acl = ERR_PTR(-ENODATA); | ||
310 | else | ||
311 | *p_acl = posix_acl_dup(acl); | ||
312 | } | ||
313 | 328 | ||
314 | return error; | 329 | return error; |
315 | } | 330 | } |
@@ -404,9 +419,7 @@ int reiserfs_cache_default_acl(struct inode *inode) | |||
404 | if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) { | 419 | if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) { |
405 | struct posix_acl *acl; | 420 | struct posix_acl *acl; |
406 | reiserfs_read_lock_xattr_i(inode); | 421 | reiserfs_read_lock_xattr_i(inode); |
407 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
408 | acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); | 422 | acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); |
409 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
410 | reiserfs_read_unlock_xattr_i(inode); | 423 | reiserfs_read_unlock_xattr_i(inode); |
411 | ret = (acl && !IS_ERR(acl)); | 424 | ret = (acl && !IS_ERR(acl)); |
412 | if (ret) | 425 | if (ret) |
@@ -429,9 +442,7 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
429 | return 0; | 442 | return 0; |
430 | } | 443 | } |
431 | 444 | ||
432 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
433 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | 445 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); |
434 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
435 | if (!acl) | 446 | if (!acl) |
436 | return 0; | 447 | return 0; |
437 | if (IS_ERR(acl)) | 448 | if (IS_ERR(acl)) |
@@ -442,17 +453,8 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
442 | return -ENOMEM; | 453 | return -ENOMEM; |
443 | error = posix_acl_chmod_masq(clone, inode->i_mode); | 454 | error = posix_acl_chmod_masq(clone, inode->i_mode); |
444 | if (!error) { | 455 | if (!error) { |
445 | int lock = !has_xattr_dir(inode); | ||
446 | reiserfs_write_lock_xattr_i(inode); | 456 | reiserfs_write_lock_xattr_i(inode); |
447 | if (lock) | ||
448 | reiserfs_write_lock_xattrs(inode->i_sb); | ||
449 | else | ||
450 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
451 | error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); | 457 | error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); |
452 | if (lock) | ||
453 | reiserfs_write_unlock_xattrs(inode->i_sb); | ||
454 | else | ||
455 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
456 | reiserfs_write_unlock_xattr_i(inode); | 458 | reiserfs_write_unlock_xattr_i(inode); |
457 | } | 459 | } |
458 | posix_acl_release(clone); | 460 | posix_acl_release(clone); |
@@ -480,14 +482,9 @@ posix_acl_access_set(struct inode *inode, const char *name, | |||
480 | static int posix_acl_access_del(struct inode *inode, const char *name) | 482 | static int posix_acl_access_del(struct inode *inode, const char *name) |
481 | { | 483 | { |
482 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); | 484 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); |
483 | struct posix_acl **acl = &reiserfs_i->i_acl_access; | ||
484 | if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) | 485 | if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1) |
485 | return -EINVAL; | 486 | return -EINVAL; |
486 | if (!IS_ERR(*acl) && *acl) { | 487 | iset_acl(inode, &reiserfs_i->i_acl_access, ERR_PTR(-ENODATA)); |
487 | posix_acl_release(*acl); | ||
488 | *acl = ERR_PTR(-ENODATA); | ||
489 | } | ||
490 | |||
491 | return 0; | 488 | return 0; |
492 | } | 489 | } |
493 | 490 | ||
@@ -533,14 +530,9 @@ posix_acl_default_set(struct inode *inode, const char *name, | |||
533 | static int posix_acl_default_del(struct inode *inode, const char *name) | 530 | static int posix_acl_default_del(struct inode *inode, const char *name) |
534 | { | 531 | { |
535 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); | 532 | struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); |
536 | struct posix_acl **acl = &reiserfs_i->i_acl_default; | ||
537 | if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) | 533 | if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1) |
538 | return -EINVAL; | 534 | return -EINVAL; |
539 | if (!IS_ERR(*acl) && *acl) { | 535 | iset_acl(inode, &reiserfs_i->i_acl_default, ERR_PTR(-ENODATA)); |
540 | posix_acl_release(*acl); | ||
541 | *acl = ERR_PTR(-ENODATA); | ||
542 | } | ||
543 | |||
544 | return 0; | 536 | return 0; |
545 | } | 537 | } |
546 | 538 | ||