cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
* [Cluster-devel] [GFS2 PATCH 01/12] gfs2: Fix loop in gfs2_rbm_find (v2)
@ 2019-05-07 20:31 Andreas Gruenbacher
  2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 02/12] gfs2: Fix lru_count going negative Andreas Gruenbacher
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: Andreas Gruenbacher @ 2019-05-07 20:31 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Fix the resource group wrap-around logic in gfs2_rbm_find that commit
e579ed4f44 broke.  The bug can lead to unnecessary repeated scanning of the
same bitmaps; there is a risk that future changes will turn this into an
endless loop.

This is an updated version of commit 2d29f6b96d ("gfs2: Fix loop in
gfs2_rbm_find") which ended up being reverted because it introduced a
performance regression in iozone (see commit e74c98ca2d).  Changes since v1:

 - Simplify the wrap-around logic.

 - Handle the case where each resource group only has a single bitmap block
   (small filesystem).

 - Update rd_extfail_pt whenever we scan the entire bitmap, even when we don't
   start the scan at the very beginning of the bitmap.

Fixes: e579ed4f446e ("GFS2: Introduce rbm field bii")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/gfs2/rgrp.c | 54 +++++++++++++++++++++++---------------------------
 1 file changed, 25 insertions(+), 29 deletions(-)

diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 17a8d3b43990..52a4f340a867 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1729,25 +1729,22 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
 static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
 			 const struct gfs2_inode *ip, bool nowrap)
 {
+	bool scan_from_start = rbm->bii == 0 && rbm->offset == 0;
 	struct buffer_head *bh;
-	int initial_bii;
-	u32 initial_offset;
-	int first_bii = rbm->bii;
-	u32 first_offset = rbm->offset;
+	int last_bii;
 	u32 offset;
 	u8 *buffer;
-	int n = 0;
-	int iters = rbm->rgd->rd_length;
+	bool wrapped = false;
 	int ret;
 	struct gfs2_bitmap *bi;
 	struct gfs2_extent maxext = { .rbm.rgd = rbm->rgd, };
 
-	/* If we are not starting at the beginning of a bitmap, then we
-	 * need to add one to the bitmap count to ensure that we search
-	 * the starting bitmap twice.
+	/*
+	 * Determine the last bitmap to search.  If we're not starting at the
+	 * beginning of a bitmap, we need to search that bitmap twice to scan
+	 * the entire resource group.
 	 */
-	if (rbm->offset != 0)
-		iters++;
+	last_bii = rbm->bii - (rbm->offset == 0);
 
 	while(1) {
 		bi = rbm_bi(rbm);
@@ -1761,47 +1758,46 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
 		WARN_ON(!buffer_uptodate(bh));
 		if (state != GFS2_BLKST_UNLINKED && bi->bi_clone)
 			buffer = bi->bi_clone + bi->bi_offset;
-		initial_offset = rbm->offset;
 		offset = gfs2_bitfit(buffer, bi->bi_bytes, rbm->offset, state);
-		if (offset == BFITNOENT)
-			goto bitmap_full;
+		if (offset == BFITNOENT) {
+			if (state == GFS2_BLKST_FREE && rbm->offset == 0)
+				set_bit(GBF_FULL, &bi->bi_flags);
+			goto next_bitmap;
+		}
 		rbm->offset = offset;
 		if (ip == NULL)
 			return 0;
 
-		initial_bii = rbm->bii;
 		ret = gfs2_reservation_check_and_update(rbm, ip,
 							minext ? *minext : 0,
 							&maxext);
 		if (ret == 0)
 			return 0;
-		if (ret > 0) {
-			n += (rbm->bii - initial_bii);
+		if (ret > 0)
 			goto next_iter;
-		}
 		if (ret == -E2BIG) {
 			rbm->bii = 0;
 			rbm->offset = 0;
-			n += (rbm->bii - initial_bii);
 			goto res_covered_end_of_rgrp;
 		}
 		return ret;
 
-bitmap_full:	/* Mark bitmap as full and fall through */
-		if ((state == GFS2_BLKST_FREE) && initial_offset == 0)
-			set_bit(GBF_FULL, &bi->bi_flags);
-
 next_bitmap:	/* Find next bitmap in the rgrp */
 		rbm->offset = 0;
 		rbm->bii++;
 		if (rbm->bii == rbm->rgd->rd_length)
 			rbm->bii = 0;
 res_covered_end_of_rgrp:
-		if ((rbm->bii == 0) && nowrap)
-			break;
-		n++;
+		if (rbm->bii == 0) {
+			if (wrapped)
+				break;
+			wrapped = true;
+			if (nowrap)
+				break;
+		}
 next_iter:
-		if (n >= iters)
+		/* Have we scanned the entire resource group? */
+		if (wrapped && rbm->bii > last_bii)
 			break;
 	}
 
@@ -1811,8 +1807,8 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
 	/* If the extent was too small, and it's smaller than the smallest
 	   to have failed before, remember for future reference that it's
 	   useless to search this rgrp again for this amount or more. */
-	if ((first_offset == 0) && (first_bii == 0) &&
-	    (*minext < rbm->rgd->rd_extfail_pt))
+	if (wrapped && (scan_from_start || rbm->bii > last_bii) &&
+	    *minext < rbm->rgd->rd_extfail_pt)
 		rbm->rgd->rd_extfail_pt = *minext;
 
 	/* If the maximum extent we found is big enough to fulfill the
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-06-11  8:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-07 20:31 [Cluster-devel] [GFS2 PATCH 01/12] gfs2: Fix loop in gfs2_rbm_find (v2) Andreas Gruenbacher
2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 02/12] gfs2: Fix lru_count going negative Andreas Gruenbacher
2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 03/12] gfs2: clean_journal improperly set sd_log_flush_head Andreas Gruenbacher
2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 04/12] gfs2: Fix occasional glock use-after-free Andreas Gruenbacher
2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 05/12] gfs2: Replace gl_revokes with a GLF flag Andreas Gruenbacher
2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 06/12] gfs2: Remove misleading comments in gfs2_evict_inode Andreas Gruenbacher
2019-05-07 20:31 ` [Cluster-devel] [GFS2 PATCH 07/12] gfs2: Remove unnecessary extern declarations Andreas Gruenbacher
2019-05-07 20:32 ` [Cluster-devel] [GFS2 PATCH 08/12] gfs2: Rename sd_log_le_{revoke, ordered} Andreas Gruenbacher
2019-05-07 20:32 ` [Cluster-devel] [GFS2 PATCH 09/12] gfs2: Rename gfs2_trans_{add_unrevoke => remove_revoke} Andreas Gruenbacher
2019-05-07 20:32 ` [Cluster-devel] [GFS2 PATCH 10/12] gfs2: fix race between gfs2_freeze_func and unmount Andreas Gruenbacher
2019-05-07 20:32 ` [Cluster-devel] [GFS2 PATCH 11/12] gfs2: Fix iomap write page reclaim deadlock Andreas Gruenbacher
2019-06-07 16:19   ` Ross Lagerwall
2019-06-08 12:16     ` Andreas Gruenbacher
2019-06-11  8:29       ` Ross Lagerwall
2019-05-07 20:32 ` [Cluster-devel] [GFS2 PATCH 12/12] gfs2: read journal in large chunks Andreas Gruenbacher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).