diff options
Diffstat (limited to 'fs/reiserfs/xattr.c')
-rw-r--r-- | fs/reiserfs/xattr.c | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 6925b835a43b..e7cc00e636dc 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/dcache.h> | 38 | #include <linux/dcache.h> |
39 | #include <linux/namei.h> | 39 | #include <linux/namei.h> |
40 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
41 | #include <linux/gfp.h> | ||
41 | #include <linux/fs.h> | 42 | #include <linux/fs.h> |
42 | #include <linux/file.h> | 43 | #include <linux/file.h> |
43 | #include <linux/pagemap.h> | 44 | #include <linux/pagemap.h> |
@@ -48,6 +49,7 @@ | |||
48 | #include <net/checksum.h> | 49 | #include <net/checksum.h> |
49 | #include <linux/stat.h> | 50 | #include <linux/stat.h> |
50 | #include <linux/quotaops.h> | 51 | #include <linux/quotaops.h> |
52 | #include <linux/security.h> | ||
51 | 53 | ||
52 | #define PRIVROOT_NAME ".reiserfs_priv" | 54 | #define PRIVROOT_NAME ".reiserfs_priv" |
53 | #define XAROOT_NAME "xattrs" | 55 | #define XAROOT_NAME "xattrs" |
@@ -60,7 +62,6 @@ | |||
60 | static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) | 62 | static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) |
61 | { | 63 | { |
62 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 64 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
63 | vfs_dq_init(dir); | ||
64 | return dir->i_op->create(dir, dentry, mode, NULL); | 65 | return dir->i_op->create(dir, dentry, mode, NULL); |
65 | } | 66 | } |
66 | #endif | 67 | #endif |
@@ -68,7 +69,6 @@ static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) | |||
68 | static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 69 | static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
69 | { | 70 | { |
70 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 71 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
71 | vfs_dq_init(dir); | ||
72 | return dir->i_op->mkdir(dir, dentry, mode); | 72 | return dir->i_op->mkdir(dir, dentry, mode); |
73 | } | 73 | } |
74 | 74 | ||
@@ -80,9 +80,9 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry) | |||
80 | { | 80 | { |
81 | int error; | 81 | int error; |
82 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 82 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
83 | vfs_dq_init(dir); | ||
84 | 83 | ||
85 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | 84 | reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, |
85 | I_MUTEX_CHILD, dir->i_sb); | ||
86 | error = dir->i_op->unlink(dir, dentry); | 86 | error = dir->i_op->unlink(dir, dentry); |
87 | mutex_unlock(&dentry->d_inode->i_mutex); | 87 | mutex_unlock(&dentry->d_inode->i_mutex); |
88 | 88 | ||
@@ -95,9 +95,9 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) | |||
95 | { | 95 | { |
96 | int error; | 96 | int error; |
97 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 97 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
98 | vfs_dq_init(dir); | ||
99 | 98 | ||
100 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | 99 | reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, |
100 | I_MUTEX_CHILD, dir->i_sb); | ||
101 | dentry_unhash(dentry); | 101 | dentry_unhash(dentry); |
102 | error = dir->i_op->rmdir(dir, dentry); | 102 | error = dir->i_op->rmdir(dir, dentry); |
103 | if (!error) | 103 | if (!error) |
@@ -234,16 +234,22 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
234 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) | 234 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) |
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | reiserfs_write_unlock(inode->i_sb); | ||
237 | dir = open_xa_dir(inode, XATTR_REPLACE); | 238 | dir = open_xa_dir(inode, XATTR_REPLACE); |
238 | if (IS_ERR(dir)) { | 239 | if (IS_ERR(dir)) { |
239 | err = PTR_ERR(dir); | 240 | err = PTR_ERR(dir); |
241 | reiserfs_write_lock(inode->i_sb); | ||
240 | goto out; | 242 | goto out; |
241 | } else if (!dir->d_inode) { | 243 | } else if (!dir->d_inode) { |
242 | err = 0; | 244 | err = 0; |
245 | reiserfs_write_lock(inode->i_sb); | ||
243 | goto out_dir; | 246 | goto out_dir; |
244 | } | 247 | } |
245 | 248 | ||
246 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); | 249 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); |
250 | |||
251 | reiserfs_write_lock(inode->i_sb); | ||
252 | |||
247 | buf.xadir = dir; | 253 | buf.xadir = dir; |
248 | err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); | 254 | err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); |
249 | while ((err == 0 || err == -ENOSPC) && buf.count) { | 255 | while ((err == 0 || err == -ENOSPC) && buf.count) { |
@@ -282,8 +288,9 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
282 | err = journal_begin(&th, inode->i_sb, blocks); | 288 | err = journal_begin(&th, inode->i_sb, blocks); |
283 | if (!err) { | 289 | if (!err) { |
284 | int jerror; | 290 | int jerror; |
285 | mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, | 291 | reiserfs_mutex_lock_nested_safe( |
286 | I_MUTEX_XATTR); | 292 | &dir->d_parent->d_inode->i_mutex, |
293 | I_MUTEX_XATTR, inode->i_sb); | ||
287 | err = action(dir, data); | 294 | err = action(dir, data); |
288 | jerror = journal_end(&th, inode->i_sb, blocks); | 295 | jerror = journal_end(&th, inode->i_sb, blocks); |
289 | mutex_unlock(&dir->d_parent->d_inode->i_mutex); | 296 | mutex_unlock(&dir->d_parent->d_inode->i_mutex); |
@@ -442,7 +449,9 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) | |||
442 | } | 449 | } |
443 | 450 | ||
444 | if (dentry->d_inode) { | 451 | if (dentry->d_inode) { |
452 | reiserfs_write_lock(inode->i_sb); | ||
445 | err = xattr_unlink(xadir->d_inode, dentry); | 453 | err = xattr_unlink(xadir->d_inode, dentry); |
454 | reiserfs_write_unlock(inode->i_sb); | ||
446 | update_ctime(inode); | 455 | update_ctime(inode); |
447 | } | 456 | } |
448 | 457 | ||
@@ -476,15 +485,24 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
476 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 485 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
477 | return -EOPNOTSUPP; | 486 | return -EOPNOTSUPP; |
478 | 487 | ||
479 | if (!buffer) | 488 | reiserfs_write_unlock(inode->i_sb); |
480 | return lookup_and_delete_xattr(inode, name); | 489 | |
490 | if (!buffer) { | ||
491 | err = lookup_and_delete_xattr(inode, name); | ||
492 | reiserfs_write_lock(inode->i_sb); | ||
493 | return err; | ||
494 | } | ||
481 | 495 | ||
482 | dentry = xattr_lookup(inode, name, flags); | 496 | dentry = xattr_lookup(inode, name, flags); |
483 | if (IS_ERR(dentry)) | 497 | if (IS_ERR(dentry)) { |
498 | reiserfs_write_lock(inode->i_sb); | ||
484 | return PTR_ERR(dentry); | 499 | return PTR_ERR(dentry); |
500 | } | ||
485 | 501 | ||
486 | down_write(&REISERFS_I(inode)->i_xattr_sem); | 502 | down_write(&REISERFS_I(inode)->i_xattr_sem); |
487 | 503 | ||
504 | reiserfs_write_lock(inode->i_sb); | ||
505 | |||
488 | xahash = xattr_hash(buffer, buffer_size); | 506 | xahash = xattr_hash(buffer, buffer_size); |
489 | while (buffer_pos < buffer_size || buffer_pos == 0) { | 507 | while (buffer_pos < buffer_size || buffer_pos == 0) { |
490 | size_t chunk; | 508 | size_t chunk; |
@@ -536,11 +554,15 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
536 | if (!err && new_size < i_size_read(dentry->d_inode)) { | 554 | if (!err && new_size < i_size_read(dentry->d_inode)) { |
537 | struct iattr newattrs = { | 555 | struct iattr newattrs = { |
538 | .ia_ctime = current_fs_time(inode->i_sb), | 556 | .ia_ctime = current_fs_time(inode->i_sb), |
539 | .ia_size = buffer_size, | 557 | .ia_size = new_size, |
540 | .ia_valid = ATTR_SIZE | ATTR_CTIME, | 558 | .ia_valid = ATTR_SIZE | ATTR_CTIME, |
541 | }; | 559 | }; |
560 | |||
561 | reiserfs_write_unlock(inode->i_sb); | ||
542 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); | 562 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); |
543 | down_write(&dentry->d_inode->i_alloc_sem); | 563 | down_write(&dentry->d_inode->i_alloc_sem); |
564 | reiserfs_write_lock(inode->i_sb); | ||
565 | |||
544 | err = reiserfs_setattr(dentry, &newattrs); | 566 | err = reiserfs_setattr(dentry, &newattrs); |
545 | up_write(&dentry->d_inode->i_alloc_sem); | 567 | up_write(&dentry->d_inode->i_alloc_sem); |
546 | mutex_unlock(&dentry->d_inode->i_mutex); | 568 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -726,15 +748,14 @@ ssize_t | |||
726 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, | 748 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, |
727 | size_t size) | 749 | size_t size) |
728 | { | 750 | { |
729 | struct inode *inode = dentry->d_inode; | ||
730 | struct xattr_handler *handler; | 751 | struct xattr_handler *handler; |
731 | 752 | ||
732 | handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name); | 753 | handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); |
733 | 754 | ||
734 | if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1) | 755 | if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) |
735 | return -EOPNOTSUPP; | 756 | return -EOPNOTSUPP; |
736 | 757 | ||
737 | return handler->get(inode, name, buffer, size); | 758 | return handler->get(dentry, name, buffer, size, handler->flags); |
738 | } | 759 | } |
739 | 760 | ||
740 | /* | 761 | /* |
@@ -746,15 +767,14 @@ int | |||
746 | reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 767 | reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
747 | size_t size, int flags) | 768 | size_t size, int flags) |
748 | { | 769 | { |
749 | struct inode *inode = dentry->d_inode; | ||
750 | struct xattr_handler *handler; | 770 | struct xattr_handler *handler; |
751 | 771 | ||
752 | handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name); | 772 | handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); |
753 | 773 | ||
754 | if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1) | 774 | if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) |
755 | return -EOPNOTSUPP; | 775 | return -EOPNOTSUPP; |
756 | 776 | ||
757 | return handler->set(inode, name, value, size, flags); | 777 | return handler->set(dentry, name, value, size, flags, handler->flags); |
758 | } | 778 | } |
759 | 779 | ||
760 | /* | 780 | /* |
@@ -764,21 +784,20 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
764 | */ | 784 | */ |
765 | int reiserfs_removexattr(struct dentry *dentry, const char *name) | 785 | int reiserfs_removexattr(struct dentry *dentry, const char *name) |
766 | { | 786 | { |
767 | struct inode *inode = dentry->d_inode; | ||
768 | struct xattr_handler *handler; | 787 | struct xattr_handler *handler; |
769 | handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name); | 788 | handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); |
770 | 789 | ||
771 | if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1) | 790 | if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) |
772 | return -EOPNOTSUPP; | 791 | return -EOPNOTSUPP; |
773 | 792 | ||
774 | return handler->set(inode, name, NULL, 0, XATTR_REPLACE); | 793 | return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags); |
775 | } | 794 | } |
776 | 795 | ||
777 | struct listxattr_buf { | 796 | struct listxattr_buf { |
778 | size_t size; | 797 | size_t size; |
779 | size_t pos; | 798 | size_t pos; |
780 | char *buf; | 799 | char *buf; |
781 | struct inode *inode; | 800 | struct dentry *dentry; |
782 | }; | 801 | }; |
783 | 802 | ||
784 | static int listxattr_filler(void *buf, const char *name, int namelen, | 803 | static int listxattr_filler(void *buf, const char *name, int namelen, |
@@ -789,17 +808,19 @@ static int listxattr_filler(void *buf, const char *name, int namelen, | |||
789 | if (name[0] != '.' || | 808 | if (name[0] != '.' || |
790 | (namelen != 1 && (name[1] != '.' || namelen != 2))) { | 809 | (namelen != 1 && (name[1] != '.' || namelen != 2))) { |
791 | struct xattr_handler *handler; | 810 | struct xattr_handler *handler; |
792 | handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr, | 811 | handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, |
793 | name); | 812 | name); |
794 | if (!handler) /* Unsupported xattr name */ | 813 | if (!handler) /* Unsupported xattr name */ |
795 | return 0; | 814 | return 0; |
796 | if (b->buf) { | 815 | if (b->buf) { |
797 | size = handler->list(b->inode, b->buf + b->pos, | 816 | size = handler->list(b->dentry, b->buf + b->pos, |
798 | b->size, name, namelen); | 817 | b->size, name, namelen, |
818 | handler->flags); | ||
799 | if (size > b->size) | 819 | if (size > b->size) |
800 | return -ERANGE; | 820 | return -ERANGE; |
801 | } else { | 821 | } else { |
802 | size = handler->list(b->inode, NULL, 0, name, namelen); | 822 | size = handler->list(b->dentry, NULL, 0, name, |
823 | namelen, handler->flags); | ||
803 | } | 824 | } |
804 | 825 | ||
805 | b->pos += size; | 826 | b->pos += size; |
@@ -820,7 +841,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
820 | int err = 0; | 841 | int err = 0; |
821 | loff_t pos = 0; | 842 | loff_t pos = 0; |
822 | struct listxattr_buf buf = { | 843 | struct listxattr_buf buf = { |
823 | .inode = dentry->d_inode, | 844 | .dentry = dentry, |
824 | .buf = buffer, | 845 | .buf = buffer, |
825 | .size = buffer ? size : 0, | 846 | .size = buffer ? size : 0, |
826 | }; | 847 | }; |
@@ -952,21 +973,13 @@ int reiserfs_permission(struct inode *inode, int mask) | |||
952 | return generic_permission(inode, mask, NULL); | 973 | return generic_permission(inode, mask, NULL); |
953 | } | 974 | } |
954 | 975 | ||
955 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 976 | static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) |
956 | static int | ||
957 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | ||
958 | { | 977 | { |
959 | struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; | 978 | return -EPERM; |
960 | if (container_of(q1, struct dentry, d_name) == priv_root) | ||
961 | return -ENOENT; | ||
962 | if (q1->len == name->len && | ||
963 | !memcmp(q1->name, name->name, name->len)) | ||
964 | return 0; | ||
965 | return 1; | ||
966 | } | 979 | } |
967 | 980 | ||
968 | static const struct dentry_operations xattr_lookup_poison_ops = { | 981 | static const struct dentry_operations xattr_lookup_poison_ops = { |
969 | .d_compare = xattr_lookup_poison, | 982 | .d_revalidate = xattr_hide_revalidate, |
970 | }; | 983 | }; |
971 | 984 | ||
972 | int reiserfs_lookup_privroot(struct super_block *s) | 985 | int reiserfs_lookup_privroot(struct super_block *s) |
@@ -975,13 +988,12 @@ int reiserfs_lookup_privroot(struct super_block *s) | |||
975 | int err = 0; | 988 | int err = 0; |
976 | 989 | ||
977 | /* If we don't have the privroot located yet - go find it */ | 990 | /* If we don't have the privroot located yet - go find it */ |
978 | mutex_lock(&s->s_root->d_inode->i_mutex); | 991 | reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); |
979 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, | 992 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, |
980 | strlen(PRIVROOT_NAME)); | 993 | strlen(PRIVROOT_NAME)); |
981 | if (!IS_ERR(dentry)) { | 994 | if (!IS_ERR(dentry)) { |
982 | REISERFS_SB(s)->priv_root = dentry; | 995 | REISERFS_SB(s)->priv_root = dentry; |
983 | if (!reiserfs_expose_privroot(s)) | 996 | dentry->d_op = &xattr_lookup_poison_ops; |
984 | s->s_root->d_op = &xattr_lookup_poison_ops; | ||
985 | if (dentry->d_inode) | 997 | if (dentry->d_inode) |
986 | dentry->d_inode->i_flags |= S_PRIVATE; | 998 | dentry->d_inode->i_flags |= S_PRIVATE; |
987 | } else | 999 | } else |
@@ -1004,14 +1016,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
1004 | goto error; | 1016 | goto error; |
1005 | 1017 | ||
1006 | if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { | 1018 | if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { |
1007 | mutex_lock(&s->s_root->d_inode->i_mutex); | 1019 | reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); |
1008 | err = create_privroot(REISERFS_SB(s)->priv_root); | 1020 | err = create_privroot(REISERFS_SB(s)->priv_root); |
1009 | mutex_unlock(&s->s_root->d_inode->i_mutex); | 1021 | mutex_unlock(&s->s_root->d_inode->i_mutex); |
1010 | } | 1022 | } |
1011 | 1023 | ||
1012 | if (privroot->d_inode) { | 1024 | if (privroot->d_inode) { |
1013 | s->s_xattr = reiserfs_xattr_handlers; | 1025 | s->s_xattr = reiserfs_xattr_handlers; |
1014 | mutex_lock(&privroot->d_inode->i_mutex); | 1026 | reiserfs_mutex_lock_safe(&privroot->d_inode->i_mutex, s); |
1015 | if (!REISERFS_SB(s)->xattr_root) { | 1027 | if (!REISERFS_SB(s)->xattr_root) { |
1016 | struct dentry *dentry; | 1028 | struct dentry *dentry; |
1017 | dentry = lookup_one_len(XAROOT_NAME, privroot, | 1029 | dentry = lookup_one_len(XAROOT_NAME, privroot, |