commit 37cf0257bf6298df38ca74ee8577bac5a40e6598
Author: Andrew Price <anprice@redhat.com>
Date: Thu Feb 6 04:25:27 2014 +0000
libgfs2: Superblock building and writing improvements
build_sb was creating the sb, setting its fields from an sdp and then
writing it, and also zeroing the gap before the sb on the device in a
block-by-block way using buffer_heads.
This patch splits the build_sb function into lgfs2_sb_init and
lgfs2_sb_write which operate on gfs2_sb structures instead of gfs2_sbds.
lgfs2_sb_write now uses pwritev to zero the initial blocks and write the
sb to an fd.
get_random_bytes has been moved into structures.c and made static as
only lgfs2_sb_init now uses it.
Resolves: rhbz#1063842
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 719ba9c..ce056a7 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -2374,7 +2374,8 @@ int main(int argc, char **argv)
bh = bread(&sb2, sb2.sb_addr);
sb2.sd_sb.sb_fs_format = GFS2_FORMAT_FS;
sb2.sd_sb.sb_multihost_format = GFS2_FORMAT_MULTI;
- gfs2_sb_out(&sb2.sd_sb, bh);
+ gfs2_sb_out(&sb2.sd_sb, bh->b_data);
+ bmodified(bh);
brelse(bh);
error = fsync(sb2.device_fd);
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index f0d9789..36f6600 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -2132,7 +2132,8 @@ static void process_field(const char *field, const char *nstr)
gfs2_sb_assigns(&lsb, field, nstr);
else
gfs2_sb_assignval(&lsb, field, newval);
- gfs2_sb_out(&lsb, rbh);
+ gfs2_sb_out(&lsb, rbh->b_data);
+ bmodified(rbh);
if (!termlines)
gfs2_sb_printval(&lsb, field);
} else {
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 5758607..0f33aa6 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -60,7 +60,7 @@ static int block_mounters(struct gfs2_sbd *sdp, int block_em)
}
}
- if (write_sb(sdp)) {
+ if (lgfs2_sb_write(&sdp->sd_sb, sdp->device_fd, sdp->bsize)) {
stack;
return -1;
}
@@ -1130,7 +1130,6 @@ static int sb_repair(struct gfs2_sbd *sdp)
{
uint64_t half;
uint32_t known_bsize = 0;
- unsigned char uuid[16];
int error = 0;
memset(&fix_md, 0, sizeof(fix_md));
@@ -1205,9 +1204,8 @@ static int sb_repair(struct gfs2_sbd *sdp)
}
}
/* Step 3 - Rebuild the lock protocol and file system table name */
- strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO);
- strcpy(sdp->locktable, "unknown");
if (query(_("Okay to fix the GFS2 superblock? (y/n)"))) {
+ struct gfs2_sb sb;
log_info(_("Found system master directory at: 0x%llx\n"),
sdp->sd_sb.sb_master_dir.no_addr);
sdp->master_dir = lgfs2_inode_read(sdp,
@@ -1226,8 +1224,12 @@ static int sb_repair(struct gfs2_sbd *sdp)
log_crit(_("Error reading root inode: %s\n"), strerror(errno));
return -1;
}
- get_random_bytes(uuid, sizeof(uuid));
- build_sb(sdp, uuid);
+ lgfs2_sb_init(&sb, sdp->bsize);
+ strcpy(sb.sb_lockproto, GFS2_DEFAULT_LOCKPROTO);
+ strcpy(sb.sb_locktable, "unknown");
+ sb.sb_master_dir = sdp->master_dir->i_di.di_num;
+ sb.sb_root_dir = sdp->md.rooti->i_di.di_num;
+ lgfs2_sb_write(&sb, sdp->device_fd, sdp->bsize);
inode_put(&sdp->md.rooti);
inode_put(&sdp->master_dir);
sb_fixed = 1;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index e785017..6710e72 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -724,7 +724,6 @@ extern int mount_gfs2_meta(struct gfs2_sbd *sdp);
extern void cleanup_metafs(struct gfs2_sbd *sdp);
extern int set_sysfs(const char *fsname, const char *filename, const char *val);
extern int is_fsname(char *name);
-extern void get_random_bytes(void *buf, int nbytes);
/* recovery.c */
extern void gfs2_replay_incr_blk(struct gfs2_inode *ip, unsigned int *blk);
@@ -758,7 +757,8 @@ static inline unsigned int rgrp_size(struct rgrp_tree *rgrp)
/* structures.c */
extern int build_master(struct gfs2_sbd *sdp);
-extern void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid);
+extern void lgfs2_sb_init(struct gfs2_sb *sb, unsigned bsize);
+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);
@@ -794,14 +794,14 @@ extern void print_it(const char *label, const char *fmt, const char *fmt2, ...)
/* Translation functions */
extern void gfs2_inum_in(struct gfs2_inum *no, char *buf);
-extern void gfs2_inum_out(struct gfs2_inum *no, char *buf);
+extern void gfs2_inum_out(const struct gfs2_inum *no, char *buf);
extern void gfs2_meta_header_in(struct gfs2_meta_header *mh,
struct gfs2_buffer_head *bh);
extern void gfs2_meta_header_out(const struct gfs2_meta_header *mh, char *buf);
extern void gfs2_meta_header_out_bh(const struct gfs2_meta_header *mh,
struct gfs2_buffer_head *bh);
extern void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh);
-extern void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh);
+extern void gfs2_sb_out(const struct gfs2_sb *sb, char *buf);
extern void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf);
extern void gfs2_rindex_out(struct gfs2_rindex *ri, char *buf);
extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh);
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index c4ed722..d707687 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -17,7 +17,6 @@
#include <dirent.h>
#include <sys/sysmacros.h>
#include <mntent.h>
-#include <sys/time.h>
#include <signal.h>
#include "libgfs2.h"
@@ -304,47 +303,3 @@ int set_sysfs(const char *fsname, const char *filename, const char *val)
close(fd);
return 0;
}
-
-/*
- * get_random_bytes - Generate a series of random bytes using /dev/urandom.
- *
- * Modified from original code in gen_uuid.c in e2fsprogs/lib
- */
-void get_random_bytes(void *buf, int nbytes)
-{
- int i, n = nbytes, fd;
- int lose_counter = 0;
- unsigned char *cp = (unsigned char *) buf;
- struct timeval tv;
-
- gettimeofday(&tv, 0);
- fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
- srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
- /* Crank the random number generator a few times */
- gettimeofday(&tv, 0);
- for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
- rand();
- if (fd >= 0) {
- while (n > 0) {
- i = read(fd, cp, n);
- if (i <= 0) {
- if (lose_counter++ > 16)
- break;
- continue;
- }
- n -= i;
- cp += i;
- lose_counter = 0;
- }
- close(fd);
- }
-
- /*
- * We do this all the time, but this is the only source of
- * randomness if /dev/random/urandom is out to lunch.
- */
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (rand() >> 7) & 0xFF;
-
- return;
-}
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
index 4baacc7..43618bc 100644
--- a/gfs2/libgfs2/ondisk.c
+++ b/gfs2/libgfs2/ondisk.c
@@ -48,7 +48,7 @@ void gfs2_inum_in(struct gfs2_inum *no, char *buf)
CPIN_64(no, str, no_addr);
}
-void gfs2_inum_out(struct gfs2_inum *no, char *buf)
+void gfs2_inum_out(const struct gfs2_inum *no, char *buf)
{
struct gfs2_inum *str = (struct gfs2_inum *)buf;
@@ -124,11 +124,11 @@ void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh)
#endif
}
-void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh)
+void gfs2_sb_out(const struct gfs2_sb *sb, char *buf)
{
- struct gfs2_sb *str = (struct gfs2_sb *)bh->b_data;
+ struct gfs2_sb *str = (struct gfs2_sb *)buf;
- gfs2_meta_header_out_bh(&sb->sb_header, bh);
+ gfs2_meta_header_out(&sb->sb_header, buf);
CPOUT_32(sb, str, sb_fs_format);
CPOUT_32(sb, str, sb_multihost_format);
@@ -144,7 +144,6 @@ void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh)
#ifdef GFS2_HAS_UUID
memcpy(str->sb_uuid, sb->sb_uuid, 16);
#endif
- bmodified(bh);
}
const char *str_uuid(const unsigned char *uuid)
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index e888f1e..2c1939a 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -11,6 +11,7 @@
#include <unistd.h>
#include <errno.h>
#include <linux/types.h>
+#include <sys/time.h>
#include "libgfs2.h"
@@ -41,43 +42,102 @@ int build_master(struct gfs2_sbd *sdp)
return 0;
}
-void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
+#ifdef GFS2_HAS_UUID
+/**
+ * Generate a series of random bytes using /dev/urandom.
+ * Modified from original code in gen_uuid.c in e2fsprogs/lib
+ */
+static void get_random_bytes(void *buf, int nbytes)
{
- unsigned int x;
- struct gfs2_buffer_head *bh;
- struct gfs2_sb sb;
-
- /* Zero out the beginning of the device up to the superblock */
- for (x = 0; x < sdp->sb_addr; x++) {
- bh = bget(sdp, x);
- memset(bh->b_data, 0, sdp->bsize);
- bmodified(bh);
- brelse(bh);
+ int i, n = nbytes, fd;
+ int lose_counter = 0;
+ unsigned char *cp = (unsigned char *) buf;
+ struct timeval tv;
+
+ gettimeofday(&tv, 0);
+ fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+ srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
+ /* Crank the random number generator a few times */
+ gettimeofday(&tv, 0);
+ for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
+ rand();
+ if (fd >= 0) {
+ while (n > 0) {
+ i = read(fd, cp, n);
+ if (i <= 0) {
+ if (lose_counter++ > 16)
+ break;
+ continue;
+ }
+ n -= i;
+ cp += i;
+ lose_counter = 0;
+ }
+ close(fd);
}
- memset(&sb, 0, sizeof(struct gfs2_sb));
- sb.sb_header.mh_magic = GFS2_MAGIC;
- sb.sb_header.mh_type = GFS2_METATYPE_SB;
- sb.sb_header.mh_format = GFS2_FORMAT_SB;
- sb.sb_fs_format = GFS2_FORMAT_FS;
- sb.sb_multihost_format = GFS2_FORMAT_MULTI;
- sb.sb_bsize = sdp->bsize;
- sb.sb_bsize_shift = ffs(sdp->bsize) - 1;
- sb.sb_master_dir = sdp->master_dir->i_di.di_num;
- sb.sb_root_dir = sdp->md.rooti->i_di.di_num;
- strcpy(sb.sb_lockproto, sdp->lockproto);
- strcpy(sb.sb_locktable, sdp->locktable);
+ /*
+ * We do this all the time, but this is the only source of
+ * randomness if /dev/random/urandom is out to lunch.
+ */
+ for (cp = buf, i = 0; i < nbytes; i++)
+ *cp++ ^= (rand() >> 7) & 0xFF;
+
+ return;
+}
+#endif
+
+/**
+ * Initialise a gfs2_sb structure with sensible defaults.
+ */
+void lgfs2_sb_init(struct gfs2_sb *sb, unsigned bsize)
+{
+ memset(sb, 0, sizeof(struct gfs2_sb));
+ sb->sb_header.mh_magic = GFS2_MAGIC;
+ sb->sb_header.mh_type = GFS2_METATYPE_SB;
+ sb->sb_header.mh_format = GFS2_FORMAT_SB;
+ sb->sb_fs_format = GFS2_FORMAT_FS;
+ sb->sb_multihost_format = GFS2_FORMAT_MULTI;
+ sb->sb_bsize = bsize;
+ sb->sb_bsize_shift = ffs(bsize) - 1;
#ifdef GFS2_HAS_UUID
- memcpy(sb.sb_uuid, uuid, sizeof(sb.sb_uuid));
+ get_random_bytes(&sb->sb_uuid, sizeof(sb->sb_uuid));
#endif
- bh = bget(sdp, sdp->sb_addr);
- gfs2_sb_out(&sb, bh);
- brelse(bh);
+}
- if (sdp->debug) {
- printf("\nSuper Block:\n");
- gfs2_sb_print(&sb);
+int lgfs2_sb_write(const struct gfs2_sb *sb, int fd, const unsigned bsize)
+{
+ int i, err = -1;
+ struct iovec *iov;
+ const size_t sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / bsize;
+ const size_t len = sb_addr + 1;
+
+ /* We only need 2 blocks: one for zeroing and a second for the superblock */
+ char *buf = calloc(2, bsize);
+ if (buf == NULL)
+ return -1;
+
+ iov = malloc(len * sizeof(*iov));
+ if (iov == NULL)
+ goto out_buf;
+
+ for (i = 0; i < len; i++) {
+ iov[i].iov_base = buf;
+ iov[i].iov_len = bsize;
}
+
+ gfs2_sb_out(sb, buf + bsize);
+ iov[sb_addr].iov_base = buf + bsize;
+
+ if (pwritev(fd, iov, len, 0) < (len * bsize))
+ goto out_iov;
+
+ err = 0;
+out_iov:
+ free(iov);
+out_buf:
+ free(buf);
+ return err;
}
int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks)
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index d074236..b956366 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -309,15 +309,3 @@ int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet)
return __ri_update(sdp, fd, rgcount, &sane, quiet);
}
-
-int write_sb(struct gfs2_sbd *sbp)
-{
- struct gfs2_buffer_head *bh;
-
- bh = bread(sbp, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift);
- gfs2_sb_out(&sbp->sd_sb, bh);
- brelse(bh);
- fsync(sbp->device_fd); /* make sure the change gets to disk ASAP */
- return 0;
-}
-
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 0d84064..8bd396a 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -569,8 +569,8 @@ static void print_results(struct gfs2_sbd *sdp, uint64_t real_device_size,
(unsigned long long)sdp->fssize, _("blocks"));
printf("%-27s%u\n", _("Journals:"), sdp->md.journals);
printf("%-27s%llu\n", _("Resource groups:"), (unsigned long long)sdp->rgrps);
- printf("%-27s\"%s\"\n", _("Locking protocol:"), sdp->lockproto);
- printf("%-27s\"%s\"\n", _("Lock table:"), sdp->locktable);
+ printf("%-27s\"%s\"\n", _("Locking protocol:"), opts->lockproto);
+ printf("%-27s\"%s\"\n", _("Lock table:"), opts->locktable);
/* Translators: "UUID" = universally unique identifier. */
printf("%-27s%s\n", _("UUID:"), str_uuid(uuid));
}
@@ -701,8 +701,6 @@ static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, struct mkfs_d
/* TODO: Check if the fssize is too small, somehow */
sdp->device.length = opts->fssize;
}
- strcpy(sdp->lockproto, opts->lockproto);
- strcpy(sdp->locktable, opts->locktable);
}
static int probe_contents(struct mkfs_dev *dev)
@@ -791,11 +789,11 @@ static void open_dev(const char *path, struct mkfs_dev *dev)
void main_mkfs(int argc, char *argv[])
{
struct gfs2_sbd sbd;
+ struct gfs2_sb sb;
struct mkfs_opts opts;
struct mkfs_dev dev;
lgfs2_rgrps_t rgs;
int error;
- unsigned char uuid[16];
unsigned bsize;
opts_init(&opts);
@@ -810,15 +808,16 @@ void main_mkfs(int argc, char *argv[])
}
sbd_init(&sbd, &opts, &dev, bsize);
+ lgfs2_sb_init(&sb, bsize);
if (opts.debug) {
printf(_("File system options:\n"));
printf(" bsize = %u\n", sbd.bsize);
printf(" qcsize = %u\n", sbd.qcsize);
printf(" jsize = %u\n", sbd.jsize);
printf(" journals = %u\n", sbd.md.journals);
- printf(" proto = %s\n", sbd.lockproto);
+ printf(" proto = %s\n", opts.lockproto);
+ printf(" table = %s\n", opts.locktable);
printf(" rgsize = %u\n", sbd.rgsize);
- printf(" table = %s\n", sbd.locktable);
printf(" fssize = %"PRIu64"\n", opts.fssize);
printf(" sunit = %lu\n", opts.sunit);
printf(" swidth = %lu\n", opts.swidth);
@@ -838,8 +837,13 @@ void main_mkfs(int argc, char *argv[])
exit(1);
}
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);
+ sb.sb_master_dir = sbd.master_dir->i_di.di_num;
+
error = build_jindex(&sbd);
if (error) {
fprintf(stderr, _("Error building '%s': %s\n"), "jindex", strerror(errno));
@@ -872,8 +876,9 @@ void main_mkfs(int argc, char *argv[])
fprintf(stderr, _("Error building '%s': %s\n"), "quota", strerror(errno));
exit(EXIT_FAILURE);
}
- get_random_bytes(uuid, sizeof(uuid));
- build_sb(&sbd, uuid);
+
+ strcpy(sb.sb_lockproto, opts.lockproto);
+ strcpy(sb.sb_locktable, opts.locktable);
do_init_inum(&sbd);
do_init_statfs(&sbd);
@@ -884,6 +889,13 @@ void main_mkfs(int argc, char *argv[])
inode_put(&sbd.md.statfs);
gfs2_rgrp_free(&sbd.rgtree);
+
+ error = lgfs2_sb_write(&sb, dev.fd, sbd.bsize);
+ if (error) {
+ perror(_("Failed to write superblock\n"));
+ exit(EXIT_FAILURE);
+ }
+
error = fsync(dev.fd);
if (error){
perror(opts.device);
@@ -897,5 +909,5 @@ void main_mkfs(int argc, char *argv[])
}
if (!opts.quiet)
- print_results(&sbd, dev.size, &opts, uuid);
+ print_results(&sbd, dev.size, &opts, sb.sb_uuid);
}