Before we can allocate files without writing buffers back to disk immediately we need to hold the bitmap blocks for one rgrp in memory. Add a lgfs2_rgrp_bitbuf_alloc() function which allocates the memory for a resource group's bitmap blocks in one chunk, and also a matching _free function.
Signed-off-by: Andrew Price <anpr...@redhat.com> --- gfs2/libgfs2/libgfs2.h | 2 ++ gfs2/libgfs2/rgrp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index 43529a0..d683dc7 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -201,6 +201,8 @@ extern uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len); extern unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize); extern uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize); extern lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry); +extern int lgfs2_rgrp_bitbuf_alloc(lgfs2_rgrp_t rg); +extern void lgfs2_rgrp_bitbuf_free(lgfs2_rgrp_t rg); extern int lgfs2_rgrp_write(int fd, lgfs2_rgrp_t rg); extern const struct gfs2_rindex *lgfs2_rgrp_index(lgfs2_rgrp_t rg); extern const struct gfs2_rgrp *lgfs2_rgrp_rgrp(lgfs2_rgrp_t rg); diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c index 772e6d0..57551c6 100644 --- a/gfs2/libgfs2/rgrp.c +++ b/gfs2/libgfs2/rgrp.c @@ -99,6 +99,54 @@ struct rgrp_tree *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk) } /** + * Allocate a multi-block buffer for a resource group's bitmaps. This is done + * as one chunk and should be freed using lgfs2_rgrp_bitbuf_free(). + * Returns 0 on success with the bitmap buffer allocated in the resource group, + * or non-zero on failure with errno set. + */ +int lgfs2_rgrp_bitbuf_alloc(lgfs2_rgrp_t rg) +{ + struct gfs2_sbd *sdp = rg->rgrps->sdp; + unsigned i; + char *bufs; + + bufs = calloc(rg->ri.ri_length, sizeof(struct gfs2_buffer_head) + sdp->bsize); + if (bufs == NULL) + return 1; + + rg->bits[0].bi_bh = (struct gfs2_buffer_head *)bufs; + rg->bits[0].bi_bh->iov.iov_base = (char *)(rg->bits[0].bi_bh + 1); + rg->bits[0].bi_bh->iov.iov_len = sdp->bsize; + rg->bits[0].bi_bh->b_blocknr = rg->ri.ri_addr; + rg->bits[0].bi_bh->sdp = sdp; + + for (i = 1; i < rg->ri.ri_length; i++) { + char *nextbuf = rg->bits[i - 1].bi_bh->b_data + sdp->bsize; + rg->bits[i].bi_bh = (struct gfs2_buffer_head *)(nextbuf); + rg->bits[i].bi_bh->iov.iov_base = (char *)(rg->bits[i].bi_bh + 1); + rg->bits[i].bi_bh->iov.iov_len = sdp->bsize; + rg->bits[i].bi_bh->b_blocknr = rg->ri.ri_addr + i; + rg->bits[i].bi_bh->sdp = sdp; + } + return 0; +} + +/** + * Free the multi-block bitmap buffer from a resource group. The buffer should + * have been allocated as a single chunk as in lgfs2_rgrp_bitbuf_alloc(). + * This does not implicitly write the bitmaps to disk. Use lgfs2_rgrp_write() + * for that. + * rg: The resource groups whose bitmap buffer should be freed. + */ +void lgfs2_rgrp_bitbuf_free(lgfs2_rgrp_t rg) +{ + unsigned i; + free(rg->bits[0].bi_bh); + for (i = 0; i < rg->ri.ri_length; i++) + rg->bits[i].bi_bh = NULL; +} + +/** * gfs2_rgrp_read - read in the resource group information from disk. * @rgd - resource group structure * returns: 0 if no error, otherwise the block number that failed -- 1.9.3