[Cluster-devel] [PATCH 1/5] libgfs2: Rework blk_alloc_i

Andrew Price anprice at redhat.com
Tue Feb 26 14:04:22 UTC 2013


blk_alloc_i previously chose any resource group with a free block and
assumed that the bitmaps were already available in the rgrp_tree. This
patch allows us to allocate blocks in a resource group with a given
number of free blocks in order to plan ahead and reads in the bitmap
data on demand. It also removes some exit()s from blk_alloc_i.

Signed-off-by: Andrew Price <anprice at redhat.com>
---
 gfs2/libgfs2/fs_ops.c  | 79 ++++++++++++++++++++++++++++++++++++++------------
 gfs2/libgfs2/libgfs2.h |  1 +
 2 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 3d027e8..b6c268d 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -116,32 +116,24 @@ void inode_put(struct gfs2_inode **ip_in)
 	*ip_in = NULL; /* make sure the memory isn't accessed again */
 }
 
-static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
+static int blk_alloc_in_rg(struct gfs2_sbd *sdp, unsigned int type, struct rgrp_tree *rl, uint64_t *blkno)
 {
-	struct osi_node *n, *next = NULL;
-	struct rgrp_tree *rl = NULL;
 	struct gfs2_rindex *ri;
 	struct gfs2_rgrp *rg;
 	unsigned int block, bn = 0, x = 0, y = 0;
 	unsigned int state;
 	struct gfs2_buffer_head *bh;
 
-	memset(&rg, 0, sizeof(rg));
-	for (n = osi_first(&sdp->rgtree); n; n = next) {
-		next = osi_next(n);
-		rl = (struct rgrp_tree *)n;
-		if (rl->rg.rg_free)
-			break;
+	if (rl == NULL || rl->rg.rg_free == 0) {
+		errno = ENOSPC;
+		return -1;
 	}
 
-	if (n == NULL) {
-		fprintf(stderr, "Not enough space available on device\n");
-		exit(1);
-	}
+	if (rl->bh[0] == NULL && gfs2_rgrp_read(sdp, rl) != 0)
+		return -1;
 
 	ri = &rl->ri;
 	rg = &rl->rg;
-
 	for (block = 0; block < ri->ri_length; block++) {
 		bh = rl->bh[block];
 		x = (block) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp);
@@ -157,7 +149,7 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
 
 	fprintf(stderr, "allocation is broken (1): %"PRIu64" %u\n",
 	    (uint64_t)rl->ri.ri_addr, rl->rg.rg_free);
-	exit(1);
+	return -1;
 
 found:
 	if (bn >= ri->ri_bitbytes * GFS2_NBBY) {
@@ -165,7 +157,7 @@ found:
 		    " (0x%" PRIx64 ") Free:%u\n",
 		    bn, ri->ri_bitbytes * GFS2_NBBY, (uint64_t)rl->ri.ri_addr,
 		    (uint64_t)rl->ri.ri_addr, rl->rg.rg_free);
-		exit(1);
+		return -1;
 	}
 
 	switch (type) {
@@ -179,7 +171,7 @@ found:
 		break;
 	default:
 		fprintf(stderr, "bad state\n");
-		exit(1);
+		return -1;
 	}
 
 	bh->b_data[x] &= ~(0x03 << (GFS2_BIT_SIZE * y));
@@ -193,7 +185,27 @@ found:
 		gfs2_rgrp_out(rg, rl->bh[0]);
 
 	sdp->blks_alloced++;
-	return ri->ri_data0 + bn;
+	*blkno = ri->ri_data0 + bn;
+	return 0;
+}
+
+/**
+ * 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 data_alloc(struct gfs2_inode *ip)
@@ -220,6 +232,33 @@ uint64_t dinode_alloc(struct gfs2_sbd *sdp)
 	return blk_alloc_i(sdp, DINODE);
 }
 
+/**
+ * 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.
+ * 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)
+{
+	int ret;
+	struct rgrp_tree *rgt;
+	struct osi_node *n = NULL;
+	for (n = osi_first(&sdp->rgtree); n; n = osi_next(n)) {
+		rgt = (struct rgrp_tree *)n;
+		if (rgt->rg.rg_free >= blksreq)
+			break;
+	}
+	if (rgt == NULL)
+		return -1;
+
+	ret = blk_alloc_in_rg(sdp, DINODE, rgt, blkno);
+	gfs2_rgrp_relse(rgt);
+
+	if (ret == 0)
+		sdp->dinodes_alloced++;
+
+	return ret;
+}
+
 static __inline__ void buffer_clear_tail(struct gfs2_sbd *sdp,
 					 struct gfs2_buffer_head *bh, int head)
 {
@@ -1380,7 +1419,9 @@ static struct gfs2_inode *__createi(struct gfs2_inode *dip,
 
 	gfs2_lookupi(dip, filename, strlen(filename), &ip);
 	if (!ip) {
-		bn = dinode_alloc(sdp);
+		err = lgfs2_dinode_alloc(sdp, 1, &bn);
+		if (err != 0)
+			return NULL;
 
 		if (if_gfs1)
 			inum.no_formal_ino = bn;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index db31a6c..c415745 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -440,6 +440,7 @@ 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 uint64_t dinode_alloc(struct gfs2_sbd *sdp);
+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);
 #define gfs2_writei(ip, buf, offset, size) \
-- 
1.8.1.2




More information about the Cluster-devel mailing list