gfs2-utils: RHEL7 - libgfs2: Refactor block allocation functions

Andrew Price andyp at fedoraproject.org
Mon Sep 8 17:32:40 UTC 2014


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=81226a0bb89b5b926dd47481c2314202783812c0
Commit:        81226a0bb89b5b926dd47481c2314202783812c0
Parent:        cd71fe5817f52f598fa2b5254a39417199e57014
Author:        Andrew Price <anprice at redhat.com>
AuthorDate:    Wed Jan 22 21:33:51 2014 +0000
Committer:     Andrew Price <anprice at redhat.com>
CommitterDate: Thu Jul 24 16:55:32 2014 +0100

libgfs2: Refactor block allocation functions

Split the part of blk_alloc_in_rg which finds a free block out into a
separate find_free_block function. This will allow callers to have more
control over where blocks are allocated in future.

Also combine the old blk_alloc_i and lgfs2_dinode_alloc and meta_alloc
functions into a single block_alloc function which now acts as a backing
function for lgfs2_dinode_alloc and meta_alloc, which is renamed
lgfs2_meta_alloc. An exit() call from blk_alloc_i has been pushed down
into its callers and replaced with error returns where possible.

Signed-off-by: Andrew Price <anprice at redhat.com>
---
 gfs2/fsck/metawalk.c   |    7 ++-
 gfs2/libgfs2/fs_ops.c  |  119 +++++++++++++++++++++++------------------------
 gfs2/libgfs2/gfs1.c    |    6 ++-
 gfs2/libgfs2/libgfs2.h |    2 +-
 4 files changed, 70 insertions(+), 64 deletions(-)

diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 6c0e02b..3190681 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1973,7 +1973,12 @@ int write_new_leaf(struct gfs2_inode *dip, int start_lindex, int num_copies,
 	}
 
 	/* allocate and write out a new leaf block */
