Commit 45d28b097280a78893ce25a5d0db41e6a2717853

Authored by Linus Torvalds

Merge branch 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/gi…

…t/frederic/random-tracing

* 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing:
  reiserfs: Safely acquire i_mutex from xattr_rmdir
  reiserfs: Safely acquire i_mutex from reiserfs_for_each_xattr
  reiserfs: Fix journal mutex <-> inode mutex lock inversion
  reiserfs: Fix unwanted recursive reiserfs lock in reiserfs_unlink()
  reiserfs: Relax lock before open xattr dir in reiserfs_xattr_set_handle()
  reiserfs: Relax reiserfs lock while freeing the journal
  reiserfs: Fix reiserfs lock <-> i_mutex dependency inversion on xattr
  reiserfs: Warn on lock relax if taken recursively
  reiserfs: Fix reiserfs lock <-> i_xattr_sem dependency inversion
  reiserfs: Fix remaining in-reclaim-fs <-> reclaim-fs-on locking inversion
  reiserfs: Fix reiserfs lock <-> inode mutex dependency inversion
  reiserfs: Fix reiserfs lock and journal lock inversion dependency
  reiserfs: Fix possible recursive lock

Showing 7 changed files Side-by-side Diff

fs/reiserfs/bitmap.c
... ... @@ -1277,7 +1277,10 @@
1277 1277 struct reiserfs_bitmap_info *bitmap;
1278 1278 unsigned int bmap_nr = reiserfs_bmap_count(sb);
1279 1279  
  1280 + /* Avoid lock recursion in fault case */
  1281 + reiserfs_write_unlock(sb);
1280 1282 bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
  1283 + reiserfs_write_lock(sb);
1281 1284 if (bitmap == NULL)
1282 1285 return -ENOMEM;
1283 1286  
... ... @@ -31,11 +31,12 @@
31 31 JOURNAL_PER_BALANCE_CNT * 2 +
32 32 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
33 33 struct reiserfs_transaction_handle th;
  34 + int depth;
34 35 int err;
35 36  
36 37 truncate_inode_pages(&inode->i_data, 0);
37 38  
38   - reiserfs_write_lock(inode->i_sb);
  39 + depth = reiserfs_write_lock_once(inode->i_sb);
39 40  
40 41 /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
41 42 if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
... ... @@ -74,7 +75,7 @@
74 75 out:
75 76 clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */
76 77 inode->i_blocks = 0;
77   - reiserfs_write_unlock(inode->i_sb);
  78 + reiserfs_write_unlock_once(inode->i_sb, depth);
78 79 }
79 80  
80 81 static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
fs/reiserfs/journal.c
... ... @@ -2009,10 +2009,11 @@
2009 2009 destroy_workqueue(commit_wq);
2010 2010 commit_wq = NULL;
2011 2011 }
2012   - reiserfs_write_lock(sb);
2013 2012  
2014 2013 free_journal_ram(sb);
2015 2014  
  2015 + reiserfs_write_lock(sb);
  2016 +
2016 2017 return 0;
2017 2018 }
2018 2019  
2019 2020  
2020 2021  
... ... @@ -2758,11 +2759,18 @@
2758 2759 struct reiserfs_journal *journal;
2759 2760 struct reiserfs_journal_list *jl;
2760 2761 char b[BDEVNAME_SIZE];
  2762 + int ret;
2761 2763  
  2764 + /*
  2765 + * Unlock here to avoid various RECLAIM-FS-ON <-> IN-RECLAIM-FS
  2766 + * dependency inversion warnings.
  2767 + */
  2768 + reiserfs_write_unlock(sb);
