diff options
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/xattr.c | 262 |
1 files changed, 135 insertions, 127 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index f9bcdd5750f7..57920a4df7a4 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -44,100 +44,123 @@ | |||
44 | #include <net/checksum.h> | 44 | #include <net/checksum.h> |
45 | #include <linux/smp_lock.h> | 45 | #include <linux/smp_lock.h> |
46 | #include <linux/stat.h> | 46 | #include <linux/stat.h> |
47 | #include <linux/quotaops.h> | ||
47 | 48 | ||
48 | #define FL_READONLY 128 | ||
49 | #define FL_DIR_SEM_HELD 256 | ||
50 | #define PRIVROOT_NAME ".reiserfs_priv" | 49 | #define PRIVROOT_NAME ".reiserfs_priv" |
51 | #define XAROOT_NAME "xattrs" | 50 | #define XAROOT_NAME "xattrs" |
52 | 51 | ||
53 | /* Returns the dentry referring to the root of the extended attribute | 52 | /* Helpers for inode ops. We do this so that we don't have all the VFS |
54 | * directory tree. If it has already been retrieved, it is used. If it | 53 | * overhead and also for proper i_mutex annotation. |
55 | * hasn't been created and the flags indicate creation is allowed, we | 54 | * dir->i_mutex must be held for all of them. */ |
56 | * attempt to create it. On error, we return a pointer-encoded error. | 55 | static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) |
57 | */ | ||
58 | static struct dentry *get_xa_root(struct super_block *sb, int flags) | ||
59 | { | 56 | { |
60 | struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); | 57 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
61 | struct dentry *xaroot; | 58 | DQUOT_INIT(dir); |
59 | return dir->i_op->create(dir, dentry, mode, NULL); | ||
60 | } | ||
62 | 61 | ||
63 | /* This needs to be created at mount-time */ | 62 | static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
64 | if (!privroot) | 63 | { |
65 | return ERR_PTR(-ENODATA); | 64 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
65 | DQUOT_INIT(dir); | ||
66 | return dir->i_op->mkdir(dir, dentry, mode); | ||
67 | } | ||
66 | 68 | ||
67 | mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR); | 69 | /* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr |
68 | if (REISERFS_SB(sb)->xattr_root) { | 70 | * mutation ops aren't called during rename or splace, which are the |
69 | xaroot = dget(REISERFS_SB(sb)->xattr_root); | 71 | * only other users of I_MUTEX_CHILD. It violates the ordering, but that's |
70 | goto out; | 72 | * better than allocating another subclass just for this code. */ |
71 | } | 73 | static int xattr_unlink(struct inode *dir, struct dentry *dentry) |
74 | { | ||
75 | int error; | ||
76 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | ||
77 | DQUOT_INIT(dir); | ||
72 | 78 | ||
73 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | 79 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); |
74 | if (IS_ERR(xaroot)) { | 80 | error = dir->i_op->unlink(dir, dentry); |
75 | goto out; | 81 | mutex_unlock(&dentry->d_inode->i_mutex); |
76 | } else if (!xaroot->d_inode) { | 82 | |
83 | if (!error) | ||
84 | d_delete(dentry); | ||
85 | return error; | ||
86 | } | ||
87 | |||
88 | static int xattr_rmdir(struct inode *dir, struct dentry *dentry) | ||
89 | { | ||
90 | int error; | ||
91 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | ||
92 | DQUOT_INIT(dir); | ||
93 | |||
94 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | ||
95 | dentry_unhash(dentry); | ||
96 | error = dir->i_op->rmdir(dir, dentry); | ||
97 | if (!error) | ||
98 | dentry->d_inode->i_flags |= S_DEAD; | ||
99 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
100 | if (!error) | ||
101 | d_delete(dentry); | ||
102 | dput(dentry); | ||
103 | |||
104 | return error; | ||
105 | } | ||
106 | |||
107 | |||
108 | #define xattr_may_create(flags) (!flags || flags & XATTR_CREATE) | ||
109 | |||
110 | /* Returns and possibly creates the xattr dir. */ | ||
111 | static struct dentry *lookup_or_create_dir(struct dentry *parent, | ||
112 | const char *name, int flags) | ||
113 | { | ||
114 | struct dentry *dentry; | ||
115 | BUG_ON(!parent); | ||
116 | |||
117 | dentry = lookup_one_len(name, parent, strlen(name)); | ||
118 | if (IS_ERR(dentry)) | ||
119 | return dentry; | ||
120 | else if (!dentry->d_inode) { | ||
77 | int err = -ENODATA; | 121 | int err = -ENODATA; |
78 | if (flags == 0 || flags & XATTR_CREATE) | 122 | |
79 | err = privroot->d_inode->i_op->mkdir(privroot->d_inode, | 123 | if (xattr_may_create(flags)) { |
80 | xaroot, 0700); | 124 | mutex_lock_nested(&parent->d_inode->i_mutex, |
125 | I_MUTEX_XATTR); | ||
126 | err = xattr_mkdir(parent->d_inode, dentry, 0700); | ||
127 | mutex_unlock(&parent->d_inode->i_mutex); | ||
128 | } | ||
129 | |||
81 | if (err) { | 130 | if (err) { |
82 | dput(xaroot); | 131 | dput(dentry); |
83 | xaroot = ERR_PTR(err); | 132 | dentry = ERR_PTR(err); |
84 | goto out; | ||
85 | } | 133 | } |
86 | } | 134 | } |
87 | REISERFS_SB(sb)->xattr_root = dget(xaroot); | ||
88 | 135 | ||
89 | out: | 136 | return dentry; |
90 | mutex_unlock(&privroot->d_inode->i_mutex); | 137 | } |
91 | dput(privroot); | 138 | |
92 | return xaroot; | 139 | static struct dentry *open_xa_root(struct super_block *sb, int flags) |
140 | { | ||
141 | struct dentry *privroot = REISERFS_SB(sb)->priv_root; | ||
142 | if (!privroot) | ||
143 | return ERR_PTR(-ENODATA); | ||
144 | return lookup_or_create_dir(privroot, XAROOT_NAME, flags); | ||
93 | } | 145 | } |
94 | 146 | ||
95 | /* Opens the directory corresponding to the inode's extended attribute store. | ||
96 | * If flags allow, the tree to the directory may be created. If creation is | ||
97 | * prohibited, -ENODATA is returned. */ | ||
98 | static struct dentry *open_xa_dir(const struct inode *inode, int flags) | 147 | static struct dentry *open_xa_dir(const struct inode *inode, int flags) |
99 | { | 148 | { |
100 | struct dentry *xaroot, *xadir; | 149 | struct dentry *xaroot, *xadir; |
101 | char namebuf[17]; | 150 | char namebuf[17]; |
102 | 151 | ||
103 | xaroot = get_xa_root(inode->i_sb, flags); | 152 | xaroot = open_xa_root(inode->i_sb, flags); |
104 | if (IS_ERR(xaroot)) | 153 | if (IS_ERR(xaroot)) |
105 | return xaroot; | 154 | return xaroot; |
106 | 155 | ||
107 | /* ok, we have xaroot open */ | ||
108 | snprintf(namebuf, sizeof(namebuf), "%X.%X", | 156 | snprintf(namebuf, sizeof(namebuf), "%X.%X", |
109 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), | 157 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), |
110 | inode->i_generation); | 158 | inode->i_generation); |
111 | xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf)); | ||
112 | if (IS_ERR(xadir)) { | ||
113 | dput(xaroot); | ||
114 | return xadir; | ||
115 | } | ||
116 | |||
117 | if (!xadir->d_inode) { | ||
118 | int err; | ||
119 | if (flags == 0 || flags & XATTR_CREATE) { | ||
120 | /* Although there is nothing else trying to create this directory, | ||
121 | * another directory with the same hash may be created, so we need | ||
122 | * to protect against that */ | ||
123 | err = | ||
124 | xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir, | ||
125 | 0700); | ||
126 | if (err) { | ||
127 | dput(xaroot); | ||
128 | dput(xadir); | ||
129 | return ERR_PTR(err); | ||
130 | } | ||
131 | } | ||
132 | if (!xadir->d_inode) { | ||
133 | dput(xaroot); | ||
134 | dput(xadir); | ||
135 | return ERR_PTR(-ENODATA); | ||
136 | } | ||
137 | } | ||
138 | 159 | ||
160 | xadir = lookup_or_create_dir(xaroot, namebuf, flags); | ||
139 | dput(xaroot); | 161 | dput(xaroot); |
140 | return xadir; | 162 | return xadir; |
163 | |||
141 | } | 164 | } |
142 | 165 | ||
143 | /* | 166 | /* |
@@ -302,13 +325,11 @@ static | |||
302 | int xattr_readdir(struct inode *inode, filldir_t filler, void *buf) | 325 | int xattr_readdir(struct inode *inode, filldir_t filler, void *buf) |
303 | { | 326 | { |
304 | int res = -ENOENT; | 327 | int res = -ENOENT; |
305 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); | ||
306 | if (!IS_DEADDIR(inode)) { | 328 | if (!IS_DEADDIR(inode)) { |
307 | lock_kernel(); | 329 | lock_kernel(); |
308 | res = __xattr_readdir(inode, buf, filler); | 330 | res = __xattr_readdir(inode, buf, filler); |
309 | unlock_kernel(); | 331 | unlock_kernel(); |
310 | } | 332 | } |
311 | mutex_unlock(&inode->i_mutex); | ||
312 | return res; | 333 | return res; |
313 | } | 334 | } |
314 | 335 | ||
@@ -345,9 +366,7 @@ __reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen) | |||
345 | return -EIO; | 366 | return -EIO; |
346 | } | 367 | } |
347 | 368 | ||
348 | err = dir->i_op->unlink(dir, dentry); | 369 | err = xattr_unlink(dir, dentry); |
349 | if (!err) | ||
350 | d_delete(dentry); | ||
351 | 370 | ||
352 | out_file: | 371 | out_file: |
353 | dput(dentry); | 372 | dput(dentry); |
@@ -381,7 +400,7 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
381 | return 0; | 400 | return 0; |
382 | 401 | ||
383 | reiserfs_read_lock_xattrs(inode->i_sb); | 402 | reiserfs_read_lock_xattrs(inode->i_sb); |
384 | dir = open_xa_dir(inode, FL_READONLY); | 403 | dir = open_xa_dir(inode, XATTR_REPLACE); |
385 | reiserfs_read_unlock_xattrs(inode->i_sb); | 404 | reiserfs_read_unlock_xattrs(inode->i_sb); |
386 | if (IS_ERR(dir)) { | 405 | if (IS_ERR(dir)) { |
387 | err = PTR_ERR(dir); | 406 | err = PTR_ERR(dir); |
@@ -391,25 +410,25 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
391 | return 0; | 410 | return 0; |
392 | } | 411 | } |
393 | 412 | ||
394 | lock_kernel(); | 413 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); |
395 | err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); | 414 | err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); |
396 | if (err) { | 415 | mutex_unlock(&dir->d_inode->i_mutex); |
397 | unlock_kernel(); | 416 | if (err) |
398 | goto out_dir; | 417 | goto out_dir; |
399 | } | ||
400 | 418 | ||
401 | /* Leftovers besides . and .. -- that's not good. */ | 419 | /* Leftovers besides . and .. -- that's not good. */ |
402 | if (dir->d_inode->i_nlink <= 2) { | 420 | if (dir->d_inode->i_nlink <= 2) { |
403 | root = get_xa_root(inode->i_sb, XATTR_REPLACE); | 421 | root = open_xa_root(inode->i_sb, XATTR_REPLACE); |
404 | reiserfs_write_lock_xattrs(inode->i_sb); | 422 | reiserfs_write_lock_xattrs(inode->i_sb); |
405 | err = vfs_rmdir(root->d_inode, dir); | 423 | mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_XATTR); |
424 | err = xattr_rmdir(root->d_inode, dir); | ||
425 | mutex_unlock(&root->d_inode->i_mutex); | ||
406 | reiserfs_write_unlock_xattrs(inode->i_sb); | 426 | reiserfs_write_unlock_xattrs(inode->i_sb); |
407 | dput(root); | 427 | dput(root); |
408 | } else { | 428 | } else { |
409 | reiserfs_warning(inode->i_sb, "jdm-20006", | 429 | reiserfs_warning(inode->i_sb, "jdm-20006", |
410 | "Couldn't remove all entries in directory"); | 430 | "Couldn't remove all entries in directory"); |
411 | } | 431 | } |
412 | unlock_kernel(); | ||
413 | 432 | ||
414 | out_dir: | 433 | out_dir: |
415 | dput(dir); | 434 | dput(dir); |
@@ -445,8 +464,11 @@ reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, | |||
445 | return -ENODATA; | 464 | return -ENODATA; |
446 | } | 465 | } |
447 | 466 | ||
448 | if (!S_ISDIR(xafile->d_inode->i_mode)) | 467 | if (!S_ISDIR(xafile->d_inode->i_mode)) { |
468 | mutex_lock_nested(&xafile->d_inode->i_mutex, I_MUTEX_CHILD); | ||
449 | err = notify_change(xafile, attrs); | 469 | err = notify_change(xafile, attrs); |
470 | mutex_unlock(&xafile->d_inode->i_mutex); | ||
471 | } | ||
450 | dput(xafile); | 472 | dput(xafile); |
451 | 473 | ||
452 | return err; | 474 | return err; |
@@ -464,38 +486,31 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | |||
464 | return 0; | 486 | return 0; |
465 | 487 | ||
466 | reiserfs_read_lock_xattrs(inode->i_sb); | 488 | reiserfs_read_lock_xattrs(inode->i_sb); |
467 | dir = open_xa_dir(inode, FL_READONLY); | 489 | dir = open_xa_dir(inode, XATTR_REPLACE); |
468 | reiserfs_read_unlock_xattrs(inode->i_sb); | 490 | reiserfs_read_unlock_xattrs(inode->i_sb); |
469 | if (IS_ERR(dir)) { | 491 | if (IS_ERR(dir)) { |
470 | if (PTR_ERR(dir) != -ENODATA) | 492 | if (PTR_ERR(dir) != -ENODATA) |
471 | err = PTR_ERR(dir); | 493 | err = PTR_ERR(dir); |
472 | goto out; | 494 | goto out; |
473 | } else if (!dir->d_inode) { | 495 | } else if (!dir->d_inode) |
474 | dput(dir); | 496 | goto out_dir; |
475 | goto out; | ||
476 | } | ||
477 | |||
478 | lock_kernel(); | ||
479 | 497 | ||
480 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | 498 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); |
481 | buf.xadir = dir; | 499 | buf.xadir = dir; |
482 | buf.attrs = attrs; | 500 | buf.attrs = attrs; |
483 | buf.inode = inode; | 501 | buf.inode = inode; |
484 | 502 | ||
503 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
485 | err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); | 504 | err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); |
486 | if (err) { | ||
487 | unlock_kernel(); | ||
488 | goto out_dir; | ||
489 | } | ||
490 | 505 | ||
491 | err = notify_change(dir, attrs); | 506 | if (!err) |
492 | unlock_kernel(); | 507 | err = notify_change(dir, attrs); |
508 | mutex_unlock(&dir->d_inode->i_mutex); | ||
493 | 509 | ||
510 | attrs->ia_valid = ia_valid; | ||
494 | out_dir: | 511 | out_dir: |
495 | dput(dir); | 512 | dput(dir); |
496 | |||
497 | out: | 513 | out: |
498 | attrs->ia_valid = ia_valid; | ||
499 | return err; | 514 | return err; |
500 | } | 515 | } |
501 | 516 | ||
@@ -513,47 +528,35 @@ static struct dentry *get_xa_file_dentry(const struct inode *inode, | |||
513 | int err = 0; | 528 | int err = 0; |
514 | 529 | ||
515 | xadir = open_xa_dir(inode, flags); | 530 | xadir = open_xa_dir(inode, flags); |
516 | if (IS_ERR(xadir)) { | 531 | if (IS_ERR(xadir)) |
517 | return ERR_CAST(xadir); | 532 | return ERR_CAST(xadir); |
518 | } else if (xadir && !xadir->d_inode) { | ||
519 | dput(xadir); | ||
520 | return ERR_PTR(-ENODATA); | ||
521 | } | ||
522 | 533 | ||
523 | xafile = lookup_one_len(name, xadir, strlen(name)); | 534 | xafile = lookup_one_len(name, xadir, strlen(name)); |
524 | if (IS_ERR(xafile)) { | 535 | if (IS_ERR(xafile)) { |
525 | dput(xadir); | 536 | err = PTR_ERR(xafile); |
526 | return ERR_CAST(xafile); | 537 | goto out; |
527 | } | 538 | } |
528 | 539 | ||
529 | if (xafile->d_inode) { /* file exists */ | 540 | if (xafile->d_inode && (flags & XATTR_CREATE)) |
530 | if (flags & XATTR_CREATE) { | 541 | err = -EEXIST; |
531 | err = -EEXIST; | ||
532 | dput(xafile); | ||
533 | goto out; | ||
534 | } | ||
535 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | ||
536 | goto out; | ||
537 | } else { | ||
538 | /* inode->i_mutex is down, so nothing else can try to create | ||
539 | * the same xattr */ | ||
540 | err = xadir->d_inode->i_op->create(xadir->d_inode, xafile, | ||
541 | 0700 | S_IFREG, NULL); | ||
542 | 542 | ||
543 | if (err) { | 543 | if (!xafile->d_inode) { |
544 | dput(xafile); | 544 | err = -ENODATA; |
545 | goto out; | 545 | if (xattr_may_create(flags)) { |
546 | mutex_lock_nested(&xadir->d_inode->i_mutex, | ||
547 | I_MUTEX_XATTR); | ||
548 | err = xattr_create(xadir->d_inode, xafile, | ||
549 | 0700|S_IFREG); | ||
550 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
546 | } | 551 | } |
547 | } | 552 | } |
548 | 553 | ||
554 | if (err) | ||
555 | dput(xafile); | ||
549 | out: | 556 | out: |
550 | dput(xadir); | 557 | dput(xadir); |
551 | if (err) | 558 | if (err) |
552 | xafile = ERR_PTR(err); | 559 | return ERR_PTR(err); |
553 | else if (!xafile->d_inode) { | ||
554 | dput(xafile); | ||
555 | xafile = ERR_PTR(-ENODATA); | ||
556 | } | ||
557 | return xafile; | 560 | return xafile; |
558 | } | 561 | } |
559 | 562 | ||
@@ -633,6 +636,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
633 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | 636 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; |
634 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); | 637 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); |
635 | err = notify_change(dentry, &newattrs); | 638 | err = notify_change(dentry, &newattrs); |
639 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
636 | if (err) | 640 | if (err) |
637 | goto out_filp; | 641 | goto out_filp; |
638 | 642 | ||
@@ -692,7 +696,6 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
692 | } | 696 | } |
693 | 697 | ||
694 | out_filp: | 698 | out_filp: |
695 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
696 | dput(dentry); | 699 | dput(dentry); |
697 | 700 | ||
698 | out: | 701 | out: |
@@ -722,7 +725,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
722 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 725 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
723 | return -EOPNOTSUPP; | 726 | return -EOPNOTSUPP; |
724 | 727 | ||
725 | dentry = get_xa_file_dentry(inode, name, FL_READONLY); | 728 | dentry = get_xa_file_dentry(inode, name, XATTR_REPLACE); |
726 | if (IS_ERR(dentry)) { | 729 | if (IS_ERR(dentry)) { |
727 | err = PTR_ERR(dentry); | 730 | err = PTR_ERR(dentry); |
728 | goto out; | 731 | goto out; |
@@ -806,13 +809,15 @@ int reiserfs_xattr_del(struct inode *inode, const char *name) | |||
806 | struct dentry *dir; | 809 | struct dentry *dir; |
807 | int err; | 810 | int err; |
808 | 811 | ||
809 | dir = open_xa_dir(inode, FL_READONLY); | 812 | dir = open_xa_dir(inode, XATTR_REPLACE); |
810 | if (IS_ERR(dir)) { | 813 | if (IS_ERR(dir)) { |
811 | err = PTR_ERR(dir); | 814 | err = PTR_ERR(dir); |
812 | goto out; | 815 | goto out; |
813 | } | 816 | } |
814 | 817 | ||
818 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
815 | err = __reiserfs_xattr_del(dir, name, strlen(name)); | 819 | err = __reiserfs_xattr_del(dir, name, strlen(name)); |
820 | mutex_unlock(&dir->d_inode->i_mutex); | ||
816 | dput(dir); | 821 | dput(dir); |
817 | 822 | ||
818 | if (!err) { | 823 | if (!err) { |
@@ -826,6 +831,7 @@ int reiserfs_xattr_del(struct inode *inode, const char *name) | |||
826 | 831 | ||
827 | /* Actual operations that are exported to VFS-land */ | 832 | /* Actual operations that are exported to VFS-land */ |
828 | 833 | ||
834 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *); | ||
829 | /* | 835 | /* |
830 | * Inode operation getxattr() | 836 | * Inode operation getxattr() |
831 | * Preliminary locking: we down dentry->d_inode->i_mutex | 837 | * Preliminary locking: we down dentry->d_inode->i_mutex |
@@ -978,7 +984,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
978 | 984 | ||
979 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 985 | reiserfs_read_lock_xattr_i(dentry->d_inode); |
980 | reiserfs_read_lock_xattrs(dentry->d_sb); | 986 | reiserfs_read_lock_xattrs(dentry->d_sb); |
981 | dir = open_xa_dir(dentry->d_inode, FL_READONLY); | 987 | dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); |
982 | reiserfs_read_unlock_xattrs(dentry->d_sb); | 988 | reiserfs_read_unlock_xattrs(dentry->d_sb); |
983 | if (IS_ERR(dir)) { | 989 | if (IS_ERR(dir)) { |
984 | err = PTR_ERR(dir); | 990 | err = PTR_ERR(dir); |
@@ -994,7 +1000,9 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
994 | 1000 | ||
995 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; | 1001 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; |
996 | 1002 | ||
1003 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
997 | err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf); | 1004 | err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf); |
1005 | mutex_unlock(&dir->d_inode->i_mutex); | ||
998 | if (err) | 1006 | if (err) |
999 | goto out_dir; | 1007 | goto out_dir; |
1000 | 1008 | ||
@@ -1146,7 +1154,7 @@ static int create_privroot(struct dentry *dentry) | |||
1146 | int err; | 1154 | int err; |
1147 | struct inode *inode = dentry->d_parent->d_inode; | 1155 | struct inode *inode = dentry->d_parent->d_inode; |
1148 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); | 1156 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); |
1149 | err = inode->i_op->mkdir(inode, dentry, 0700); | 1157 | err = xattr_mkdir(inode, dentry, 0700); |
1150 | mutex_unlock(&inode->i_mutex); | 1158 | mutex_unlock(&inode->i_mutex); |
1151 | if (err) { | 1159 | if (err) { |
1152 | dput(dentry); | 1160 | dput(dentry); |