]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
gfs2: Withdraw in gfs2_ail1_flush if write_cache_pages fails
authorBob Peterson <rpeterso@redhat.com>
Wed, 13 Nov 2019 19:53:42 +0000 (13:53 -0600)
committerBob Peterson <rpeterso@redhat.com>
Thu, 27 Feb 2020 13:53:18 +0000 (07:53 -0600)
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>
fs/gfs2/log.c

index c37f81470792b084bbe70d124261e5d40acf0778..ed80ef8e5c33eed6b7202ec384dc8300afbcda36 100644 (file)
@@ -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);
 }