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