2762 2769 journal = SB_JOURNAL(sb) = vmalloc(sizeof(struct reiserfs_journal));
2763 2770 if (!journal) {
2764 2771 reiserfs_warning(sb, "journal-1256",
2765 2772 "unable to get memory for journal structure");
  2773 + reiserfs_write_lock(sb);
2766 2774 return 1;
2767 2775 }
2768 2776 memset(journal, 0, sizeof(struct reiserfs_journal));
2769 2777  
... ... @@ -2771,10 +2779,12 @@
2771 2779 INIT_LIST_HEAD(&journal->j_working_list);
2772 2780 INIT_LIST_HEAD(&journal->j_journal_list);
2773 2781 journal->j_persistent_trans = 0;
2774   - if (reiserfs_allocate_list_bitmaps(sb,
2775   - journal->j_list_bitmap,
2776   - reiserfs_bmap_count(sb)))
  2782 + ret = reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
  2783 + reiserfs_bmap_count(sb));
  2784 + reiserfs_write_lock(sb);
  2785 + if (ret)
2777 2786 goto free_and_return;
  2787 +
2778 2788 allocate_bitmap_nodes(sb);
2779 2789  
2780 2790 /* reserved for journal area support */
... ... @@ -86,4 +86,13 @@
86 86 reiserfs_panic(sb, "%s called without kernel lock held %d",
87 87 caller);
88 88 }
  89 +
  90 +#ifdef CONFIG_REISERFS_CHECK
  91 +void reiserfs_lock_check_recursive(struct super_block *sb)
  92 +{
  93 + struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
  94 +
  95 + WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");
  96 +}
  97 +#endif
... ... @@ -921,6 +921,7 @@
921 921 struct reiserfs_transaction_handle th;
922 922 int jbegin_count;
923 923 unsigned long savelink;
  924 + int depth;
924 925  
925 926 inode = dentry->d_inode;
926 927  
... ... @@ -932,7 +933,7 @@
932 933 JOURNAL_PER_BALANCE_CNT * 2 + 2 +
933 934 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
934 935  
935   - reiserfs_write_lock(dir->i_sb);
  936 + depth = reiserfs_write_lock_once(dir->i_sb);
936 937 retval = journal_begin(&th, dir->i_sb, jbegin_count);
937 938 if (retval)
938 939 goto out_unlink;
... ... @@ -993,7 +994,7 @@
993 994  
994 995 retval = journal_end(&th, dir->i_sb, jbegin_count);
995 996 reiserfs_check_path(&path);
996   - reiserfs_write_unlock(dir->i_sb);
  997 + reiserfs_write_unlock_once(dir->i_sb, depth);
997 998 return retval;
998 999  
999 1000 end_unlink:
... ... @@ -1003,7 +1004,7 @@
1003 1004 if (err)
1004 1005 retval = err;
1005 1006 out_unlink:
1006   - reiserfs_write_unlock(dir->i_sb);
  1007 + reiserfs_write_unlock_once(dir->i_sb, depth);
1007 1008 return retval;
1008 1009 }
1009 1010  
... ... @@ -83,7 +83,8 @@
83 83 BUG_ON(!mutex_is_locked(&dir->i_mutex));
84 84 vfs_dq_init(dir);
85 85  
86   - mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
  86 + reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
  87 + I_MUTEX_CHILD, dir->i_sb);
87 88 error = dir->i_op->unlink(dir, dentry);
88 89 mutex_unlock(&dentry->d_inode->i_mutex);
89 90  
... ... @@ -98,7 +99,8 @@
98 99 BUG_ON(!mutex_is_locked(&dir->i_mutex));
99 100 vfs_dq_init(dir);
100 101  
101   - mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
  102 + reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
  103 + I_MUTEX_CHILD, dir->i_sb);
102 104 dentry_unhash(dentry);
103 105 error = dir->i_op->rmdir(dir, dentry);
104 106 if (!error)
105 107  
106 108  
107 109  
... ... @@ -235,16 +237,22 @@
235 237 if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
236 238 return 0;
237 239  
  240 + reiserfs_write_unlock(inode->i_sb);
