summaryrefslogtreecommitdiff
path: root/fs/gfs2
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2019-11-13 13:53:42 -0600
committerBob Peterson <rpeterso@redhat.com>2020-02-27 07:53:18 -0600
commitb1676cbb11153b5bf4dd9e6c99869b284fb8160e (patch)
tree3b251c62d5d8b780319d7004d50d453bf730f0d9 /fs/gfs2
parent9ff78289356af640941bbb0dd3f46af2063f0046 (diff)
gfs2: Withdraw in gfs2_ail1_flush if write_cache_pages fails
Before this patch, function gfs2_ail1_start_one would return any errors it received from write_cache_pages (except -EBUSY) but it did not withdraw. Since function gfs2_ail1_flush just checks for the bad return code and loops, the loop might potentially never end. This patch adds some logic to allow it to exit the loop and withdraw properly when errors are received from write_cache_pages. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/log.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index c37f81470792..ed80ef8e5c33 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -96,6 +96,7 @@ __acquires(&sdp->sd_ail_lock)
struct address_space *mapping;
struct gfs2_bufdata *bd, *s;
struct buffer_head *bh;
+ int ret = 0;
list_for_each_entry_safe_reverse(bd, s, &tr->tr_ail1_list, bd_ail_st_list) {
bh = bd->bd_bh;
@@ -128,14 +129,14 @@ __acquires(&sdp->sd_ail_lock)
if (!mapping)
continue;
spin_unlock(&sdp->sd_ail_lock);
- generic_writepages(mapping, wbc);
+ ret = generic_writepages(mapping, wbc);
spin_lock(&sdp->sd_ail_lock);
- if (wbc->nr_to_write <= 0)
+ if (ret || wbc->nr_to_write <= 0)
break;
- return 1;
+ return -EBUSY;
}
- return 0;
+ return ret;
}
@@ -153,6 +154,7 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
struct list_head *head = &sdp->sd_ail1_list;
struct gfs2_trans *tr;
struct blk_plug plug;
+ int ret = 0;
trace_gfs2_ail_flush(sdp, wbc, 1);
blk_start_plug(&plug);
@@ -161,12 +163,16 @@ restart:
list_for_each_entry_reverse(tr, head, tr_list) {
if (wbc->nr_to_write <= 0)
break;
- if (gfs2_ail1_start_one(sdp, wbc, tr) && !gfs2_withdrawn(sdp))
- goto restart;
+ ret = gfs2_ail1_start_one(sdp, wbc, tr);
+ if (ret) {
+ if (ret == -EBUSY)
+ goto restart;
+ break;
+ }
}
spin_unlock(&sdp->sd_ail_lock);
blk_finish_plug(&plug);
- if (test_bit(SDF_WITHDRAWING, &sdp->sd_flags))
+ if (ret)
gfs2_withdraw(sdp);
trace_gfs2_ail_flush(sdp, wbc, 0);
}