gfs2-utils: master - Add Filesystem UUID to GFS2 utils.

Bob Peterson rpeterso@fedoraproject.org
Fri Jan 30 16:30:00 GMT 2009


Gitweb:        http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=ac2b41b856cc9ad148400c179de4fae7c78a1cb0
Commit:        ac2b41b856cc9ad148400c179de4fae7c78a1cb0
Parent:        26cedcc6c98185d78c8874ebfba4c16a8f3dcbb7
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Fri Jan 30 10:25:24 2009 -0600
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Fri Jan 30 10:25:24 2009 -0600

Add Filesystem UUID to GFS2 utils.

bz #242701

1. Added the ability for gfs2_edit to print the uuid value with
   -p sb and also to show it in the "structures" display.
2. Added the ability for gfs2_tool to print the uuid value with
   "sb"..."all" and "sb"..."uuid" and the ability to change the uuid
   through the same mechanism.
3. Updated the gfs2_tool.8 man page to reflect those changes.
4. This version of mkfs concocts the new uuid randomly, but does not
   allow the users to specify it (the same as mkfs.ext3 and mkfs.xfs)
---
 gfs2/edit/gfs2hex.c       |    3 ++
 gfs2/libgfs2/libgfs2.h    |    4 ++-
 gfs2/libgfs2/ondisk.c     |   34 ++++++++++++++++++++++++++
 gfs2/libgfs2/structures.c |   12 +--------
 gfs2/man/gfs2_tool.8      |    6 ++++
 gfs2/mkfs/main_mkfs.c     |   57 ++++++++++++++++++++++++++++++++++++++++++--
 gfs2/tool/sb.c            |   57 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 159 insertions(+), 14 deletions(-)

diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
index e24ae9b..f9b3ef4 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -471,6 +471,9 @@ void gfs2_sb_print2(struct gfs2_sb *sb)
 		gfs2_inum_print2("quota ino ", &gfs1_quota_di);
 		gfs2_inum_print2("license   ", &gfs1_license_di);
 	}
+#ifdef GFS2_HAS_UUID
+	print_it("  sb_uuid", "%s", NULL, str_uuid(sb->sb_uuid));
+#endif
 }
 
 /******************************************************************************
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index b37fd0d..1c743d1 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -663,7 +663,7 @@ extern void gfs2_rgrp_free(osi_list_t *rglist, enum update_flags updated);
 
 /* structures.c */
 extern int build_master(struct gfs2_sbd *sdp);
-extern void build_sb(struct gfs2_sbd *sdp);
+extern void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid);
 extern int build_jindex(struct gfs2_sbd *sdp);
 extern int build_per_node(struct gfs2_sbd *sdp);
 extern int build_inum(struct gfs2_sbd *sdp);
@@ -686,6 +686,8 @@ extern int write_sb(struct gfs2_sbd *sdp);
 
 /* ondisk.c */
 extern uint32_t gfs2_disk_hash(const char *data, int len);
+extern const char *str_uuid(const unsigned char *uuid);
+extern void gfs2_print_uuid(const unsigned char *uuid);
 extern void print_it(const char *label, const char *fmt, const char *fmt2, ...)
 	__attribute__((format(printf,2,4)));
 
diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c
index 7599a66..f1c91fb 100644
--- a/gfs2/libgfs2/ondisk.c
+++ b/gfs2/libgfs2/ondisk.c
@@ -3,6 +3,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <ctype.h>
 
 #include <linux/types.h>
 #include "libgfs2.h"
@@ -103,6 +104,9 @@ void gfs2_sb_in(struct gfs2_sb *sb, char *buf)
 
 	CPIN_08(sb, str, sb_lockproto, GFS2_LOCKNAME_LEN);
 	CPIN_08(sb, str, sb_locktable, GFS2_LOCKNAME_LEN);
+#ifdef GFS2_HAS_UUID
+	CPIN_08(sb, str, sb_uuid, sizeof(sb->sb_uuid));
+#endif
 }
 
 void gfs2_sb_out(struct gfs2_sb *sb, char *buf)
@@ -127,6 +131,32 @@ void gfs2_sb_out(struct gfs2_sb *sb, char *buf)
 #endif
 }
 
