aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2009-03-30 14:02:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-30 15:16:38 -0400
commit8b6dd72a441a683cef7ace93de0a57ced4367f00 (patch)
tree6bdeebd3a35d71db2c7ea3e48e3f617b5efbd81a /fs
parentd984561b326cd0fe0d1183d11b9b4fa1d011d21d (diff)
reiserfs: make per-inode xattr locking more fine grained
The per-inode locking can be made more fine-grained to surround just the interaction with the filesystem itself. This really only applies to protecting reads during a write, since concurrent writes are barred with inode->i_mutex at the vfs level. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/reiserfs/xattr.c114
-rw-r--r--fs/reiserfs/xattr_acl.c7
2 files changed, 54 insertions, 67 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 62c98829c545..ccb8e4d4c032 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -29,10 +29,8 @@
29 * to the inode so that unnecessary lookups are avoided. 29 * to the inode so that unnecessary lookups are avoided.
30 * 30 *
31 * Locking works like so: 31 * Locking works like so:
32 * The xattr root (/.reiserfs_priv/xattrs) is protected by its i_mutex. 32 * Directory components (xattr root, xattr dir) are protectd by their i_mutex.
33 * The xattr dir (/.reiserfs_priv/xattrs/<oid>.<gen>) is protected by 33 * The xattrs themselves are protected by the xattr_sem.
34 * inode->xattr_sem.
35 * The xattrs themselves are likewise protected by the xattr_sem.
36 */ 34 */
37 35
38#include <linux/reiserfs_fs.h> 36#include <linux/reiserfs_fs.h>
@@ -55,6 +53,8 @@
55#define PRIVROOT_NAME ".reiserfs_priv" 53#define PRIVROOT_NAME ".reiserfs_priv"
56#define XAROOT_NAME "xattrs" 54#define XAROOT_NAME "xattrs"
57 55
56static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *);
57
58/* Helpers for inode ops. We do this so that we don't have all the VFS 58/* Helpers for inode ops. We do this so that we don't have all the VFS
59 * overhead and also for proper i_mutex annotation. 59 * overhead and also for proper i_mutex annotation.
60 * dir->i_mutex must be held for all of them. */ 60 * dir->i_mutex must be held for all of them. */
@@ -339,12 +339,14 @@ int xattr_readdir(struct inode *inode, filldir_t filler, void *buf)
339 return res; 339 return res;
340} 340}
341 341
342/* expects xadir->d_inode->i_mutex to be locked */
342static int 343static int
343__reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen) 344__reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen)
344{ 345{
345 struct dentry *dentry; 346 struct dentry *dentry;
346 struct inode *dir = xadir->d_inode; 347 struct inode *dir = xadir->d_inode;
347 int err = 0; 348 int err = 0;
349 struct reiserfs_xattr_handler *xah;
348 350
349 dentry = lookup_one_len(name, xadir, namelen); 351 dentry = lookup_one_len(name, xadir, namelen);
350 if (IS_ERR(dentry)) { 352 if (IS_ERR(dentry)) {
@@ -372,6 +374,14 @@ __reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen)
372 return -EIO; 374 return -EIO;
373 } 375 }
374 376
377 /* Deletion pre-operation */
378 xah = find_xattr_handler_prefix(name);
379 if (xah && xah->del) {
380 err = xah->del(dentry->d_inode, name);
381 if (err)
382 goto out;
383 }
384
375 err = xattr_unlink(dir, dentry); 385 err = xattr_unlink(dir, dentry);
376 386
377out_file: 387out_file:
@@ -398,7 +408,7 @@ reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
398/* This is called w/ inode->i_mutex downed */ 408/* This is called w/ inode->i_mutex downed */
399int reiserfs_delete_xattrs(struct inode *inode) 409int reiserfs_delete_xattrs(struct inode *inode)
400{ 410{
401 int err = 0; 411 int err = -ENODATA;
402 struct dentry *dir, *root; 412 struct dentry *dir, *root;
403 struct reiserfs_transaction_handle th; 413 struct reiserfs_transaction_handle th;
404 int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 414 int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 +
@@ -414,14 +424,19 @@ int reiserfs_delete_xattrs(struct inode *inode)
414 goto out; 424 goto out;
415 } else if (!dir->d_inode) { 425 } else if (!dir->d_inode) {
416 dput(dir); 426 dput(dir);
417 return 0; 427 goto out;
418 } 428 }
419 429
420 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); 430 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
421 err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); 431 err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir);
422 mutex_unlock(&dir->d_inode->i_mutex); 432 mutex_unlock(&dir->d_inode->i_mutex);
423 if (err) 433 if (err) {
424 goto out_dir; 434 dput(dir);
435 goto out;
436 }
437
438 root = dget(dir->d_parent);
439 dput(dir);
425 440
426 /* We start a transaction here to avoid a ABBA situation 441 /* We start a transaction here to avoid a ABBA situation
427 * between the xattr root's i_mutex and the journal lock. 442 * between the xattr root's i_mutex and the journal lock.
@@ -435,19 +450,14 @@ int reiserfs_delete_xattrs(struct inode *inode)
435 err = journal_begin(&th, inode->i_sb, blocks); 450 err = journal_begin(&th, inode->i_sb, blocks);
436 if (!err) { 451 if (!err) {
437 int jerror; 452 int jerror;
438 root = dget(dir->d_parent);
439 mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_XATTR); 453 mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_XATTR);
440 err = xattr_rmdir(root->d_inode, dir); 454 err = xattr_rmdir(root->d_inode, dir);
441 jerror = journal_end(&th, inode->i_sb, blocks); 455 jerror = journal_end(&th, inode->i_sb, blocks);
442 mutex_unlock(&root->d_inode->i_mutex); 456 mutex_unlock(&root->d_inode->i_mutex);
443 dput(root);
444
445 err = jerror ?: err; 457 err = jerror ?: err;
446 } 458 }
447 459
448out_dir: 460 dput(root);
449 dput(dir);
450
451out: 461out:
452 if (!err) 462 if (!err)
453 REISERFS_I(inode)->i_flags = 463 REISERFS_I(inode)->i_flags =
@@ -484,7 +494,7 @@ reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen,
484 494
485 if (!S_ISDIR(xafile->d_inode->i_mode)) { 495 if (!S_ISDIR(xafile->d_inode->i_mode)) {
486 mutex_lock_nested(&xafile->d_inode->i_mutex, I_MUTEX_CHILD); 496 mutex_lock_nested(&xafile->d_inode->i_mutex, I_MUTEX_CHILD);
487 err = notify_change(xafile, attrs); 497 err = reiserfs_setattr(xafile, attrs);
488 mutex_unlock(&xafile->d_inode->i_mutex); 498 mutex_unlock(&xafile->d_inode->i_mutex);
489 } 499 }
490 dput(xafile); 500 dput(xafile);
@@ -520,13 +530,16 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
520 err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); 530 err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf);
521 531
522 if (!err) 532 if (!err)
523 err = notify_change(dir, attrs); 533 err = reiserfs_setattr(dir, attrs);
524 mutex_unlock(&dir->d_inode->i_mutex); 534 mutex_unlock(&dir->d_inode->i_mutex);
525 535
526 attrs->ia_valid = ia_valid; 536 attrs->ia_valid = ia_valid;
527out_dir: 537out_dir:
528 dput(dir); 538 dput(dir);
529out: 539out:
540 if (err)
541 reiserfs_warning(inode->i_sb, "jdm-20007",
542 "Couldn't chown all xattrs (%d)\n", err);
530 return err; 543 return err;
531} 544}
532 545
@@ -635,9 +648,8 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
635 if (get_inode_sd_version(inode) == STAT_DATA_V1) 648 if (get_inode_sd_version(inode) == STAT_DATA_V1)
636 return -EOPNOTSUPP; 649 return -EOPNOTSUPP;
637 650
638 /* Empty xattrs are ok, they're just empty files, no hash */ 651 if (!buffer)
639 if (buffer && buffer_size) 652 return reiserfs_xattr_del(inode, name);
640 xahash = xattr_hash(buffer, buffer_size);
641 653
642 dentry = get_xa_file_dentry(inode, name, flags); 654 dentry = get_xa_file_dentry(inode, name, flags);
643 if (IS_ERR(dentry)) { 655 if (IS_ERR(dentry)) {
@@ -645,13 +657,19 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
645 goto out; 657 goto out;
646 } 658 }
647 659
660 down_write(&REISERFS_I(inode)->i_xattr_sem);
661
662 xahash = xattr_hash(buffer, buffer_size);
648 REISERFS_I(inode)->i_flags |= i_has_xattr_dir; 663 REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
649 664
650 /* Resize it so we're ok to write there */ 665 /* Resize it so we're ok to write there */
651 newattrs.ia_size = buffer_size; 666 newattrs.ia_size = buffer_size;
667 newattrs.ia_ctime = current_fs_time(inode->i_sb);
652 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; 668 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
653 mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); 669 mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
654 err = notify_change(dentry, &newattrs); 670 down_write(&dentry->d_inode->i_alloc_sem);
671 err = reiserfs_setattr(dentry, &newattrs);
672 up_write(&dentry->d_inode->i_alloc_sem);
655 mutex_unlock(&dentry->d_inode->i_mutex); 673 mutex_unlock(&dentry->d_inode->i_mutex);
656 if (err) 674 if (err)
657 goto out_filp; 675 goto out_filp;
@@ -712,6 +730,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
712 } 730 }
713 731
714 out_filp: 732 out_filp:
733 up_write(&REISERFS_I(inode)->i_xattr_sem);
715 dput(dentry); 734 dput(dentry);
716 735
717 out: 736 out:
@@ -747,10 +766,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
747 goto out; 766 goto out;
748 } 767 }
749 768
750 /* protect against concurrent access. xattrs are backed by 769 down_read(&REISERFS_I(inode)->i_xattr_sem);
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 770
755 isize = i_size_read(dentry->d_inode); 771 isize = i_size_read(dentry->d_inode);
756 REISERFS_I(inode)->i_flags |= i_has_xattr_dir; 772 REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
@@ -758,12 +774,12 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
758 /* Just return the size needed */ 774 /* Just return the size needed */
759 if (buffer == NULL) { 775 if (buffer == NULL) {
760 err = isize - sizeof(struct reiserfs_xattr_header); 776 err = isize - sizeof(struct reiserfs_xattr_header);
761 goto out_dput; 777 goto out_unlock;
762 } 778 }
763 779
764 if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) { 780 if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) {
765 err = -ERANGE; 781 err = -ERANGE;
766 goto out_dput; 782 goto out_unlock;
767 } 783 }
768 784
769 while (file_pos < isize) { 785 while (file_pos < isize) {
@@ -778,7 +794,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
778 page = reiserfs_get_page(dentry->d_inode, file_pos); 794 page = reiserfs_get_page(dentry->d_inode, file_pos);
779 if (IS_ERR(page)) { 795 if (IS_ERR(page)) {
780 err = PTR_ERR(page); 796 err = PTR_ERR(page);
781 goto out_dput; 797 goto out_unlock;
782 } 798 }
783 799
784 lock_page(page); 800 lock_page(page);
@@ -797,7 +813,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
797 "associated with %k", name, 813 "associated with %k", name,
798 INODE_PKEY(inode)); 814 INODE_PKEY(inode));
799 err = -EIO; 815 err = -EIO;
800 goto out_dput; 816 goto out_unlock;
801 } 817 }
802 hash = le32_to_cpu(rxh->h_hash); 818 hash = le32_to_cpu(rxh->h_hash);
803 } 819 }
@@ -818,8 +834,8 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
818 err = -EIO; 834 err = -EIO;
819 } 835 }
820 836
821out_dput: 837out_unlock:
822 mutex_unlock(&dentry->d_inode->i_mutex); 838 up_read(&REISERFS_I(inode)->i_xattr_sem);
823 dput(dentry); 839 dput(dentry);
824 840
825out: 841out:
@@ -852,8 +868,6 @@ int reiserfs_xattr_del(struct inode *inode, const char *name)
852} 868}
853 869
854/* Actual operations that are exported to VFS-land */ 870/* Actual operations that are exported to VFS-land */
855
856static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *);
857/* 871/*
858 * Inode operation getxattr() 872 * Inode operation getxattr()
859 */ 873 */
@@ -868,9 +882,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
868 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) 882 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
869 return -EOPNOTSUPP; 883 return -EOPNOTSUPP;
870 884
871 reiserfs_read_lock_xattr_i(dentry->d_inode);
872 err = xah->get(dentry->d_inode, name, buffer, size); 885 err = xah->get(dentry->d_inode, name, buffer, size);
873 reiserfs_read_unlock_xattr_i(dentry->d_inode);
874 return err; 886 return err;
875} 887}
876 888
@@ -890,9 +902,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
890 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) 902 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
891 return -EOPNOTSUPP; 903 return -EOPNOTSUPP;
892 904
893 reiserfs_write_lock_xattr_i(dentry->d_inode);
894 err = xah->set(dentry->d_inode, name, value, size, flags); 905 err = xah->set(dentry->d_inode, name, value, size, flags);
895 reiserfs_write_unlock_xattr_i(dentry->d_inode);
896 return err; 906 return err;
897} 907}
898 908
@@ -910,21 +920,11 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)
910 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) 920 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
911 return -EOPNOTSUPP; 921 return -EOPNOTSUPP;
912 922
913 reiserfs_write_lock_xattr_i(dentry->d_inode);
914 /* Deletion pre-operation */
915 if (xah->del) {
916 err = xah->del(dentry->d_inode, name);
917 if (err)
918 goto out;
919 }
920
921 err = reiserfs_xattr_del(dentry->d_inode, name); 923 err = reiserfs_xattr_del(dentry->d_inode, name);
922 924
923 dentry->d_inode->i_ctime = CURRENT_TIME_SEC; 925 dentry->d_inode->i_ctime = CURRENT_TIME_SEC;
924 mark_inode_dirty(dentry->d_inode); 926 mark_inode_dirty(dentry->d_inode);
925 927
926 out:
927 reiserfs_write_unlock_xattr_i(dentry->d_inode);
928 return err; 928 return err;
929} 929}
930 930
@@ -986,7 +986,6 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
986 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) 986 get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
987 return -EOPNOTSUPP; 987 return -EOPNOTSUPP;
988 988
989 reiserfs_read_lock_xattr_i(dentry->d_inode);
990 dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); 989 dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE);
991 if (IS_ERR(dir)) { 990 if (IS_ERR(dir)) {
992 err = PTR_ERR(dir); 991 err = PTR_ERR(dir);
@@ -1005,19 +1004,16 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
1005 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); 1004 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
1006 err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf); 1005 err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf);
1007 mutex_unlock(&dir->d_inode->i_mutex); 1006 mutex_unlock(&dir->d_inode->i_mutex);
1008 if (err)
1009 goto out_dir;
1010 1007
1011 if (buf.r_pos > buf.r_size && buffer != NULL) 1008 if (!err) {
1012 err = -ERANGE; 1009 if (buf.r_pos > buf.r_size && buffer != NULL)
1013 else 1010 err = -ERANGE;
1014 err = buf.r_pos; 1011 else
1012 err = buf.r_pos;
1013 }
1015 1014
1016 out_dir:
1017 dput(dir); 1015 dput(dir);
1018 1016out:
1019 out:
1020 reiserfs_read_unlock_xattr_i(dentry->d_inode);
1021 return err; 1017 return err;
1022} 1018}
1023 1019
@@ -1115,12 +1111,8 @@ static int reiserfs_check_acl(struct inode *inode, int mask)
1115 struct posix_acl *acl; 1111 struct posix_acl *acl;
1116 int error = -EAGAIN; /* do regular unix permission checks by default */ 1112 int error = -EAGAIN; /* do regular unix permission checks by default */
1117 1113
1118 reiserfs_read_lock_xattr_i(inode);
1119
1120 acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); 1114 acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
1121 1115
1122 reiserfs_read_unlock_xattr_i(inode);
1123
1124 if (acl) { 1116 if (acl) {
1125 if (!IS_ERR(acl)) { 1117 if (!IS_ERR(acl)) {
1126 error = posix_acl_permission(inode, acl, mask); 1118 error = posix_acl_permission(inode, acl, mask);
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index d63b2c5850c3..d3ce6ee9b262 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -418,9 +418,7 @@ int reiserfs_cache_default_acl(struct inode *inode)
418 int ret = 0; 418 int ret = 0;
419 if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) { 419 if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) {
420 struct posix_acl *acl; 420 struct posix_acl *acl;
421 reiserfs_read_lock_xattr_i(inode);
422 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); 421 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
423 reiserfs_read_unlock_xattr_i(inode);
424 ret = (acl && !IS_ERR(acl)); 422 ret = (acl && !IS_ERR(acl));
425 if (ret) 423 if (ret)
426 posix_acl_release(acl); 424 posix_acl_release(acl);
@@ -452,11 +450,8 @@ int reiserfs_acl_chmod(struct inode *inode)
452 if (!clone) 450 if (!clone)
453 return -ENOMEM; 451 return -ENOMEM;
454 error = posix_acl_chmod_masq(clone, inode->i_mode); 452 error = posix_acl_chmod_masq(clone, inode->i_mode);
455 if (!error) { 453 if (!error)
456 reiserfs_write_lock_xattr_i(inode);
457 error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 454 error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
458 reiserfs_write_unlock_xattr_i(inode);
459 }
460 posix_acl_release(clone); 455 posix_acl_release(clone);
461 return error; 456 return error;
462} 457}