Merge tag 'linux-kselftest-5.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / fs / fs-writeback.c
index 36855c1f8dafdce42422e0b31ce806d6d9973979..e41cbe8e81b9b439863fe8404d91943b908c2a01 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * fs/fs-writeback.c
  *
@@ -523,8 +524,6 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
 
        isw->inode = inode;
 
-       atomic_inc(&isw_nr_in_flight);
-
        /*
         * In addition to synchronizing among switchers, I_WB_SWITCH tells
         * the RCU protected stat update paths to grab the i_page
@@ -532,6 +531,9 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
         * Let's continue after I_WB_SWITCH is guaranteed to be visible.
         */
        call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
+
+       atomic_inc(&isw_nr_in_flight);
+
        goto out_unlock;
 
 out_free:
@@ -901,7 +903,11 @@ restart:
 void cgroup_writeback_umount(void)
 {
        if (atomic_read(&isw_nr_in_flight)) {
-               synchronize_rcu();
+               /*
+                * Use rcu_barrier() to wait for all pending callbacks to
+                * ensure that all in-flight wb switches are in the workqueue.
+                */
+               rcu_barrier();
                flush_workqueue(isw_wq);
        }
 }