diff options
Diffstat (limited to 'fs/reiserfs/xattr.c')
-rw-r--r-- | fs/reiserfs/xattr.c | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 8c7033a8b67e..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> |
@@ -61,7 +62,6 @@ | |||
61 | 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) |
62 | { | 63 | { |
63 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 64 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
64 | vfs_dq_init(dir); | ||
65 | return dir->i_op->create(dir, dentry, mode, NULL); | 65 | return dir->i_op->create(dir, dentry, mode, NULL); |
66 | } | 66 | } |
67 | #endif | 67 | #endif |
@@ -69,7 +69,6 @@ static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) | |||
69 | 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) |
70 | { | 70 | { |
71 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 71 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
72 | vfs_dq_init(dir); | ||
73 | return dir->i_op->mkdir(dir, dentry, mode); | 72 | return dir->i_op->mkdir(dir, dentry, mode); |
74 | } | 73 | } |
75 | 74 | ||
@@ -81,9 +80,9 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry) | |||
81 | { | 80 | { |
82 | int error; | 81 | int error; |
83 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 82 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
84 | vfs_dq_init(dir); | ||
85 | 83 | ||
86 | 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); | ||
87 | error = dir->i_op->unlink(dir, dentry); | 86 | error = dir->i_op->unlink(dir, dentry); |
88 | mutex_unlock(&dentry->d_inode->i_mutex); | 87 | mutex_unlock(&dentry->d_inode->i_mutex); |
89 | 88 | ||
@@ -96,9 +95,9 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) | |||
96 | { | 95 | { |
97 | int error; | 96 | int error; |
98 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 97 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
99 | vfs_dq_init(dir); | ||
100 | 98 | ||
101 | 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); | ||
102 | dentry_unhash(dentry); | 101 | dentry_unhash(dentry); |
103 | error = dir->i_op->rmdir(dir, dentry); | 102 | error = dir->i_op->rmdir(dir, dentry); |
104 | if (!error) | 103 | if (!error) |
@@ -235,16 +234,22 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
235 | 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) |
236 | return 0; | 235 | return 0; |
237 | 236 | ||
237 | reiserfs_write_unlock(inode->i_sb); | ||
238 | dir = open_xa_dir(inode, XATTR_REPLACE); | 238 | dir = open_xa_dir(inode, XATTR_REPLACE); |
239 | if (IS_ERR(dir)) { | 239 | if (IS_ERR(dir)) { |
240 | err = PTR_ERR(dir); | 240 | err = PTR_ERR(dir); |
241 | reiserfs_write_lock(inode->i_sb); | ||
241 | goto out; | 242 | goto out; |
242 | } else if (!dir->d_inode) { | 243 | } else if (!dir->d_inode) { |
243 | err = 0; | 244 | err = 0; |
245 | reiserfs_write_lock(inode->i_sb); | ||
244 | goto out_dir; | 246 | goto out_dir; |
245 | } | 247 | } |
246 | 248 | ||
247 | 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 | |||
248 | buf.xadir = dir; | 253 | buf.xadir = dir; |
249 | err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); | 254 | err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); |
250 | while ((err == 0 || err == -ENOSPC) && buf.count) { | 255 | while ((err == 0 || err == -ENOSPC) && buf.count) { |
@@ -283,8 +288,9 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
283 | err = journal_begin(&th, inode->i_sb, blocks); | 288 | err = journal_begin(&th, inode->i_sb, blocks); |
284 | if (!err) { | 289 | if (!err) { |
285 | int jerror; | 290 | int jerror; |
286 | mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, | 291 | reiserfs_mutex_lock_nested_safe( |
287 | I_MUTEX_XATTR); | 292 | &dir->d_parent->d_inode->i_mutex, |
293 | I_MUTEX_XATTR, inode->i_sb); | ||
288 | err = action(dir, data); | 294 | err = action(dir, data); |
289 | jerror = journal_end(&th, inode->i_sb, blocks); | 295 | jerror = journal_end(&th, inode->i_sb, blocks); |
290 | mutex_unlock(&dir->d_parent->d_inode->i_mutex); | 296 | mutex_unlock(&dir->d_parent->d_inode->i_mutex); |
@@ -443,7 +449,9 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) | |||
443 | } | 449 | } |
444 | 450 | ||
445 | if (dentry->d_inode) { | 451 | if (dentry->d_inode) { |
452 | reiserfs_write_lock(inode->i_sb); | ||
446 | err = xattr_unlink(xadir->d_inode, dentry); | 453 | err = xattr_unlink(xadir->d_inode, dentry); |
454 | reiserfs_write_unlock(inode->i_sb); | ||
447 | update_ctime(inode); | 455 | update_ctime(inode); |
448 | } | 456 | } |
449 | 457 | ||
@@ -477,15 +485,24 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
477 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 485 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
478 | return -EOPNOTSUPP; | 486 | return -EOPNOTSUPP; |
479 | 487 | ||
480 | if (!buffer) | 488 | reiserfs_write_unlock(inode->i_sb); |
481 | 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 | } | ||
482 | 495 | ||
483 | dentry = xattr_lookup(inode, name, flags); | 496 | dentry = xattr_lookup(inode, name, flags); |
484 | if (IS_ERR(dentry)) | 497 | if (IS_ERR(dentry)) { |
498 | reiserfs_write_lock(inode->i_sb); | ||
485 | return PTR_ERR(dentry); | 499 | return PTR_ERR(dentry); |
500 | } | ||
486 | 501 | ||
487 | down_write(&REISERFS_I(inode)->i_xattr_sem); | 502 | down_write(&REISERFS_I(inode)->i_xattr_sem); |
488 | 503 | ||
504 | reiserfs_write_lock(inode->i_sb); | ||
505 | |||
489 | xahash = xattr_hash(buffer, buffer_size); | 506 | xahash = xattr_hash(buffer, buffer_size); |
490 | while (buffer_pos < buffer_size || buffer_pos == 0) { | 507 | while (buffer_pos < buffer_size || buffer_pos == 0) { |
491 | size_t chunk; | 508 | size_t chunk; |
@@ -537,11 +554,15 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
537 | if (!err && new_size < i_size_read(dentry->d_inode)) { | 554 | if (!err && new_size < i_size_read(dentry->d_inode)) { |
538 | struct iattr newattrs = { | 555 | struct iattr newattrs = { |
539 | .ia_ctime = current_fs_time(inode->i_sb), | 556 | .ia_ctime = current_fs_time(inode->i_sb), |
540 | .ia_size = buffer_size, | 557 | .ia_size = new_size, |
541 | .ia_valid = ATTR_SIZE | ATTR_CTIME, | 558 | .ia_valid = ATTR_SIZE | ATTR_CTIME, |
542 | }; | 559 | }; |
560 | |||
561 | reiserfs_write_unlock(inode->i_sb); | ||
543 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); | 562 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); |
544 | 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 | |||
545 | err = reiserfs_setattr(dentry, &newattrs); | 566 | err = reiserfs_setattr(dentry, &newattrs); |
546 | up_write(&dentry->d_inode->i_alloc_sem); | 567 | up_write(&dentry->d_inode->i_alloc_sem); |
547 | mutex_unlock(&dentry->d_inode->i_mutex); | 568 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -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) |
@@ -980,8 +993,7 @@ int reiserfs_lookup_privroot(struct super_block *s) | |||
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 |