[Cluster-devel] [PATCH 1/4] libgfs2: Superblock building and writing improvements

Andrew Price anprice at redhat.com
Mon Feb 17 14:47:57 UTC 2014


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.

Signed-off-by: Andrew Price <anprice at redhat.com>
---
 gfs2/convert/gfs2_convert.c |   3 +-
 gfs2/edit/hexedit.c         |   3 +-
 gfs2/fsck/initialize.c      |  14 +++---
 gfs2/libgfs2/libgfs2.h      |   8 +--
 gfs2/libgfs2/misc.c         |  45 -----------------
 gfs2/libgfs2/ondisk.c       |   9 ++--
 gfs2/libgfs2/structures.c   | 120 +++++++++++++++++++++++++++++++++-----------
 gfs2/libgfs2/super.c        |  12 -----
 gfs2/mkfs/main_mkfs.c       |  32 ++++++++----
 9 files changed, 132 insertions(+), 114 deletions(-)

diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 55db4fa..7a7d4df 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -2323,7 +2323,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 738dc4e..ffbf075 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -2150,7 +2150,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 cc65003..6372128 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -719,7 +719,6 @@ extern int dir_exists(const char *dir);
 extern int mount_gfs2_meta(struct gfs2_sbd *sdp);
 extern void cleanup_metafs(struct gfs2_sbd *sdp);
 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);
@@ -753,7 +752,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);
@@ -789,14 +789,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 d34b8a5..4cdd6e0 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"
@@ -276,47 +275,3 @@ void cleanup_metafs(struct gfs2_sbd *sdp)
 	sigaction(SIGUSR2, &sa, NULL);
 	metafs_interrupted = 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 030974b..2cc9a98 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_inode *jnl, unsigned bsize, 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);
 }
-- 
1.8.5.3




More information about the Cluster-devel mailing list