diff options
| author | Jeff Mahoney <jeffm@suse.com> | 2009-05-01 12:11:12 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-05-09 10:49:38 -0400 |
| commit | 5a6059c358d3b3004cb6b8562e3b049b1f8564f9 (patch) | |
| tree | 3c0d0bfabc7545963c0d618afbe4bd483b7c6166 | |
| parent | 67e55205ec55cc7899f1d783f217961596798419 (diff) | |
reiserfs: Expand i_mutex to enclose lookup_one_len
2.6.30-rc3 introduced some sanity checks in the VFS code to avoid NFS
bugs by ensuring that lookup_one_len is always called under i_mutex.
This patch expands the i_mutex locking to enclose lookup_one_len. This was
always required, but not not enforced in the reiserfs code since it
does locking around the xattr interactions with the xattr_sem.
This is obvious enough, and it survived an overnight 50 thread ACL test.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/reiserfs/xattr.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index f83f52bae390..31a3dbb120e1 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -120,25 +120,20 @@ static struct dentry *lookup_or_create_dir(struct dentry *parent, | |||
| 120 | struct dentry *dentry; | 120 | struct dentry *dentry; |
| 121 | BUG_ON(!parent); | 121 | BUG_ON(!parent); |
| 122 | 122 | ||
| 123 | mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_XATTR); | ||
| 123 | dentry = lookup_one_len(name, parent, strlen(name)); | 124 | dentry = lookup_one_len(name, parent, strlen(name)); |
| 124 | if (IS_ERR(dentry)) | 125 | if (!IS_ERR(dentry) && !dentry->d_inode) { |
| 125 | return dentry; | ||
| 126 | else if (!dentry->d_inode) { | ||
| 127 | int err = -ENODATA; | 126 | int err = -ENODATA; |
| 128 | 127 | ||
| 129 | if (xattr_may_create(flags)) { | 128 | if (xattr_may_create(flags)) |
| 130 | mutex_lock_nested(&parent->d_inode->i_mutex, | ||
| 131 | I_MUTEX_XATTR); | ||
| 132 | err = xattr_mkdir(parent->d_inode, dentry, 0700); | 129 | err = xattr_mkdir(parent->d_inode, dentry, 0700); |
| 133 | mutex_unlock(&parent->d_inode->i_mutex); | ||
| 134 | } | ||
| 135 | 130 | ||
| 136 | if (err) { | 131 | if (err) { |
| 137 | dput(dentry); | 132 | dput(dentry); |
| 138 | dentry = ERR_PTR(err); | 133 | dentry = ERR_PTR(err); |
| 139 | } | 134 | } |
| 140 | } | 135 | } |
| 141 | 136 | mutex_unlock(&parent->d_inode->i_mutex); | |
| 142 | return dentry; | 137 | return dentry; |
| 143 | } | 138 | } |
| 144 | 139 | ||
| @@ -184,6 +179,7 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset, | |||
| 184 | { | 179 | { |
| 185 | struct reiserfs_dentry_buf *dbuf = buf; | 180 | struct reiserfs_dentry_buf *dbuf = buf; |
| 186 | struct dentry *dentry; | 181 | struct dentry *dentry; |
| 182 | WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex)); | ||
| 187 | 183 | ||
| 188 | if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) | 184 | if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) |
| 189 | return -ENOSPC; | 185 | return -ENOSPC; |
| @@ -349,6 +345,7 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name, | |||
| 349 | if (IS_ERR(xadir)) | 345 | if (IS_ERR(xadir)) |
| 350 | return ERR_CAST(xadir); | 346 | return ERR_CAST(xadir); |
| 351 | 347 | ||
| 348 | mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
| 352 | xafile = lookup_one_len(name, xadir, strlen(name)); | 349 | xafile = lookup_one_len(name, xadir, strlen(name)); |
| 353 | if (IS_ERR(xafile)) { | 350 | if (IS_ERR(xafile)) { |
| 354 | err = PTR_ERR(xafile); | 351 | err = PTR_ERR(xafile); |
| @@ -360,18 +357,15 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name, | |||
| 360 | 357 | ||
| 361 | if (!xafile->d_inode) { | 358 | if (!xafile->d_inode) { |
| 362 | err = -ENODATA; | 359 | err = -ENODATA; |
| 363 | if (xattr_may_create(flags)) { | 360 | if (xattr_may_create(flags)) |
| 364 | mutex_lock_nested(&xadir->d_inode->i_mutex, | ||
| 365 | I_MUTEX_XATTR); | ||
| 366 | err = xattr_create(xadir->d_inode, xafile, | 361 | err = xattr_create(xadir->d_inode, xafile, |
| 367 | 0700|S_IFREG); | 362 | 0700|S_IFREG); |
| 368 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
| 369 | } | ||
| 370 | } | 363 | } |
| 371 | 364 | ||
| 372 | if (err) | 365 | if (err) |
| 373 | dput(xafile); | 366 | dput(xafile); |
| 374 | out: | 367 | out: |
| 368 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
| 375 | dput(xadir); | 369 | dput(xadir); |
| 376 | if (err) | 370 | if (err) |
| 377 | return ERR_PTR(err); | 371 | return ERR_PTR(err); |
| @@ -435,6 +429,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) | |||
| 435 | if (IS_ERR(xadir)) | 429 | if (IS_ERR(xadir)) |
| 436 | return PTR_ERR(xadir); | 430 | return PTR_ERR(xadir); |
| 437 | 431 | ||
| 432 | mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
| 438 | dentry = lookup_one_len(name, xadir, strlen(name)); | 433 | dentry = lookup_one_len(name, xadir, strlen(name)); |
| 439 | if (IS_ERR(dentry)) { | 434 | if (IS_ERR(dentry)) { |
| 440 | err = PTR_ERR(dentry); | 435 | err = PTR_ERR(dentry); |
| @@ -442,14 +437,13 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) | |||
| 442 | } | 437 | } |
| 443 | 438 | ||
| 444 | if (dentry->d_inode) { | 439 | if (dentry->d_inode) { |
| 445 | mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); | ||
| 446 | err = xattr_unlink(xadir->d_inode, dentry); | 440 | err = xattr_unlink(xadir->d_inode, dentry); |
| 447 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
| 448 | update_ctime(inode); | 441 | update_ctime(inode); |
| 449 | } | 442 | } |
| 450 | 443 | ||
| 451 | dput(dentry); | 444 | dput(dentry); |
| 452 | out_dput: | 445 | out_dput: |
| 446 | mutex_unlock(&xadir->d_inode->i_mutex); | ||
| 453 | dput(xadir); | 447 | dput(xadir); |
| 454 | return err; | 448 | return err; |
| 455 | } | 449 | } |
| @@ -906,9 +900,9 @@ static int create_privroot(struct dentry *dentry) | |||
| 906 | { | 900 | { |
| 907 | int err; | 901 | int err; |
| 908 | struct inode *inode = dentry->d_parent->d_inode; | 902 | struct inode *inode = dentry->d_parent->d_inode; |
| 909 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); | 903 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); |
| 904 | |||
| 910 | err = xattr_mkdir(inode, dentry, 0700); | 905 | err = xattr_mkdir(inode, dentry, 0700); |
| 911 | mutex_unlock(&inode->i_mutex); | ||
| 912 | if (err) { | 906 | if (err) { |
| 913 | dput(dentry); | 907 | dput(dentry); |
| 914 | dentry = NULL; | 908 | dentry = NULL; |
| @@ -980,6 +974,7 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
| 980 | /* If we don't have the privroot located yet - go find it */ | 974 | /* If we don't have the privroot located yet - go find it */ |
| 981 | if (!REISERFS_SB(s)->priv_root) { | 975 | if (!REISERFS_SB(s)->priv_root) { |
| 982 | struct dentry *dentry; | 976 | struct dentry *dentry; |
| 977 | mutex_lock_nested(&s->s_root->d_inode->i_mutex, I_MUTEX_CHILD); | ||
| 983 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, | 978 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, |
| 984 | strlen(PRIVROOT_NAME)); | 979 | strlen(PRIVROOT_NAME)); |
| 985 | if (!IS_ERR(dentry)) { | 980 | if (!IS_ERR(dentry)) { |
| @@ -993,6 +988,7 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
| 993 | } | 988 | } |
| 994 | } else | 989 | } else |
| 995 | err = PTR_ERR(dentry); | 990 | err = PTR_ERR(dentry); |
| 991 | mutex_unlock(&s->s_root->d_inode->i_mutex); | ||
| 996 | 992 | ||
| 997 | if (!err && dentry) { | 993 | if (!err && dentry) { |
| 998 | s->s_root->d_op = &xattr_lookup_poison_ops; | 994 | s->s_root->d_op = &xattr_lookup_poison_ops; |
