[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