238 241 dir = open_xa_dir(inode, XATTR_REPLACE);
239 242 if (IS_ERR(dir)) {
240 243 err = PTR_ERR(dir);
  244 + reiserfs_write_lock(inode->i_sb);
241 245 goto out;
242 246 } else if (!dir->d_inode) {
243 247 err = 0;
  248 + reiserfs_write_lock(inode->i_sb);
244 249 goto out_dir;
245 250 }
246 251  
247 252 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
  253 +
  254 + reiserfs_write_lock(inode->i_sb);
  255 +
248 256 buf.xadir = dir;
249 257 err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos);
250 258 while ((err == 0 || err == -ENOSPC) && buf.count) {
... ... @@ -283,8 +291,9 @@
283 291 err = journal_begin(&th, inode->i_sb, blocks);
284 292 if (!err) {
285 293 int jerror;
286   - mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
287   - I_MUTEX_XATTR);
  294 + reiserfs_mutex_lock_nested_safe(
  295 + &dir->d_parent->d_inode->i_mutex,
  296 + I_MUTEX_XATTR, inode->i_sb);
288 297 err = action(dir, data);
289 298 jerror = journal_end(&th, inode->i_sb, blocks);
290 299 mutex_unlock(&dir->d_parent->d_inode->i_mutex);
291 300  
292 301  
293 302  
... ... @@ -480,11 +489,16 @@
480 489 if (!buffer)
481 490 return lookup_and_delete_xattr(inode, name);
482 491  
  492 + reiserfs_write_unlock(inode->i_sb);
483 493 dentry = xattr_lookup(inode, name, flags);
484   - if (IS_ERR(dentry))
  494 + if (IS_ERR(dentry)) {
  495 + reiserfs_write_lock(inode->i_sb);
485 496 return PTR_ERR(dentry);
  497 + }
486 498  
487   - down_write(&REISERFS_I(inode)->i_xattr_sem);
  499 + down_read(&REISERFS_I(inode)->i_xattr_sem);
  500 +
  501 + reiserfs_write_lock(inode->i_sb);
488 502  
489 503 xahash = xattr_hash(buffer, buffer_size);
490 504 while (buffer_pos < buffer_size || buffer_pos == 0) {
include/linux/reiserfs_fs.h
... ... @@ -62,6 +62,12 @@
62 62 int reiserfs_write_lock_once(struct super_block *s);
63 63 void reiserfs_write_unlock_once(struct super_block *s, int lock_depth);
64 64  
  65 +#ifdef CONFIG_REISERFS_CHECK
  66 +void reiserfs_lock_check_recursive(struct super_block *s);
  67 +#else
  68 +static inline void reiserfs_lock_check_recursive(struct super_block *s) { }
  69 +#endif
  70 +
65 71 /*
66 72 * Several mutexes depend on the write lock.
67 73 * However sometimes we want to relax the write lock while we hold
68 74  
... ... @@ -92,8 +98,28 @@
92 98 static inline void reiserfs_mutex_lock_safe(struct mutex *m,
93 99 struct super_block *s)
94 100 {
  101 + reiserfs_lock_check_recursive(s);
95 102 reiserfs_write_unlock(s);
96 103 mutex_lock(m);
  104 + reiserfs_write_lock(s);
  105 +}
  106 +
  107 +static inline void
  108 +reiserfs_mutex_lock_nested_safe(struct mutex *m, unsigned int subclass,
  109 + struct super_block *s)
  110 +{
  111 + reiserfs_lock_check_recursive(s);
  112 + reiserfs_write_unlock(s);
  113 + mutex_lock_nested(m, subclass);
  114 + reiserfs_write_lock(s);
  115 +}
  116 +
  117 +static inline void
  118 +reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s)
  119 +{
  120 + reiserfs_lock_check_recursive(s);
  121 + reiserfs_write_unlock(s);
  122 + down_read(sem);
97 123 reiserfs_write_lock(s);
98 124 }
99 125