Merge tag 'renesas-cleanup-for-v3.19' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / mm / backing-dev.c
index 12a992b..0ae0df5 100644 (file)
@@ -40,7 +40,7 @@ LIST_HEAD(bdi_list);
 /* bdi_wq serves all asynchronous writeback tasks */
 struct workqueue_struct *bdi_wq;
 
-void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)
+static void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)
 {
        if (wb1 < wb2) {
                spin_lock(&wb1->list_lock);
@@ -376,13 +376,7 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
        mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0);
        flush_delayed_work(&bdi->wb.dwork);
        WARN_ON(!list_empty(&bdi->work_list));
-
-       /*
-        * This shouldn't be necessary unless @bdi for some reason has
-        * unflushed dirty IO after work_list is drained.  Do it anyway
-        * just in case.
-        */
-       cancel_delayed_work_sync(&bdi->wb.dwork);
+       WARN_ON(delayed_work_pending(&bdi->wb.dwork));
 }
 
 /*
@@ -402,21 +396,15 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
 
 void bdi_unregister(struct backing_dev_info *bdi)
 {
-       struct device *dev = bdi->dev;
-
-       if (dev) {
+       if (bdi->dev) {
                bdi_set_min_ratio(bdi, 0);
                trace_writeback_bdi_unregister(bdi);
                bdi_prune_sb(bdi);
 
                bdi_wb_shutdown(bdi);
                bdi_debug_unregister(bdi);
-
-               spin_lock_bh(&bdi->wb_lock);
+               device_unregister(bdi->dev);
                bdi->dev = NULL;
-               spin_unlock_bh(&bdi->wb_lock);
-
-               device_unregister(dev);
        }
 }
 EXPORT_SYMBOL(bdi_unregister);
@@ -487,8 +475,17 @@ void bdi_destroy(struct backing_dev_info *bdi)
        int i;
 
        /*
-        * Splice our entries to the default_backing_dev_info, if this
-        * bdi disappears
+        * Splice our entries to the default_backing_dev_info.  This
+        * condition shouldn't happen.  @wb must be empty at this point and
+        * dirty inodes on it might cause other issues.  This workaround is
+        * added by ce5f8e779519 ("writeback: splice dirty inode entries to
+        * default bdi on bdi_destroy()") without root-causing the issue.
+        *
+        * http://lkml.kernel.org/g/1253038617-30204-11-git-send-email-jens.axboe@oracle.com
+        * http://thread.gmane.org/gmane.linux.file-systems/35341/focus=35350
+        *
+        * We should probably add WARN_ON() to find out whether it still
+        * happens and track it down if so.
         */
        if (bdi_has_dirty_io(bdi)) {
                struct bdi_writeback *dst = &default_backing_dev_info.wb;
@@ -503,12 +500,7 @@ void bdi_destroy(struct backing_dev_info *bdi)
 
        bdi_unregister(bdi);
 
-       /*
-        * If bdi_unregister() had already been called earlier, the dwork
-        * could still be pending because bdi_prune_sb() can race with the
-        * bdi_wakeup_thread_delayed() calls from __mark_inode_dirty().
-        */
-       cancel_delayed_work_sync(&bdi->wb.dwork);
+       WARN_ON(delayed_work_pending(&bdi->wb.dwork));
 
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
                percpu_counter_destroy(&bdi->bdi_stat[i]);