summary refs log tree commit diff
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2021-02-18 09:07:21 -0500
committerAndreas Gruenbacher <agruenba@redhat.com>2021-02-23 19:01:42 +0100
commit17d77684088510df84ff8285982d0eed52cd5890 (patch)
tree5107251c1bd18a06be6bd3675de7c627ff0ab5fb
parent803074ad77b91e270c1ce90793a924cdb4547162 (diff)
downloadlinux-17d77684088510df84ff8285982d0eed52cd5890.tar.gz
gfs2: Don't get stuck with I/O plugged in gfs2_ail1_flush
In gfs2_ail1_flush, we're using I/O plugging to give the block layer a
better chance of merging I/O requests.  If we're too aggressive here, we
can end up waiting on I/O to complete while still plugged.  Fix that in
a way similar to writeback_sb_inodes, except that we can't use
blk_flush_plug because blk_flush_plug_list is not exported.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
-rw-r--r--fs/gfs2/log.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index a6fbde9f609f..16937ebb2a3e 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -91,7 +91,7 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
 
 static int gfs2_ail1_start_one(struct gfs2_sbd *sdp,
 			       struct writeback_control *wbc,
-			       struct gfs2_trans *tr)
+			       struct gfs2_trans *tr, struct blk_plug *plug)
 __releases(&sdp->sd_ail_lock)
 __acquires(&sdp->sd_ail_lock)
 {
@@ -133,6 +133,11 @@ __acquires(&sdp->sd_ail_lock)
 			continue;
 		spin_unlock(&sdp->sd_ail_lock);
 		ret = generic_writepages(mapping, wbc);
+		if (need_resched()) {
+			blk_finish_plug(plug);
+			cond_resched();
+			blk_start_plug(plug);
+		}
 		spin_lock(&sdp->sd_ail_lock);
 		if (ret == -ENODATA) /* if a jdata write into a new hole */
 			ret = 0; /* ignore it */
@@ -207,7 +212,7 @@ restart:
 	list_for_each_entry_reverse(tr, head, tr_list) {
 		if (wbc->nr_to_write <= 0)
 			break;
-		ret = gfs2_ail1_start_one(sdp, wbc, tr);
+		ret = gfs2_ail1_start_one(sdp, wbc, tr, &plug);
 		if (ret) {
 			if (ret == -EBUSY)
 				goto restart;