+const char *str_uuid(const unsigned char *uuid)
+{
+	static char str[64];
+	char *ch;
+	int i;
+
+	memset(str, 0, sizeof(str));
+	ch = str;
+	for (i = 0; i < 16; i++) {
+		sprintf(ch, "%02X", uuid[i]);
+		ch += 2;
+		if ((i == 3) || (i == 5) || (i == 7) || (i == 9)) {
+			*ch = '-';
+			ch++;
+		}
+	}
+	return str;
+}
+
+#ifdef GFS2_HAS_UUID
+void gfs2_print_uuid(const unsigned char *uuid)
+{
+	print_it("  uuid", "%s", NULL, str_uuid(uuid));
+}
+#endif
+
 void gfs2_sb_print(struct gfs2_sb *sb)
 {
 	gfs2_meta_header_print(&sb->sb_header);
@@ -142,6 +172,10 @@ void gfs2_sb_print(struct gfs2_sb *sb)
 
 	pv(sb, sb_lockproto, "%s", NULL);
 	pv(sb, sb_locktable, "%s", NULL);
+
+#ifdef GFS2_HAS_UUID
+	gfs2_print_uuid(sb->sb_uuid);
+#endif
 }
 
 void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf)
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index 4d77b2c..734efde 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -33,7 +33,7 @@ int build_master(struct gfs2_sbd *sdp)
 	return 0;
 }
 
-void build_sb(struct gfs2_sbd *sdp)
+void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid)
 {
 	unsigned int x;
 	struct gfs2_buffer_head *bh;
@@ -59,15 +59,7 @@ void build_sb(struct gfs2_sbd *sdp)
 	strcpy(sb.sb_lockproto, sdp->lockproto);
 	strcpy(sb.sb_locktable, sdp->locktable);
 #ifdef GFS2_HAS_UUID
-	{
-		int fd = open("/dev/urandom", O_RDONLY);
-		int n;
-		if (fd >= 0)
-			n = read(fd, &sb.sb_uuid, 16);
-		if (fd < 0 || n != 16)
-			memset(&sb.sb_uuid, 0, 16);
-		close(fd);
-	}
+	memcpy(sb.sb_uuid, uuid, sizeof(sb.sb_uuid));
 #endif
 	bh = bget(&sdp->buf_list, sdp->sb_addr);
 	gfs2_sb_out(&sb, bh->b_data);
diff --git a/gfs2/man/gfs2_tool.8 b/gfs2/man/gfs2_tool.8
index c28356a..a938a49 100644
--- a/gfs2/man/gfs2_tool.8
+++ b/gfs2/man/gfs2_tool.8
@@ -90,6 +90,12 @@ View (and possibly replace) the multihost format number in the
 file system superblock.  The file system shouldn't be mounted by any
 client when you do this.  No one should have to use this.
 .TP
+\fBsb\fP \fIdevice\fR \fBuuid\fP \fI[newvalue]\fR
+View (and possibly replace) the uuid in the file system superblock.
+The file system shouldn't be mounted by any client when you do this.
+The new uuid value should be in the standard uuid format.  For
+example: 1AEA8269-15C5-72BD-6D83-8720B17AA4EE
+.TP
 \fBsb\fP \fIdevice\fR \fBall\fP
 Print out the superblock.
 .TP
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 2b8a82a..cdc0068 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -12,6 +12,7 @@
 #include <stdarg.h>
 #include <mntent.h>
 #include <ctype.h>
+#include <sys/time.h>
 
 #include <linux/types.h>
 #include "libgfs2.h"
@@ -373,6 +374,50 @@ void check_mount(char *device)
 	return;
 }
 
+/*
+ * get_random_bytes - 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)
+{
+	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);
+	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;
+}
+
 /**
  * print_results - print out summary information
  * @sdp: the command line
@@ -380,7 +425,8 @@ void check_mount(char *device)
  */
 
 static void
-print_results(struct gfs2_sbd *sdp, uint64_t real_device_size)
+print_results(struct gfs2_sbd *sdp, uint64_t real_device_size,
+	      unsigned char uuid[16])
 {
 	if (sdp->debug)
 		printf("\n");
@@ -412,6 +458,7 @@ print_results(struct gfs2_sbd *sdp, uint64_t real_device_size)
 		printf("Writes:                    %u\n", sdp->writes);
 	}
 