-	*bn = meta_alloc(dip);
+	if (lgfs2_meta_alloc(dip, bn)) {
+		log_err( _("Error: allocation failed while fixing directory leaf "
+			   "pointers.\n"));
+		free(padbuf);
+		return -1;
+	}
 	fsck_blockmap_set(dip, *bn, _("directory leaf"), gfs2_leaf_blk);
 	log_err(_("A new directory leaf was allocated at block %lld "
 		  "(0x%llx) to fill the %d (0x%x) pointer gap %s the existing "
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 9889e22..f59f014 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -112,24 +112,16 @@ void inode_put(struct gfs2_inode **ip_in)
 	*ip_in = NULL; /* make sure the memory isn't accessed again */
 }
 
-static int blk_alloc_in_rg(struct gfs2_sbd *sdp, unsigned state, struct rgrp_tree *rgd, uint64_t *blkno)
+static uint64_t find_free_block(struct rgrp_tree *rgd)
 {
-	unsigned int release = 0;
-	unsigned int bm;
-	int error = -1;
+	unsigned bm;
+	uint64_t blkno = 0;
 
 	if (rgd == NULL || rgd->rg.rg_free == 0) {
 		errno = ENOSPC;
-		return -1;
-	}
-
-	if (rgd->bh[0] == NULL) {
-		if (gfs2_rgrp_read(sdp, rgd))
-			return -1;
-		release = 1;
+		return 0;
 	}
 
-	*blkno = 0;
 	for (bm = 0; bm < rgd->ri.ri_length; bm++) {
 		unsigned long blk = 0;
 		struct gfs2_bitmap *bits = &rgd->bits[bm];
@@ -137,17 +129,20 @@ static int blk_alloc_in_rg(struct gfs2_sbd *sdp, unsigned state, struct rgrp_tre
 		blk = gfs2_bitfit((unsigned char *)rgd->bh[bm]->b_data + bits->bi_offset,
 		                  bits->bi_len, blk, GFS2_BLKST_FREE);
 		if (blk != BFITNOENT) {
-			*blkno = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0;
+			blkno = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0;
 			break;
 		}
 	}
+	return blkno;
+}
 
-	if (*blkno == 0)
-		goto out;
+static int blk_alloc_in_rg(struct gfs2_sbd *sdp, unsigned state, struct rgrp_tree *rgd, uint64_t blkno)
+{
+	if (blkno == 0)
+		return -1;
 
-	error = gfs2_set_bitmap(sdp, *blkno, state);
-	if (error)
-		goto out;
+	if (gfs2_set_bitmap(sdp, blkno, state))
+		return -1;
 
 	if (state == GFS2_BLKST_DINODE)
 		rgd->rg.rg_dinodes++;
@@ -159,50 +154,22 @@ static int blk_alloc_in_rg(struct gfs2_sbd *sdp, unsigned state, struct rgrp_tre
 		gfs2_rgrp_out_bh(&rgd->rg, rgd->bh[0]);
 
 	sdp->blks_alloced++;
-out:
-	if (release)
-		gfs2_rgrp_relse(rgd);
-	return error;
-}
-
-/**
- * Do not use this function, it's only here until we can kill it.
- * Use blk_alloc_in_rg directly instead.
- */
-static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
-{
-	int ret;
-	uint64_t blkno = 0;
-	struct osi_node *n = NULL;
-	for (n = osi_first(&sdp->rgtree); n; n = osi_next(n)) {
-		if (((struct rgrp_tree *)n)->rg.rg_free)
-			break;
-	}
-	ret = blk_alloc_in_rg(sdp, type, (struct rgrp_tree *)n, &blkno);
-	if (ret != 0) /* Do what the old blk_alloc_i did */
-		exit(1);
-	return blkno;
-}
-
-uint64_t meta_alloc(struct gfs2_inode *ip)
-{
-	uint64_t x;
-	x = blk_alloc_i(ip->i_sbd, GFS2_BLKST_USED);
-	ip->i_di.di_goal_meta = x;
-	bmodified(ip->i_bh);
-	return x;
+	return 0;
 }
 
 /**
- * Allocate a dinode block in a bitmap. In order to plan ahead we look for a
- * resource group with blksreq free blocks but only allocate the one dinode block.
+ * Allocate a block in a bitmap. In order to plan ahead we look for a
+ * resource group with blksreq free blocks but only allocate the one block.
  * Returns 0 on success with the allocated block number in *blkno or non-zero otherwise.
  */
-int lgfs2_dinode_alloc(struct gfs2_sbd *sdp, const uint64_t blksreq, uint64_t *blkno)
+static int block_alloc(struct gfs2_sbd *sdp, const uint64_t blksreq, int state, uint64_t *blkno)
 {
 	int ret;
+	int release = 0;
 	struct rgrp_tree *rgt = NULL;
 	struct osi_node *n = NULL;
+	uint64_t bn = 0;
+
 	for (n = osi_first(&sdp->rgtree); n; n = osi_next(n)) {
 		rgt = (struct rgrp_tree *)n;
 		if (rgt->rg.rg_free >= blksreq)
@@ -211,10 +178,35 @@ int lgfs2_dinode_alloc(struct gfs2_sbd *sdp, const uint64_t blksreq, uint64_t *b
 	if (rgt == NULL)
 		return -1;
 
-	ret = blk_alloc_in_rg(sdp, GFS2_BLKST_DINODE, rgt, blkno);
+	if (rgt->bh[0] == NULL) {
+		if (gfs2_rgrp_read(sdp, rgt))
+			return -1;
+		release = 1;
+	}
+
+	bn = find_free_block(rgt);
+	ret = blk_alloc_in_rg(sdp, state, rgt, bn);
+	if (release)
+		gfs2_rgrp_relse(rgt);
+	*blkno = bn;
+	return ret;
+}
+
+int lgfs2_dinode_alloc(struct gfs2_sbd *sdp, const uint64_t blksreq, uint64_t *blkno)
+{
+	int ret = block_alloc(sdp, blksreq, GFS2_BLKST_DINODE, blkno);
 	if (ret == 0)
 		sdp->dinodes_alloced++;
+	return ret;
+}
 
+int lgfs2_meta_alloc(struct gfs2_inode *ip, uint64_t *blkno)
+{
+	int ret = block_alloc(ip->i_sbd, 1, GFS2_BLKST_USED, blkno);
+	if (ret == 0) {
+		ip->i_di.di_goal_meta = *blkno;
+		bmodified(ip->i_bh);
+	}
 	return ret;
 }
 
@@ -245,10 +237,11 @@ void unstuff_dinode(struct gfs2_inode *ip)
 	int isdir = S_ISDIR(ip->i_di.di_mode) || is_gfs_dir(&ip->i_di);
 
 	if (ip->i_di.di_size) {
+		if (lgfs2_meta_alloc(ip, &block))
+			exit(1);
 		if (isdir) {
 			struct gfs2_meta_header mh;
 
-			block = meta_alloc(ip);
 			bh = bget(sdp, block);
 			mh.mh_magic = GFS2_MAGIC;
 			mh.mh_type = GFS2_METATYPE_JD;
@@ -261,7 +254,6 @@ void unstuff_dinode(struct gfs2_inode *ip)
 
 			brelse(bh);
 		} else {
-			block = meta_alloc(ip);
 			bh = bget(sdp, block);
 
 			buffer_copy_tail(sdp, bh, 0,
@@ -325,7 +317,8 @@ void build_height(struct gfs2_inode *ip, int height)
 		if (new_block) {
 			struct gfs2_meta_header mh;
 
-			block = meta_alloc(ip);
+			if (lgfs2_meta_alloc(ip, &block))
+				exit(1);
 			bh = bget(sdp, block);
 			mh.mh_magic = GFS2_MAGIC;
 			mh.mh_type = GFS2_METATYPE_IN;
@@ -377,7 +370,8 @@ void lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
 	if (!create)
 		return;
 
-	*block = meta_alloc(ip);
+	if (lgfs2_meta_alloc(ip, block))
+		return;
 	*ptr = cpu_to_be64(*block);
 	bmodified(bh);
 	ip->i_di.di_blocks++;
@@ -853,7 +847,8 @@ void dir_split_leaf(struct gfs2_inode *dip, uint32_t start, uint64_t leaf_no,
 	int x, moved = FALSE;
 	int count;
 
-	bn = meta_alloc(dip);
+	if (lgfs2_meta_alloc(dip, &bn))
+		exit(1);
 	nbh = bget(dip->i_sbd, bn);
 	{
 		struct gfs2_meta_header mh;
@@ -1119,7 +1114,8 @@ restart:
 			} else {
 				struct gfs2_meta_header mh;
 
-				bn = meta_alloc(dip);
+				if (lgfs2_meta_alloc(dip, &bn))
+					exit(1);
 				nbh = bget(dip->i_sbd, bn);
 				mh.mh_magic = GFS2_MAGIC;
 				mh.mh_type = GFS2_METATYPE_LF;
@@ -1170,7 +1166,8 @@ static void dir_make_exhash(struct gfs2_inode *dip)
 	uint32_t x;
 	uint64_t *lp, bn;
 
-	bn = meta_alloc(dip);
+	if (lgfs2_meta_alloc(dip, &bn))
+		exit(1);
 	bh = bget(sdp, bn);
 	{
 		struct gfs2_meta_header mh;
diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c
index aee845a..c00d7be 100644
--- a/gfs2/libgfs2/gfs1.c
+++ b/gfs2/libgfs2/gfs1.c
@@ -57,7 +57,11 @@ void gfs1_lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
 	if (!create)
 		return;
 
-	*block = meta_alloc(ip);
+	if (lgfs2_meta_alloc(ip, block)) {
+		*block = 0;
+		return;
+	}
+
 	*ptr = cpu_to_be64(*block);
 	bmodified(bh);
 	ip->i_di.di_blocks++;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 9abe3b2..d044bc6 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -448,7 +448,7 @@ extern struct gfs2_inode *is_system_inode(struct gfs2_sbd *sdp,
 					  uint64_t block);
 extern void inode_put(struct gfs2_inode **ip);
 extern uint64_t data_alloc(struct gfs2_inode *ip);
-extern uint64_t meta_alloc(struct gfs2_inode *ip);
+extern int lgfs2_meta_alloc(struct gfs2_inode *ip, uint64_t *blkno);
 extern int lgfs2_dinode_alloc(struct gfs2_sbd *sdp, const uint64_t blksreq, uint64_t *blkno);
 extern int gfs2_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
 		      unsigned int size);


More information about the cluster-commits mailing list