Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=efd06c888ff... Commit: efd06c888ff3bbf1a7076b3283bf1f0bfa51be1c Parent: f1fe60d8d2fca0eb10d5cec6ecf8dacac3cb262e Author: Andrew Price anprice@redhat.com AuthorDate: Wed Jan 22 21:33:51 2014 +0000 Committer: Andrew Price anprice@redhat.com CommitterDate: Mon Jan 27 11:46:58 2014 +0000
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@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 b8cef87..b9b4154 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -1912,7 +1912,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 1d6fb4a..7a6f57a 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++; @@ -871,7 +865,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; @@ -1134,7 +1129,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; @@ -1183,7 +1179,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 00e18e6..8c8ca91 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 07cb221..084ef41 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);