gfs2-utils: RHEL7 - mkfs.gfs2: Improve journal creation performance
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=4b8cdf7b...
Commit: 4b8cdf7bcb1048090b458ad84d678847bd59bc7f
Parent: d442c87479a35b272007c2794f0e70de34cbb0b4
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon Sep 1 19:51:04 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
mkfs.gfs2: Improve journal creation performance
Now that all of the journal extent allocation and writing building
blocks are in place in libgfs2, we can make use of them in mkfs.gfs2 to
write the journals sequentially and in-order with the resource group
blocks. This patch is a little messy because the changes had to be
introduced at the same time to avoid mismatching old and new behaviour,
but the end result should be fairly easy to follow.
Instead of writing all the resource group headers and then building the
journals afterwards, requiring the resource group headers to be read
back in, we now create a resource group header in memory, allocate the
blocks that we'll use for a journal in its bitmaps, write the resource
group header out, and then write the journal inode, indirect blocks and
data blocks in that order. This gives a substantial speed-up. For
example, running the test suite on my machine takes around 12 minutes
before and just over 2 minutes after this patch set.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/mkfs/main_mkfs.c | 151 +++++++++++++++++++++++++++++++++++++------------
1 files changed, 114 insertions(+), 37 deletions(-)
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 39b9609..530383d 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -166,6 +166,8 @@ static void opts_init(struct mkfs_opts *opts)
opts->align = 1;
}
+struct gfs2_inum *mkfs_journals = NULL;
+
#ifndef BLKDISCARD
#define BLKDISCARD _IO(0x12,119)
#endif
@@ -617,16 +619,11 @@ static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
return rgs;
}
-static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct gfs2_rindex *ri, int debug)
+static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrp_t rg, int debug)
{
int err = 0;
- lgfs2_rgrp_t rg = NULL;
+ const struct gfs2_rindex *ri = lgfs2_rgrp_index(rg);
- rg = lgfs2_rgrps_append(rgs, ri);
- if (rg == NULL) {
- perror(_("Failed to create resource group"));
- return -1;
- }
err = lgfs2_rgrp_write(sdp->device_fd, rg);
if (err != 0) {
perror(_("Failed to write resource group"));
@@ -642,46 +639,121 @@ static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct gfs2_rinde
return 0;
}
-static int place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts)
+static int add_rgrp(lgfs2_rgrps_t rgs, uint64_t *addr, uint32_t len, lgfs2_rgrp_t *rg)
{
struct gfs2_rindex ri;
- uint64_t jfsize = lgfs2_space_for_data(sdp, sdp->bsize, opts->jsize << 20);
- uint32_t jrgsize = lgfs2_rgsize_for_data(jfsize, sdp->bsize);
- uint64_t rgaddr = lgfs2_rgrp_align_addr(rgs, sdp->sb_addr + 1);
- uint32_t rgsize = lgfs2_rgrps_plan(rgs, sdp->device.length - rgaddr, ((opts->rgsize << 20) / sdp->bsize));
- unsigned j;
- if (rgsize >= jrgsize)
- jrgsize = rgsize;
+ /* When we get to the end of the device, it's only an error if we have
+ more structures left to write, i.e. when len is != 0. */
+ *addr = lgfs2_rindex_entry_new(rgs, &ri, *addr, len);
+ if (*addr == 0) {
+ if (len != 0) {
+ perror(_("Failed to create resource group index entry"));
+ return -1;
+ } else {
+ return 1;
+ }
+ }
- if (rgsize < ((GFS2_MIN_RGSIZE << 20) / sdp->bsize)) {
- fprintf(stderr, _("Resource group size is too small\n"));
+ *rg = lgfs2_rgrps_append(rgs, &ri);
+ if (*rg == NULL) {
+ perror(_("Failed to create resource group"));
return -1;
- } else if (rgsize < ((GFS2_DEFAULT_RGSIZE << 20) / sdp->bsize)) {
- fprintf(stderr, _("Warning: small resource group size could impact performance\n"));
}
+ return 0;
+}
+
+static int place_journals(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts, uint64_t *rgaddr)
+{
+ uint64_t jfsize = lgfs2_space_for_data(sdp, sdp->bsize, opts->jsize << 20);
+ uint32_t rgsize = lgfs2_rgsize_for_data(jfsize, sdp->bsize);
+ unsigned j;
+
+ /* We'll build the jindex later so remember where we put the journals */
+ mkfs_journals = calloc(opts->journals, sizeof(*mkfs_journals));
+ if (mkfs_journals == NULL)
+ return 1;
+ *rgaddr = lgfs2_rgrp_align_addr(rgs, sdp->sb_addr + 1);
for (j = 0; j < opts->journals; j++) {
int result;
- rgaddr = lgfs2_rindex_entry_new(rgs, &ri, rgaddr, jrgsize);
- if (rgaddr == 0) /* Reached the end when we still have journals to write */
- return 1;
- result = place_rgrp(sdp, rgs, &ri, opts->debug);
+ lgfs2_rgrp_t rg;
+ struct gfs2_inode in = {0};
+
+ if (opts->debug)
+ printf(_("Placing resource group for journal%u\n"), j);
+
+ result = add_rgrp(rgs, rgaddr, rgsize, &rg);
+ if (result > 0)
+ break;
+ else if (result < 0)
+ return result;
+
+ result = lgfs2_rgrp_bitbuf_alloc(rg);
+ if (result != 0) {
+ perror(_("Failed to allocate space for bitmap buffer"));
+ return result;
+ }
+ /* In order to keep writes sequential here, we have to allocate
+ the journal, then write the rgrp header (which is now in its
+ final form) and then write the journal out */
+ result = lgfs2_file_alloc(rg, opts->jsize << 20, &in, GFS2_DIF_SYSTEM, S_IFREG | 0600);
+ if (result != 0) {
+ fprintf(stderr, _("Failed to allocate space for journal %u\n"), j);
+ return result;
+ }
+
+ if (opts->debug)
+ gfs2_dinode_print(&in.i_di);
+
+ result = place_rgrp(sdp, rg, opts->debug);
if (result != 0)
return result;
+
+ lgfs2_rgrp_bitbuf_free(rg);
+
+ result = lgfs2_write_filemeta(&in);
+ if (result != 0) {
+ fprintf(stderr, _("Failed to write journal %u\n"), j);
+ return result;
+ }
+
+ result = lgfs2_write_journal_data(&in);
+ if (result != 0) {
+ fprintf(stderr, _("Failed to write data blocks for journal %u\n"), j);
+ return result;
+ }
+ mkfs_journals[j] = in.i_di.di_num;
}
- if (rgsize != jrgsize)
- lgfs2_rgrps_plan(rgs, sdp->device.length - rgaddr, ((opts->rgsize << 20) / sdp->bsize));
+ return 0;
+}
+
+static int place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts)
+{
+ uint64_t rgaddr = lgfs2_rgrp_align_addr(rgs, sdp->sb_addr + 1);
+ uint32_t rgblks = ((opts->rgsize << 20) / sdp->bsize);
+ int result;
+
+ result = place_journals(sdp, rgs, opts, &rgaddr);
+ if (result != 0)
+ return result;
+
+ lgfs2_rgrps_plan(rgs, sdp->device.length - rgaddr, rgblks);
while (1) {
- int result;
- rgaddr = lgfs2_rindex_entry_new(rgs, &ri, rgaddr, 0);
- if (rgaddr == 0)
- break; /* Done */
- result = place_rgrp(sdp, rgs, &ri, opts->debug);
- if (result)
+ lgfs2_rgrp_t rg;
+ result = add_rgrp(rgs, &rgaddr, 0, &rg);
+ if (result > 0)
+ break;
+ else if (result < 0)
+ return result;
+
+ result = place_rgrp(sdp, rg, opts->debug);
+ if (result != 0) {
+ fprintf(stderr, _("Failed to build resource groups\n"));
return result;
+ }
}
return 0;
}
@@ -696,7 +768,7 @@ static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, unsigned bsiz
sdp->jsize = opts->jsize;
sdp->md.journals = opts->journals;
sdp->device_fd = opts->dev.fd;
- sdp->bsize = bsize;
+ sdp->bsize = sdp->sd_sb.sb_bsize = bsize;
if (compute_constants(sdp)) {
perror(_("Failed to compute file system constants"));
@@ -848,17 +920,19 @@ void main_mkfs(int argc, char *argv[])
}
sbd.rgtree.osi_node = lgfs2_rgrps_root(rgs); // Temporary
- build_root(&sbd);
- sb.sb_root_dir = sbd.md.rooti->i_di.di_num;
-
- build_master(&sbd);
+ error = build_master(&sbd);
+ if (error) {
+ fprintf(stderr, _("Error building '%s': %s\n"), "master", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
sb.sb_master_dir = sbd.master_dir->i_di.di_num;
- error = build_jindex(&sbd);
+ error = lgfs2_build_jindex(sbd.master_dir, mkfs_journals, opts.journals);
if (error) {
fprintf(stderr, _("Error building '%s': %s\n"), "jindex", strerror(errno));
exit(EXIT_FAILURE);
}
+ free(mkfs_journals);
error = build_per_node(&sbd);
if (error) {
fprintf(stderr, _("Error building '%s': %s\n"), "per_node", strerror(errno));
@@ -887,6 +961,9 @@ void main_mkfs(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ build_root(&sbd);
+ sb.sb_root_dir = sbd.md.rooti->i_di.di_num;
+
strcpy(sb.sb_lockproto, opts.lockproto);
strcpy(sb.sb_locktable, opts.locktable);
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Create jindex directory separately from journals
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=d442c874...
Commit: d442c87479a35b272007c2794f0e70de34cbb0b4
Parent: afcb5592c84171a0631f91e4f938c7649c906f14
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon Sep 1 18:49:29 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Create jindex directory separately from journals
Previously journals were created indirectly via build_jindex and the
jindex inode (and therefore the master inode) was created before the
journals. Now that we're allocating the journals in whole resource
groups at the start of the mkfs process we need a way to create the
jindex after the journals are created. This adds lgfs2_build_jindex
which takes a list of inums relating to journals and builds the jindex
from them.
The old build_jindex function is left in place until the other tools
have been switched to use the new function.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/libgfs2.h | 1 +
gfs2/libgfs2/structures.c | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 406fbbe..831d45b 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -729,6 +729,7 @@ extern int lgfs2_sb_write(const struct gfs2_sb *sb, int fd, const unsigned bsize
extern int build_journal(struct gfs2_sbd *sdp, int j,
struct gfs2_inode *jindex);
extern int build_jindex(struct gfs2_sbd *sdp);
+extern int lgfs2_build_jindex(struct gfs2_inode *master, struct gfs2_inum *jnls, size_t nmemb);
extern int build_per_node(struct gfs2_sbd *sdp);
extern int build_inum(struct gfs2_sbd *sdp);
extern int build_statfs(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index c4b9ebc..87ffde7 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -255,6 +255,46 @@ int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
return ret;
}
+/**
+ * Write a jindex file given a list of journal inums.
+ * master: Inode of the master directory
+ * jnls: List of inum structures relating to previously created journals.
+ * nmemb: The number of entries in the list (number of journals).
+ * Returns 0 on success or non-zero on error with errno set.
+ */
+int lgfs2_build_jindex(struct gfs2_inode *master, struct gfs2_inum *jnls, size_t nmemb)
+{
+ char fname[GFS2_FNAMESIZE + 1];
+ struct gfs2_inode *jindex;
+ unsigned j;
+ int ret;
+
+ if (nmemb == 0 || jnls == NULL) {
+ errno = EINVAL;
+ return 1;
+ }
+ jindex = createi(master, "jindex", S_IFDIR | 0700, GFS2_DIF_SYSTEM);
+ if (jindex == NULL)
+ return 1;
+
+ fname[GFS2_FNAMESIZE] = '\0';
+
+ for (j = 0; j < nmemb; j++) {
+ snprintf(fname, GFS2_FNAMESIZE, "journal%u", j);
+ ret = dir_add(jindex, fname, strlen(fname), &jnls[j], IF2DT(S_IFREG | 0600));
+ if (ret)
+ return 1;
+ }
+
+ if (cfg_debug) {
+ printf("\nJindex:\n");
+ gfs2_dinode_print(&jindex->i_di);
+ }
+
+ inode_put(&jindex);
+ return 0;
+}
+
int build_jindex(struct gfs2_sbd *sdp)
{
struct gfs2_inode *jindex;
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Add a speedier journal data block writing function
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=afcb5592...
Commit: afcb5592c84171a0631f91e4f938c7649c906f14
Parent: 4cedf04eec47dff9040efc5b51e9ff50e726026b
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon Sep 1 17:30:35 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Add a speedier journal data block writing function
Now that we guarantee journals to be allocated contiguously, and the
block allocation has been separated out, we can speed up the journal
data writing process by simply generating the blocks and writing them
sequentially without consulting the resource group bitmaps each time a
new block is required.
lgfs2_write_journal_data() is added and the old write_journal() function
is left in place for now, until other journal creation scenarios (e.g.
potentially fragmented journals in gfs2_jadd and fsck.gfs2) have been
catered for, and those tools migrated to the new functions.
A further speed-up may be possible by using async i/o but we already
have a significant performance improvement with this strategy alone so
the added complexity of async i/o may not be worth it.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/libgfs2.h | 1 +
gfs2/libgfs2/structures.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index c7adbc1..406fbbe 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -500,6 +500,7 @@ extern void build_height(struct gfs2_inode *ip, int height);
extern void unstuff_dinode(struct gfs2_inode *ip);
extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
extern int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned blocks);
+extern int lgfs2_write_journal_data(struct gfs2_inode *ip);
extern int lgfs2_write_filemeta(struct gfs2_inode *ip);
/* gfs1.c - GFS1 backward compatibility structures and functions */
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index 1836255..c4b9ebc 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -143,6 +143,54 @@ out_buf:
return err;
}
+/**
+ * Intialise and write the data blocks for a new journal as a contiguous
+ * extent. The indirect blocks pointing to these data blocks should have been
+ * written separately using lgfs2_write_filemeta() and the extent should have
+ * been allocated using lgfs2_file_alloc().
+ * ip: The journal's inode
+ * Returns 0 on success or -1 with errno set on error.
+ */
+int lgfs2_write_journal_data(struct gfs2_inode *ip)
+{
+ uint32_t hash;
+ struct gfs2_log_header lh = {
+ .lh_header.mh_magic = GFS2_MAGIC,
+ .lh_header.mh_type = GFS2_METATYPE_LH,
+ .lh_header.mh_format = GFS2_FORMAT_LH,
+ .lh_flags = GFS2_LOG_HEAD_UNMOUNT,
+ };
+ struct gfs2_buffer_head *bh;
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ unsigned blocks = (ip->i_di.di_size + sdp->bsize - 1) / sdp->bsize;
+ uint64_t jext0 = ip->i_di.di_num.no_addr + ip->i_di.di_blocks - blocks;
+ uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0)));
+
+ bh = bget(sdp, jext0);
+ if (bh == NULL)
+ return -1;
+
+ do {
+ lh.lh_sequence = seq;
+ lh.lh_blkno = bh->b_blocknr - jext0;
+ gfs2_log_header_out(&lh, bh);
+ hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
+ ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash);
+
+ if (bwrite(bh)) {
+ free(bh);
+ return -1;
+ }
+
+ if (++seq == blocks)
+ seq = 0;
+
+ } while (++bh->b_blocknr < jext0 + blocks);
+
+ free(bh);
+ return 0;
+}
+
int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned int blocks)
{
struct gfs2_log_header lh;
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Handle non-zero bitmaps in lgfs2_rgrp_write
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=4cedf04e...
Commit: 4cedf04eec47dff9040efc5b51e9ff50e726026b
Parent: 0eb46efaeccbbf5f18da660e755fe193f4c325df
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Mon Sep 1 16:49:46 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Handle non-zero bitmaps in lgfs2_rgrp_write
Previously, lgfs2_rgrp_write had been used only for writing new resource
groups where the bitmaps were all zero. Fix it to write the bitmap
buffers already present in the resource group structure directly.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/rgrp.c | 32 +++++++++++++++++---------------
1 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 8f96c9f..f57ae3a 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -587,31 +587,33 @@ lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry)
*/
int lgfs2_rgrp_write(int fd, const lgfs2_rgrp_t rg)
{
- ssize_t ret = 0;
- lgfs2_rgrps_t rgs = rg->rgrps;
- size_t len = rg->ri.ri_length * rgs->sdp->bsize;
+ int ret = 0;
unsigned int i;
const struct gfs2_meta_header bmh = {
.mh_magic = GFS2_MAGIC,
.mh_type = GFS2_METATYPE_RB,
.mh_format = GFS2_FORMAT_RB,
};
- char *buff = calloc(len, 1);
- if (buff == NULL)
- return -1;
+ int freebufs = 0;
- gfs2_rgrp_out(&rg->rg, buff);
- for (i = 1; i < rg->ri.ri_length; i++)
- gfs2_meta_header_out(&bmh, buff + (i * rgs->sdp->bsize));
+ if (rg->bits[0].bi_bh == NULL) {
+ freebufs = 1;
+ if (lgfs2_rgrp_bitbuf_alloc(rg) != 0)
+ return -1;
+ }
- ret = pwrite(fd, buff, len, rg->ri.ri_addr * rgs->sdp->bsize);
- if (ret != len) {
- free(buff);
- return -1;
+ gfs2_rgrp_out(&rg->rg, rg->bits[0].bi_bh->b_data);
+ ret = bwrite(rg->bits[0].bi_bh);
+
+ for (i = 1; ret == 0 && i < rg->ri.ri_length; i++) {
+ gfs2_meta_header_out(&bmh, rg->bits[i].bi_bh->b_data);
+ ret = bwrite(rg->bits[i].bi_bh);
}
- free(buff);
- return 0;
+ if (freebufs)
+ lgfs2_rgrp_bitbuf_free(rg);
+
+ return ret;
}
lgfs2_rgrp_t lgfs2_rgrp_first(lgfs2_rgrps_t rgs)
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Fix alignment in lgfs2_rgsize_for_data
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=0eb46efa...
Commit: 0eb46efaeccbbf5f18da660e755fe193f4c325df
Parent: 443d8ee6df480d08db3e998a180b682ad0ed4210
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Aug 26 23:52:10 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Fix alignment in lgfs2_rgsize_for_data
Align the result of this function such that it matches the alignment
done by other functions which calculate a resource group size. This
avoids a situation where the resource group size is smaller than the
contents meant to fill it (e.g. journal file extents).
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/rgrp.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 57551c6..8f96c9f 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -525,6 +525,7 @@ unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize)
const uint32_t blks_rgrp = GFS2_NBBY * (bsize - sizeof(struct gfs2_rgrp));
const uint32_t blks_meta = GFS2_NBBY * (bsize - sizeof(struct gfs2_meta_header));
unsigned bitblocks = 1;
+ blksreq = (blksreq + 3) & ~3;
if (blksreq > blks_rgrp)
bitblocks += ((blksreq - blks_rgrp) + blks_meta - 1) / blks_meta;
return bitblocks + blksreq;
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Write file metadata sequentially
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=443d8ee6...
Commit: 443d8ee6df480d08db3e998a180b682ad0ed4210
Parent: 75495994a710d09a8a9a7b6f4a09b73e01a2a772
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Aug 26 23:40:56 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Write file metadata sequentially
Until now the journal creation functions built up the height of the
journal metadata using incremental allocation and the build_height
function which grows a file naively. Two things are about to change:
1. We will guarantee that a journal will occupy a single extent.
2. Journals will be written out sequentially and will only required one
write of the resource group header, before the journal is written.
Since we know the size of the extent and can predict the layout of the
journal's metadata tree, it is possible to generate and write the
metadata blocks in sequence. This patch adds an lgfs2_write_filemeta()
function which does just that.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/fs_ops.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
gfs2/libgfs2/libgfs2.h | 1 +
2 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 98db34d..9c9cc82 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -1412,6 +1412,75 @@ int init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, struct gfs2
return __init_dinode(sdp, bhp, inum, mode, flags, parent, 0);
}
+static void lgfs2_fill_indir(char *start, char *end, uint64_t ptr0, unsigned n, unsigned *p)
+{
+ char *bp;
+ memset(start, 0, end - start);
+ for (bp = start; bp < end && *p < n; bp += sizeof(uint64_t)) {
+ uint64_t pn = ptr0 + *p;
+ *(uint64_t *)bp = cpu_to_be64(pn);
+ (*p)++;
+ }
+}
+
+/**
+ * Calculate and write the indirect blocks for a single-extent file of a given
+ * size.
+ * ip: The inode for which to write indirect blocks, with fields already set
+ * appropriately (see lgfs2_file_alloc).
+ * Returns 0 on success or non-zero with errno set on failure.
+ */
+int lgfs2_write_filemeta(struct gfs2_inode *ip)
+{
+ unsigned height = 0;
+ struct metapath mp;
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ uint64_t dblocks = (ip->i_di.di_size + sdp->bsize - 1) / sdp->bsize;
+ uint64_t ptr0 = ip->i_di.di_num.no_addr + 1;
+ unsigned ptrs = 1;
+ struct gfs2_meta_header mh = {
+ .mh_magic = GFS2_MAGIC,
+ .mh_type = GFS2_METATYPE_IN,
+ .mh_format = GFS2_FORMAT_IN,
+ };
+ struct gfs2_buffer_head *bh = bget(sdp, ip->i_di.di_num.no_addr);
+ if (bh == NULL)
+ return 1;
+
+ /* Using find_metapath() to find the last data block in the file will
+ effectively give a remainder for the number of pointers at each
+ height. Just need to add 1 to convert ptr index to quantity later. */
+ find_metapath(ip, dblocks - 1, &mp);
+
+ for (height = 0; height < ip->i_di.di_height; height++) {
+ unsigned p;
+ /* The number of pointers in this height will be the number of
+ full indirect blocks pointed to by the previous height
+ multiplied by the pointer capacity of an indirect block,
+ plus the remainder which find_metapath() gave us. */
+ ptrs = ((ptrs - 1) * sdp->sd_inptrs) + mp.mp_list[height] + 1;
+
+ for (p = 0; p < ptrs; bh->b_blocknr++) {
+ char *start = bh->b_data;
+ if (height == 0) {
+ start += sizeof(struct gfs2_dinode);
+ gfs2_dinode_out(&ip->i_di, bh);
+ } else {
+ start += sizeof(struct gfs2_meta_header);
+ gfs2_meta_header_out(&mh, bh->b_data);
+ }
+ lgfs2_fill_indir(start, bh->b_data + sdp->bsize, ptr0, ptrs, &p);
+ if(bwrite(bh)) {
+ free(bh);
+ return 1;
+ }
+ }
+ ptr0 += ptrs;
+ }
+ free(bh);
+ return 0;
+}
+
static struct gfs2_inode *__createi(struct gfs2_inode *dip,
const char *filename, unsigned int mode,
uint32_t flags, int if_gfs1)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index d683dc7..c7adbc1 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -500,6 +500,7 @@ extern void build_height(struct gfs2_inode *ip, int height);
extern void unstuff_dinode(struct gfs2_inode *ip);
extern unsigned int calc_tree_height(struct gfs2_inode *ip, uint64_t size);
extern int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned blocks);
+extern int lgfs2_write_filemeta(struct gfs2_inode *ip);
/* gfs1.c - GFS1 backward compatibility structures and functions */
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Add support for allocating entire rgrp headers
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=75495994...
Commit: 75495994a710d09a8a9a7b6f4a09b73e01a2a772
Parent: dc2be884934f140393ead923c09f7798a7263e29
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Aug 26 23:26:30 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Add support for allocating entire rgrp headers
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 <anprice(a)redhat.com>
---
gfs2/libgfs2/libgfs2.h | 2 ++
gfs2/libgfs2/rgrp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 0 deletions(-)
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
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Add extent allocation functions
by Andrew Price
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__ */
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Allow init_dinode to accept a preallocated bh
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=52533970...
Commit: 525339706657f324fdfa56f9538b74a6cd51752b
Parent: a1e9d5e5171079b7d2f0c2f7c9f22e3a9dff04c4
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Aug 26 15:19:01 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Allow init_dinode to accept a preallocated bh
Previously init_dinode() always allocated the bh with bget() which meant
less control over memory allocation higher up. This patch changes the
signature of init_dinode to accept a bh pointer and only allocates a new
bh if it is NULL. Also adds error checking to init_dinode()'s callers.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/convert/gfs2_convert.c | 7 +++++--
gfs2/fsck/initialize.c | 12 ++++++++----
gfs2/libgfs2/fs_ops.c | 42 ++++++++++++++++++++++++------------------
gfs2/libgfs2/libgfs2.h | 6 ++----
gfs2/libgfs2/structures.c | 13 +++++++++----
5 files changed, 48 insertions(+), 32 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 61ed320..19a9839 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1389,7 +1389,7 @@ static int fix_cdpn_symlinks(struct gfs2_sbd *sbp, osi_list_t *cdpn_to_fix)
osi_list_foreach_safe(tmp, cdpn_to_fix, x) {
struct gfs2_inum fix, dir;
struct inode_dir_block *l_fix;
- struct gfs2_buffer_head *bh;
+ struct gfs2_buffer_head *bh = NULL;
struct gfs2_inode *fix_inode;
uint64_t eablk;
@@ -1411,7 +1411,10 @@ static int fix_cdpn_symlinks(struct gfs2_sbd *sbp, osi_list_t *cdpn_to_fix)
}
/* initialize the symlink inode to be a directory */
- bh = init_dinode(sbp, &fix, S_IFDIR | 0755, 0, &dir);
+ error = init_dinode(sbp, &bh, &fix, S_IFDIR | 0755, 0, &dir);
+ if (error != 0)
+ return -1;
+
fix_inode = lgfs2_inode_get(sbp, bh);
if (fix_inode == NULL)
return -1;
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 02ecd3f..4dedec2 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -419,7 +419,7 @@ static void check_rgrps_integrity(struct gfs2_sbd *sdp)
static int rebuild_master(struct gfs2_sbd *sdp)
{
struct gfs2_inum inum;
- struct gfs2_buffer_head *bh;
+ struct gfs2_buffer_head *bh = NULL;
int err = 0;
log_err(_("The system master directory seems to be destroyed.\n"));
@@ -430,7 +430,9 @@ static int rebuild_master(struct gfs2_sbd *sdp)
log_err(_("Trying to rebuild the master directory.\n"));
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = sdp->sd_sb.sb_master_dir.no_addr;
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
+ err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
+ if (err != 0)
+ return -1;
sdp->master_dir = lgfs2_inode_get(sdp, bh);
if (sdp->master_dir == NULL) {
log_crit(_("Error reading master: %s\n"), strerror(errno));
@@ -1210,7 +1212,7 @@ static int sb_repair(struct gfs2_sbd *sdp)
sdp->md.rooti = lgfs2_inode_read(sdp, possible_root);
if (!sdp->md.rooti ||
sdp->md.rooti->i_di.di_header.mh_magic != GFS2_MAGIC) {
- struct gfs2_buffer_head *bh;
+ struct gfs2_buffer_head *bh = NULL;
log_err(_("The root dinode block is destroyed.\n"));
log_err(_("At this point I recommend "
@@ -1225,7 +1227,9 @@ static int sb_repair(struct gfs2_sbd *sdp)
}
inum.no_formal_ino = 1;
inum.no_addr = possible_root;
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, 0, &inum);
+ error = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, &inum);
+ if (error != 0)
+ return -1;
brelse(bh);
}
}
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index aa95aa8..c8b90ad 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -1273,24 +1273,30 @@ int dir_add(struct gfs2_inode *dip, const char *filename, int len,
return err;
}
-static struct gfs2_buffer_head *__init_dinode(struct gfs2_sbd *sdp,
- struct gfs2_inum *inum,
- unsigned int mode,
- uint32_t flags,
- struct gfs2_inum *parent,
- int gfs1)
+static int __init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, struct gfs2_inum *inum,
+ unsigned int mode, uint32_t flags, struct gfs2_inum *parent, int gfs1)
{
struct gfs2_buffer_head *bh;
- struct gfs2_dinode di;
+ struct gfs2_dinode di = {{0}};
int is_dir;
if (gfs1)
is_dir = (IF2DT(mode) == GFS_FILE_DIR);
else
is_dir = S_ISDIR(mode);
- bh = bget(sdp, inum->no_addr);
- memset(&di, 0, sizeof(struct gfs2_dinode));
+ errno = EINVAL;
+ if (bhp == NULL)
+ return 1;
+
+ if (*bhp == NULL) {
+ *bhp = bget(sdp, inum->no_addr);
+ if (*bhp == NULL)
+ return 1;
+ }
+
+ bh = *bhp;
+
di.di_header.mh_magic = GFS2_MAGIC;
di.di_header.mh_type = GFS2_METATYPE_DI;
di.di_header.mh_format = GFS2_FORMAT_DI;
@@ -1340,15 +1346,13 @@ static struct gfs2_buffer_head *__init_dinode(struct gfs2_sbd *sdp,
gfs2_dinode_out(&di, bh);
- return bh;
+ return 0;
}
-struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
- struct gfs2_inum *inum,
- unsigned int mode, uint32_t flags,
- struct gfs2_inum *parent)
+int init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, struct gfs2_inum *inum,
+ unsigned int mode, uint32_t flags, struct gfs2_inum *parent)
{
- return __init_dinode(sdp, inum, mode, flags, parent, 0);
+ return __init_dinode(sdp, bhp, inum, mode, flags, parent, 0);
}
static struct gfs2_inode *__createi(struct gfs2_inode *dip,
@@ -1358,7 +1362,7 @@ static struct gfs2_inode *__createi(struct gfs2_inode *dip,
struct gfs2_sbd *sdp = dip->i_sbd;
uint64_t bn;
struct gfs2_inum inum;
- struct gfs2_buffer_head *bh;
+ struct gfs2_buffer_head *bh = NULL;
struct gfs2_inode *ip;
int err = 0;
int is_dir;
@@ -1388,8 +1392,10 @@ static struct gfs2_inode *__createi(struct gfs2_inode *dip,
dip->i_di.di_nlink++;
}
- bh = __init_dinode(sdp, &inum, mode, flags, &dip->i_di.di_num,
- if_gfs1);
+ err = __init_dinode(sdp, &bh, &inum, mode, flags, &dip->i_di.di_num, if_gfs1);
+ if (err != 0)
+ return NULL;
+
ip = lgfs2_inode_get(sdp, bh);
if (ip == NULL)
return NULL;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index ed1030c..9b1bdc2 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -462,10 +462,8 @@ extern int __gfs2_writei(struct gfs2_inode *ip, void *buf, uint64_t offset,
unsigned int size, int resize);
extern struct gfs2_buffer_head *get_file_buf(struct gfs2_inode *ip,
uint64_t lbn, int prealloc);
-extern struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
- struct gfs2_inum *inum,
- unsigned int mode, uint32_t flags,
- struct gfs2_inum *parent);
+extern int init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, struct gfs2_inum *inum,
+ unsigned int mode, uint32_t flags, struct gfs2_inum *parent);
extern struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename,
unsigned int mode, uint32_t flags);
extern struct gfs2_inode *gfs_createi(struct gfs2_inode *dip,
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index 9d90657..1836255 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -20,7 +20,7 @@ int build_master(struct gfs2_sbd *sdp)
{
struct gfs2_inum inum;
uint64_t bn;
- struct gfs2_buffer_head *bh;
+ struct gfs2_buffer_head *bh = NULL;
int err = lgfs2_dinode_alloc(sdp, 1, &bn);
if (err != 0)
@@ -29,7 +29,9 @@ int build_master(struct gfs2_sbd *sdp)
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = bn;
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
+ err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
+ if (err != 0)
+ return -1;
sdp->master_dir = lgfs2_inode_get(sdp, bh);
if (sdp->master_dir == NULL)
@@ -479,7 +481,7 @@ int build_root(struct gfs2_sbd *sdp)
{
struct gfs2_inum inum;
uint64_t bn;
- struct gfs2_buffer_head *bh;
+ struct gfs2_buffer_head *bh = NULL;
int err = lgfs2_dinode_alloc(sdp, 1, &bn);
if (err != 0)
@@ -488,7 +490,10 @@ int build_root(struct gfs2_sbd *sdp)
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = bn;
- bh = init_dinode(sdp, &inum, S_IFDIR | 0755, 0, &inum);
+ err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, &inum);
+ if (err != 0)
+ return -1;
+
sdp->md.rooti = lgfs2_inode_get(sdp, bh);
if (sdp->md.rooti == NULL)
return -1;
9 years, 7 months
gfs2-utils: RHEL7 - libgfs2: Const-ify the parameters of print functions
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=a1e9d5e5...
Commit: a1e9d5e5171079b7d2f0c2f7c9f22e3a9dff04c4
Parent: 080e886c3188adb63a0d5cfeed37bd488b9ebb0e
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Wed Jul 9 13:04:57 2014 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Fri Sep 5 14:57:46 2014 +0100
libgfs2: Const-ify the parameters of print functions
This allows us to use the *_print functions to print const types, which
works better with values returned from functions such as
lgfs2_rgrp_index()
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/libgfs2.h | 26 +++++++++++++-------------
gfs2/libgfs2/ondisk.c | 26 +++++++++++++-------------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index fca90b0..ed1030c 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -799,19 +799,19 @@ extern void gfs2_quota_change_out(struct gfs2_quota_change *qc,
/* Printing functions */
-extern void gfs2_inum_print(struct gfs2_inum *no);
-extern void gfs2_meta_header_print(struct gfs2_meta_header *mh);
-extern void gfs2_sb_print(struct gfs2_sb *sb);
-extern void gfs2_rindex_print(struct gfs2_rindex *ri);
-extern void gfs2_rgrp_print(struct gfs2_rgrp *rg);
-extern void gfs2_quota_print(struct gfs2_quota *qu);
-extern void gfs2_dinode_print(struct gfs2_dinode *di);
-extern void gfs2_leaf_print(struct gfs2_leaf *lf);
-extern void gfs2_ea_header_print(struct gfs2_ea_header *ea, char *name);
-extern void gfs2_log_header_print(struct gfs2_log_header *lh);
-extern void gfs2_log_descriptor_print(struct gfs2_log_descriptor *ld);
-extern void gfs2_statfs_change_print(struct gfs2_statfs_change *sc);
-extern void gfs2_quota_change_print(struct gfs2_quota_change *qc);
+extern void gfs2_inum_print(const struct gfs2_inum *no);
+extern void gfs2_meta_header_print(const struct gfs2_meta_header *mh);
+extern void gfs2_sb_print(const struct gfs2_sb *sb);
+extern void gfs2_rindex_print(const struct gfs2_rindex *ri);
+extern void gfs2_rgrp_print(const struct gfs2_rgrp *rg);
+extern void gfs2_quota_print(const struct gfs2_quota *qu);
+extern void gfs2_dinode_print(const struct gfs2_dinode *di);
+extern void gfs2_leaf_print(const struct gfs2_leaf *lf);
+extern void gfs2_ea_header_print(const struct gfs2_ea_header *ea, char *name);
+extern void gfs2_log_header_print(const struct gfs2_log_header *lh);
+extern void gfs2_log_descriptor_print(const struct gfs2_log_descriptor *ld);
+extern void gfs2_statfs_change_print(const struct gfs2_statfs_change *sc);
+extern void gfs2_quota_change_print(const struct gfs2_quota_change *qc);
/* Language functions */
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
index 1f81b5f..4744337 100644
--- a/gfs2/libgfs2/ondisk.c
+++ b/gfs2/libgfs2/ondisk.c
@@ -56,7 +56,7 @@ void gfs2_inum_out(const struct gfs2_inum *no, char *buf)
CPOUT_64(no, str, no_addr);
}
-void gfs2_inum_print(struct gfs2_inum *no)
+void gfs2_inum_print(const struct gfs2_inum *no)
{
pv(no, no_formal_ino, "%llu", "0x%llx");
pv(no, no_addr, "%llu", "0x%llx");
@@ -90,7 +90,7 @@ void gfs2_meta_header_out_bh(const struct gfs2_meta_header *mh,
bmodified(bh);
}
-void gfs2_meta_header_print(struct gfs2_meta_header *mh)
+void gfs2_meta_header_print(const struct gfs2_meta_header *mh)
{
pv(mh, mh_magic, "0x%08X", NULL);
pv(mh, mh_type, "%u", "0x%x");
@@ -177,7 +177,7 @@ void gfs2_print_uuid(const unsigned char *uuid)
}
#endif
-void gfs2_sb_print(struct gfs2_sb *sb)
+void gfs2_sb_print(const struct gfs2_sb *sb)
{
gfs2_meta_header_print(&sb->sb_header);
@@ -229,7 +229,7 @@ void gfs2_rindex_out(const struct gfs2_rindex *ri, char *buf)
CPOUT_08(ri, str, ri_reserved, 64);
}
-void gfs2_rindex_print(struct gfs2_rindex *ri)
+void gfs2_rindex_print(const struct gfs2_rindex *ri)
{
pv(ri, ri_addr, "%llu", "0x%llx");
pv(ri, ri_length, "%u", "0x%x");
@@ -270,7 +270,7 @@ void gfs2_rgrp_out_bh(const struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh)
bmodified(bh);
}
-void gfs2_rgrp_print(struct gfs2_rgrp *rg)
+void gfs2_rgrp_print(const struct gfs2_rgrp *rg)
{
gfs2_meta_header_print(&rg->rg_header);
pv(rg, rg_flags, "%u", "0x%x");
@@ -298,7 +298,7 @@ void gfs2_quota_out(struct gfs2_quota *qu, char *buf)
memset(qu->qu_reserved, 0, sizeof(qu->qu_reserved));
}
-void gfs2_quota_print(struct gfs2_quota *qu)
+void gfs2_quota_print(const struct gfs2_quota *qu)
{
pv(qu, qu_limit, "%llu", "0x%llx");
pv(qu, qu_warn, "%llu", "0x%llx");
@@ -376,7 +376,7 @@ void gfs2_dinode_out(struct gfs2_dinode *di, struct gfs2_buffer_head *bh)
bmodified(bh);
}
-void gfs2_dinode_print(struct gfs2_dinode *di)
+void gfs2_dinode_print(const struct gfs2_dinode *di)
{
gfs2_meta_header_print(&di->di_header);
gfs2_inum_print(&di->di_num);
@@ -470,7 +470,7 @@ void gfs2_leaf_out(struct gfs2_leaf *lf, struct gfs2_buffer_head *bh)
bmodified(bh);
}
-void gfs2_leaf_print(struct gfs2_leaf *lf)
+void gfs2_leaf_print(const struct gfs2_leaf *lf)
{
gfs2_meta_header_print(&lf->lf_header);
pv(lf, lf_depth, "%u", "0x%x");
@@ -497,7 +497,7 @@ void gfs2_ea_header_in(struct gfs2_ea_header *ea, char *buf)
ea->ea_num_ptrs = str->ea_num_ptrs;
}
-void gfs2_ea_header_print(struct gfs2_ea_header *ea, char *name)
+void gfs2_ea_header_print(const struct gfs2_ea_header *ea, char *name)
{
char buf[GFS2_EA_MAX_NAME_LEN + 1];
@@ -540,7 +540,7 @@ void gfs2_log_header_out(struct gfs2_log_header *lh,
bmodified(bh);
}
-void gfs2_log_header_print(struct gfs2_log_header *lh)
+void gfs2_log_header_print(const struct gfs2_log_header *lh)
{
gfs2_meta_header_print(&lh->lh_header);
pv(lh, lh_sequence, "%llu", "0x%llx");
@@ -579,7 +579,7 @@ void gfs2_log_descriptor_out(struct gfs2_log_descriptor *ld,
bmodified(bh);
}
-void gfs2_log_descriptor_print(struct gfs2_log_descriptor *ld)
+void gfs2_log_descriptor_print(const struct gfs2_log_descriptor *ld)
{
gfs2_meta_header_print(&ld->ld_header);
pv(ld, ld_type, "%u", "0x%x");
@@ -606,7 +606,7 @@ void gfs2_statfs_change_out(struct gfs2_statfs_change *sc, char *buf)
CPOUT_64(sc, str, sc_dinodes);
}
-void gfs2_statfs_change_print(struct gfs2_statfs_change *sc)
+void gfs2_statfs_change_print(const struct gfs2_statfs_change *sc)
{
pv(sc, sc_total, "%lld", "0x%llx");
pv(sc, sc_free, "%lld", "0x%llx");
@@ -636,7 +636,7 @@ void gfs2_quota_change_out(struct gfs2_quota_change *qc,
bmodified(bh);
}
-void gfs2_quota_change_print(struct gfs2_quota_change *qc)
+void gfs2_quota_change_print(const struct gfs2_quota_change *qc)
{
pv(qc, qc_change, "%lld", "0x%llx");
pv(qc, qc_flags, "0x%.8X", NULL);
9 years, 7 months