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 /fs/reiserfs | |
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>
Diffstat (limited to 'fs/reiserfs')
-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; |