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

Reply via email to