+	printf("UUID:                      %s\n", str_uuid(uuid));
 	printf("\n");
 }
 
@@ -429,6 +476,7 @@ main_mkfs(int argc, char *argv[])
 	int error;
 	int rgsize_specified = 0;
 	uint64_t real_device_size;
+	unsigned char uuid[16];
 
 	memset(sdp, 0, sizeof(struct gfs2_sbd));
 	sdp->bsize = GFS2_DEFAULT_BSIZE;
@@ -488,12 +536,15 @@ main_mkfs(int argc, char *argv[])
 
 	compute_rgrp_layout(sdp, rgsize_specified);
 
+	/* Generate a random uuid */
+	get_random_bytes(uuid, sizeof(uuid));
+
 	/* Build ondisk structures */
 
 	build_rgrps(sdp, TRUE);
 	build_root(sdp);
 	build_master(sdp);
-	build_sb(sdp);
+	build_sb(sdp, uuid);
 	build_jindex(sdp);
 	build_per_node(sdp);
 	build_inum(sdp);
@@ -521,5 +572,5 @@ main_mkfs(int argc, char *argv[])
 		die("error closing device (%d): %s\n",
 		    error, strerror(errno));
 
-	print_results(sdp, real_device_size);
+	print_results(sdp, real_device_size, uuid);
 }
diff --git a/gfs2/tool/sb.c b/gfs2/tool/sb.c
index a668b8e..d6296c8 100644
--- a/gfs2/tool/sb.c
+++ b/gfs2/tool/sb.c
@@ -12,6 +12,7 @@
 #include <sys/ioctl.h>
 #include <limits.h>
 #include <errno.h>
+#include <ctype.h>
 
 #include <linux/gfs2_ondisk.h>
 
@@ -30,6 +31,31 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...)
 }
 
 /**
+ * str_to_hexchar - convert a string consisting of two isxdigits back to hex.
+ * Returns: the hex character
+ */
+int str_to_hexchar(const char *estring)
+{
+	int ch = 0;
+
+	if (isdigit(*estring))
+		ch = (*estring - '0') * 0x10;
+	else if (*estring >= 'a' && *estring <= 'f')
+		ch = (*estring - 'a' + 0x0a) * 0x10;
+	else if (*estring >= 'A' && *estring <= 'F')
+		ch = (*estring - 'A' + 0x0a) * 0x10;
+
+	estring++;
+	if (isdigit(*estring))
+		ch += (*estring - '0');
+	else if (*estring >= 'a' && *estring <= 'f')
+		ch += (*estring - 'a' + 0x0a);
+	else if (*estring >= 'A' && *estring <= 'F')
+		ch += (*estring - 'A' + 0x0a);
+	return ch;
+}
+
+/**
  * do_sb - examine/modify a unmounted FS' superblock
  * @argc:
  * @argv:
@@ -135,6 +161,37 @@ do_sb(int argc, char **argv)
 			printf("new multihost format = %u\n",
 			       sb.sb_multihost_format);
 		}
+#ifdef GFS2_HAS_UUID
+	} else if (strcmp(field, "uuid") == 0) {
+		printf("current uuid = %s\n", str_uuid(sb.sb_uuid));
+
+		if (newval) {
+			int i;
+			unsigned char uuid[16], *cp;
+
+			if (strlen(newval) != 36)
+				die("uuid %s is the wrong length; must be 36 "
+				    "hex characters long.\n", newval);
+			cp = uuid;
+			for (i = 0; i < 36; i++) {
+				if ((i == 8) || (i == 13) ||
+				    (i == 18) || (i == 23)) {
+					if (newval[i] == '-')
+						continue;
+					die("uuid %s has an invalid format.",
+					    newval);
+				}
+				if (!isxdigit(newval[i]))
+					die("uuid %s has an invalid hex "
+					    "digit '%c' at offset %d.\n",
+					    newval, newval[i], i + 1);
+				*cp = str_to_hexchar(&newval[i++]);
+				cp++;
+			}
+			memcpy(sb.sb_uuid, uuid, 16);
+			printf("new uuid = %s\n", str_uuid(sb.sb_uuid));
+		}
+#endif
 	} else if (strcmp(field, "all") == 0) {
 		gfs2_sb_print(&sb);
 		newval = FALSE;



More information about the Cluster-cvs mailing list