Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=dc2be884...
Commit: dc2be884934f140393ead923c09f7798a7263e29
Parent: 525339706657f324fdfa56f9538b74a6cd51752b
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Aug 26 23:15:26 2014 +0100
Committer: Andrew Price <anprice(a)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(a)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__ */