gfs2-utils: RHEL7 - libgfs2: Add extent allocation functions

Andrew Price andyp at fedoraproject.org
Mon Sep 8 17:34:32 UTC 2014


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=dc2be884934f140393ead923c09f7798a7263e29
Commit:        dc2be884934f140393ead923c09f7798a7263e29
Parent:        525339706657f324fdfa56f9538b74a6cd51752b
Author:        Andrew Price <anprice at redhat.com>
AuthorDate:    Tue Aug 26 23:15:26 2014 +0100
Committer:     Andrew Price <anprice at redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100

libgfs2: Add extent allocation functions

In order to preallocate journals as single extents we need functions
which allow bitmap allocation separate from buffer allocation and
writing. This adds two functions, lgfs2_file_alloc and
lgfs2_alloc_extent, which solve this problem, making use of the new
lgfs2_rbm functions.

Signed-off-by: Andrew Price <anprice at redhat.com>
---
 gfs2/libgfs2/fs_ops.c  |   57 ++++++++++++++++++++++++++++++++++++++++++++++++
 gfs2/libgfs2/libgfs2.h |    1 +
 gfs2/libgfs2/rgrp.c    |   24 ++++++++++++++++++++
 gfs2/libgfs2/rgrp.h    |    1 +
 4 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index c8b90ad..98db34d 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include "libgfs2.h"
+#include "rgrp.h"
 
 static __inline__ uint64_t *metapointer(struct gfs2_buffer_head *bh,
 					unsigned int height,
@@ -291,6 +292,62 @@ uint64_t lgfs2_space_for_data(const struct gfs2_sbd *sdp, const unsigned bsize,
 	return blks + 1;
 }
 
+/**
+ * Allocate an extent for a file in a resource group's bitmaps.
+ * rg: The resource group in which to allocate the extent
+ * di_size: The size of the file in bytes
+ * ip: A pointer to the inode structure, whose fields will be set appropriately
+ * flags: GFS2_DIF_* flags
+ * mode: File mode flags, see creat(2)
+ * Returns 0 on success with the contents of ip set accordingly, or non-zero
+ * with errno set on error. If errno is ENOSPC then rg does not contain a
+ * large enough free extent for the given di_size.
+ */
+int lgfs2_file_alloc(lgfs2_rgrp_t rg, uint64_t di_size, struct gfs2_inode *ip, uint32_t flags, unsigned mode)
+{
+	unsigned extlen;
+	struct gfs2_dinode *di = &ip->i_di;
+	struct gfs2_sbd *sdp = rg->rgrps->sdp;
+	struct lgfs2_rbm rbm = { .rgd = rg, .offset = 0, .bii = 0 };
+	uint32_t blocks = lgfs2_space_for_data(sdp, sdp->bsize, di_size);
+	int err;
+
+	err = lgfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &blocks);
+	if (err != 0)
+		return err;
+
+	extlen = lgfs2_alloc_extent(&rbm, GFS2_BLKST_DINODE, blocks);
+	if (extlen < blocks) {
+		errno = EINVAL;
+		return 1;
+	}
+
+	ip->i_sbd = sdp;
+
+	di->di_header.mh_magic = GFS2_MAGIC;
+	di->di_header.mh_type = GFS2_METATYPE_DI;
+	di->di_header.mh_format = GFS2_FORMAT_DI;
+	di->di_size = di_size;
+	di->di_num.no_addr = lgfs2_rbm_to_block(&rbm);
+	di->di_num.no_formal_ino = sdp->md.next_inum++;
+	di->di_mode = mode;
+	di->di_nlink = 1;
+	di->di_blocks = blocks;
+	di->di_atime = di->di_mtime = di->di_ctime = sdp->time;
+	di->di_goal_data = di->di_num.no_addr + di->di_blocks - 1;
+	di->di_goal_meta = di->di_goal_data - ((di_size + sdp->bsize - 1) / sdp->bsize);
+	di->di_height = calc_tree_height(ip, di_size);
+	di->di_flags = flags;
+
+	rg->rg.rg_free -= blocks;
+	rg->rg.rg_dinodes += 1;
+
+	sdp->dinodes_alloced++;
+	sdp->blks_alloced += blocks;
+
+	return 0;
+}
+
 unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size)
 {
 	struct gfs2_sbd *sdp = ip->i_sbd;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 9b1bdc2..43529a0 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -453,6 +453,7 @@ extern uint64_t data_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 uint64_t lgfs2_space_for_data(const struct gfs2_sbd *sdp, unsigned bsize, uint64_t bytes);
+extern int lgfs2_file_alloc(lgfs2_rgrp_t rg, uint64_t di_size, struct gfs2_inode *ip, uint32_t flags, unsigned mode);
 
 extern int gfs2_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
 		      unsigned int size);
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index a3fa1a4..772e6d0 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -841,3 +841,27 @@ res_covered_end_of_rgrp:
 	errno = ENOSPC;
 	return 1;
 }
+
+/**
+ * lgfs2_alloc_extent - allocate an extent from a given bitmap
+ * @rbm: the resource group information
+ * @state: The state of the first block, GFS2_BLKST_DINODE or GFS2_BLKST_USED
+ * @elen: The requested extent length
+ * Returns the length of the extent allocated.
+ */
+unsigned lgfs2_alloc_extent(const struct lgfs2_rbm *rbm, int state, const unsigned elen)
+{
+	struct lgfs2_rbm pos = { .rgd = rbm->rgd, };
+	const uint64_t block = lgfs2_rbm_to_block(rbm);
+	unsigned len;
+
+	gfs2_set_bitmap(rbm->rgd, block, state);
+
+	for (len = 1; len < elen; len++) {
+		int ret = lgfs2_rbm_from_block(&pos, block + len);
+		if (ret || lgfs2_testbit(&pos) != GFS2_BLKST_FREE)
+			break;
+		gfs2_set_bitmap(pos.rgd, block + len, GFS2_BLKST_USED);
+	}
+	return len;
+}
diff --git a/gfs2/libgfs2/rgrp.h b/gfs2/libgfs2/rgrp.h
index 1634fbc..bd89289 100644
--- a/gfs2/libgfs2/rgrp.h
+++ b/gfs2/libgfs2/rgrp.h
@@ -45,5 +45,6 @@ static inline int lgfs2_rbm_eq(const struct lgfs2_rbm *rbm1, const struct lgfs2_
 }
 
 extern int lgfs2_rbm_find(struct lgfs2_rbm *rbm, uint8_t state, uint32_t *minext);
+extern unsigned lgfs2_alloc_extent(const struct lgfs2_rbm *rbm, int state, const unsigned elen);
 
 #endif /* __RGRP_DOT_H__ */


More information about the cluster-commits mailing list