reiserfs: Fix remaining in-reclaim-fs <-> reclaim-fs-on locking inversion
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / reiserfs / journal.c
index 5cd600b..a059879 100644 (file)
@@ -537,42 +537,6 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table,
        journal_hash(table, cn->sb, cn->blocknr) = cn;
 }
 
-/*
- * Several mutexes depend on the write lock.
- * However sometimes we want to relax the write lock while we hold
- * these mutexes, according to the release/reacquire on schedule()
- * properties of the Bkl that were used.
- * Reiserfs performances and locking were based on this scheme.
- * Now that the write lock is a mutex and not the bkl anymore, doing so
- * may result in a deadlock:
- *
- * A acquire write_lock
- * A acquire j_commit_mutex
- * A release write_lock and wait for something
- * B acquire write_lock
- * B can't acquire j_commit_mutex and sleep
- * A can't acquire write lock anymore
- * deadlock
- *
- * What we do here is avoiding such deadlock by playing the same game
- * than the Bkl: if we can't acquire a mutex that depends on the write lock,
- * we release the write lock, wait a bit and then retry.
- *
- * The mutexes concerned by this hack are:
- * - The commit mutex of a journal list
- * - The flush mutex
- * - The journal lock
- */
-static inline void reiserfs_mutex_lock_safe(struct mutex *m,
-                              struct super_block *s)
-{
-       while (!mutex_trylock(m)) {
-               reiserfs_write_unlock(s);
-               schedule();
-               reiserfs_write_lock(s);
-       }
-}
-
 /* lock the current transaction */
 static inline void lock_journal(struct super_block *sb)
 {
@@ -1120,8 +1084,11 @@ static int flush_commit_list(struct super_block *s,
                    SB_ONDISK_JOURNAL_SIZE(s);
                tbh = journal_find_get_block(s, bn);
                if (tbh) {
-                       if (buffer_dirty(tbh))
-                           ll_rw_block(WRITE, 1, &tbh) ;
+                       if (buffer_dirty(tbh)) {
+                           reiserfs_write_unlock(s);
+                           ll_rw_block(WRITE, 1, &tbh);
+                           reiserfs_write_lock(s);
+                       }
                        put_bh(tbh) ;
                }
        }
@@ -2791,11 +2758,18 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        struct reiserfs_journal *journal;
        struct reiserfs_journal_list *jl;
        char b[BDEVNAME_SIZE];
+       int ret;
 
+       /*
+        * Unlock here to avoid various RECLAIM-FS-ON <-> IN-RECLAIM-FS
+        * dependency inversion warnings.
+        */
+       reiserfs_write_unlock(sb);
        journal = SB_JOURNAL(sb) = vmalloc(sizeof(struct reiserfs_journal));
        if (!journal) {
                reiserfs_warning(sb, "journal-1256",
                                 "unable to get memory for journal structure");
+               reiserfs_write_lock(sb);
                return 1;
        }
        memset(journal, 0, sizeof(struct reiserfs_journal));
@@ -2804,10 +2778,12 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        INIT_LIST_HEAD(&journal->j_working_list);
        INIT_LIST_HEAD(&journal->j_journal_list);
        journal->j_persistent_trans = 0;
-       if (reiserfs_allocate_list_bitmaps(sb,
-                                          journal->j_list_bitmap,
-                                          reiserfs_bmap_count(sb)))
+       ret = reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
+                                          reiserfs_bmap_count(sb));
+       reiserfs_write_lock(sb);
+       if (ret)
                goto free_and_return;
+
        allocate_bitmap_nodes(sb);
 
        /* reserved for journal area support */
@@ -2834,11 +2810,27 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
                goto free_and_return;
        }
 
+       /*
+        * We need to unlock here to avoid creating the following
+        * dependency:
+        * reiserfs_lock -> sysfs_mutex
+        * Because the reiserfs mmap path creates the following dependency:
+        * mm->mmap -> reiserfs_lock, hence we have
+        * mm->mmap -> reiserfs_lock ->sysfs_mutex
+        * This would ends up in a circular dependency with sysfs readdir path
+        * which does sysfs_mutex -> mm->mmap_sem
+        * This is fine because the reiserfs lock is useless in mount path,
+        * at least until we call journal_begin. We keep it for paranoid
+        * reasons.
+        */
+       reiserfs_write_unlock(sb);
        if (journal_init_dev(sb, journal, j_dev_name) != 0) {
+               reiserfs_write_lock(sb);
                reiserfs_warning(sb, "sh-462",
                                 "unable to initialize jornal device");
                goto free_and_return;
        }
+       reiserfs_write_lock(sb);
 
        rs = SB_DISK_SUPER_BLOCK(sb);
 
@@ -2950,8 +2942,11 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
        }
 
        reiserfs_mounted_fs_count++;
-       if (reiserfs_mounted_fs_count <= 1)
+       if (reiserfs_mounted_fs_count <= 1) {
+               reiserfs_write_unlock(sb);
                commit_wq = create_workqueue("reiserfs");
+               reiserfs_write_lock(sb);
+       }
 
        INIT_DELAYED_WORK(&journal->j_work, flush_async_commits);
        journal->j_work_sb = sb;