aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-08-24 20:44:21 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-09-14 01:18:27 -0400
commitb10ab4c337a600456ed2d9daea0331016f7cdeeb (patch)
tree6e85b1faea80835b5dcab78bf66d51b529711ada /fs
parentae635c0bbd6c10aa62bf5149c6f41add59fbf4d2 (diff)
kill-the-bkl/reiserfs: fix recursive reiserfs lock in reiserfs_mkdir()
reiserfs_mkdir() acquires the reiserfs lock, assuming it has been called from the dir inodes callbacks, without the lock held. But it can also be called from other internal sites such as reiserfs_xattr_init() which already holds the lock. This recursive locking leads to further wrong assumptions. For example, later calls to reiserfs_mutex_lock_safe() won't actually unlock the reiserfs lock the time we acquire a given mutex, creating unexpected lock inversions. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Chris Mason <chris.mason@oracle.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Alexander Beregalov <a.beregalov@gmail.com> Cc: Laurent Riffard <laurent.riffard@free.fr>
Diffstat (limited to 'fs')
-rw-r--r--fs/reiserfs/namei.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index b3973c9f0bf1..e296ff72a6cc 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -732,6 +732,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
732 struct inode *inode; 732 struct inode *inode;
733 struct reiserfs_transaction_handle th; 733 struct reiserfs_transaction_handle th;
734 struct reiserfs_security_handle security; 734 struct reiserfs_security_handle security;
735 int lock_depth;
735 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 736 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
736 int jbegin_count = 737 int jbegin_count =
737 JOURNAL_PER_BALANCE_CNT * 3 + 738 JOURNAL_PER_BALANCE_CNT * 3 +
@@ -755,7 +756,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
755 return retval; 756 return retval;
756 } 757 }
757 jbegin_count += retval; 758 jbegin_count += retval;
758 reiserfs_write_lock(dir->i_sb); 759 lock_depth = reiserfs_write_lock_once(dir->i_sb);
759 760
760 retval = journal_begin(&th, dir->i_sb, jbegin_count); 761 retval = journal_begin(&th, dir->i_sb, jbegin_count);
761 if (retval) { 762 if (retval) {
@@ -805,8 +806,8 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
805 d_instantiate(dentry, inode); 806 d_instantiate(dentry, inode);
806 unlock_new_inode(inode); 807 unlock_new_inode(inode);
807 retval = journal_end(&th, dir->i_sb, jbegin_count); 808 retval = journal_end(&th, dir->i_sb, jbegin_count);
808 out_failed: 809out_failed:
809 reiserfs_write_unlock(dir->i_sb); 810 reiserfs_write_unlock_once(dir->i_sb, lock_depth);
810 return retval; 811 return retval;
811} 812}
812 813