cluster: STABLE3 - gfs2: GFS2 utilities should make use of exported device topology

Bob Peterson rpeterso at fedoraproject.org
Tue Mar 2 14:52:18 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=ff524561ca1684696a7e1a5526edb108b78324f2
Commit:        ff524561ca1684696a7e1a5526edb108b78324f2
Parent:        463a731a9396385a46d2ec5736bfe7ba687968b3
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Tue Mar 2 08:46:35 2010 -0600
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Tue Mar 2 08:50:35 2010 -0600

gfs2: GFS2 utilities should make use of exported device topology

This patch uses ioctls to fetch device topology information for
the devices and uses it to validate and default block sizes in
rgrps.

rhbz#519491
---
 gfs2/libgfs2/device_geometry.c |   38 +++++++++++++++++++++-
 gfs2/libgfs2/libgfs2.h         |   10 ++++++
 gfs2/mkfs/main_mkfs.c          |   69 +++++++++++++++++++++++++++++++++++-----
 3 files changed, 108 insertions(+), 9 deletions(-)

diff --git a/gfs2/libgfs2/device_geometry.c b/gfs2/libgfs2/device_geometry.c
index b2d5861..a05ae94 100644
--- a/gfs2/libgfs2/device_geometry.c
+++ b/gfs2/libgfs2/device_geometry.c
@@ -8,10 +8,46 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-
+#include <sys/ioctl.h>
 #include <linux/types.h>
+
 #include "libgfs2.h"
 
+#define BLKSSZGET _IO(0x12,104)   /* logical_block_size */
+#define BLKIOMIN _IO(0x12,120)    /* minimum_io_size */
+#define BLKIOOPT _IO(0x12,121)    /* optimal_io_size */
+#define BLKALIGNOFF _IO(0x12,122) /* alignment_offset */
+#define BLKPBSZGET _IO(0x12,123)  /* physical_block_size */
+
+/**
+ * device_topology - Get the device topology
+ * Values not fetched are returned as zero.
+ */
+int device_topology(struct gfs2_sbd *sdp)
+{
+	if (ioctl(sdp->device_fd, BLKSSZGET, &sdp->logical_block_size) < 0)
+		sdp->logical_block_size = 0;
+	if (ioctl(sdp->device_fd, BLKIOMIN, &sdp->minimum_io_size) < 0)
+		sdp->minimum_io_size = 0;
+	if (ioctl(sdp->device_fd, BLKALIGNOFF, &sdp->optimal_io_size) < 0)
+		sdp->optimal_io_size = 0;
+	if (ioctl(sdp->device_fd, BLKIOOPT, &sdp->alignment_offset) < 0)
+		sdp->alignment_offset = 0;
+	if (ioctl(sdp->device_fd, BLKPBSZGET, &sdp->physical_block_size) < 0)
+		sdp->physical_block_size = 0;
+	if (!sdp->debug)
+		return 0;
+
+	printf("\nDevice Topology:\n");
+	printf("  Logical block size: %u\n", sdp->logical_block_size);
+	printf("  Physical block size: %u\n", sdp->physical_block_size);
+	printf("  Minimum I/O size: %u\n", sdp->minimum_io_size);
+	printf("  Optimal I/O size: %u (0 means unknown)\n",
+	       sdp->optimal_io_size);
+	printf("  Alignment offset: %u\n", sdp->alignment_offset);
+	return 0;
+}
+
 /**
  * device_geometry - Get the size of a device
  * @w: the command line
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 6aa9e2d..f98f845 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -235,6 +235,15 @@ struct gfs2_sbd {
 	int metafs_fd;
 	char metafs_path[PATH_MAX]; /* where metafs is mounted */
 	struct special_blocks eattr_blocks;
+
+	/* device topology information: */
+	uint32_t logical_block_size;
+	uint32_t minimum_io_size;
+	uint32_t optimal_io_size;
+	uint32_t alignment_offset;
+	uint32_t physical_block_size;
+	uint64_t rg_one_length;
+	uint64_t rg_length;
 };
 
 struct metapath {
@@ -376,6 +385,7 @@ extern int brelse(struct gfs2_buffer_head *bh);
 #define bcommit(bl) do { __bcommit(bl, __LINE__, __FUNCTION__); } while(0)
 
 /* device_geometry.c */
+extern int device_topology(struct gfs2_sbd *sdp);
 extern int device_geometry(struct gfs2_sbd *sdp);
 extern int fix_device_geometry(struct gfs2_sbd *sdp);
 
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 50e3550..eff2c9a 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -16,6 +16,7 @@
 #include <signal.h>
 #include <sys/time.h>
 #include <libintl.h>
+
 #define _(String) gettext(String)
 
 #include <linux/types.h>
@@ -189,7 +190,8 @@ static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
 
 	if (sdp->debug) {
 		printf( _("Command Line Arguments:\n"));
-		printf("  bsize = %u\n", sdp->bsize);
+		if (sdp->bsize != -1)
+			printf("  bsize = %u\n", sdp->bsize);
 		printf("  qcsize = %u\n", sdp->qcsize);
 		printf("  jsize = %u\n", sdp->jsize);
 		printf("  journals = %u\n", sdp->md.journals);
@@ -256,12 +258,10 @@ static void test_locking(char *lockproto, char *locktable)
 	}
 }
 
-static void verify_arguments(struct gfs2_sbd *sdp)
+static void verify_bsize(struct gfs2_sbd *sdp)
 {
 	unsigned int x;
-
-	if (!sdp->expert)
-		test_locking(sdp->lockproto, sdp->locktable);
+	char input[32];
 
 	/* Block sizes must be a power of two from 512 to 65536 */
 
@@ -269,9 +269,38 @@ static void verify_arguments(struct gfs2_sbd *sdp)
 		if (x == sdp->bsize)
 			break;
 
-	if (!x || sdp->bsize > 65536)
-		die( _("block size must be a power of two between 512 and 65536\n"));
+	if (!x || sdp->bsize > getpagesize())
+		die( _("block size must be a power of two between 512 and "
+		       "%d\n"), getpagesize());
 
+	if (sdp->bsize < sdp->logical_block_size) {
+		die( _("Error: Block size %d is less than minimum logical "
+		       "block size (%d).\n"), sdp->bsize,
+		     sdp->logical_block_size);
+	}
+
+	if (sdp->bsize < sdp->physical_block_size) {
+		printf( _("WARNING: Block size %d is inefficient because it "
+			  "is less than the physical block size (%d).\n"),
+			  sdp->bsize, sdp->physical_block_size);
+		if (sdp->override)
+			return;
+
+		printf( _("\nAre you sure you want to proceed? [y/n] "));
+		if(!fgets(input, 32, stdin))
+			die( _("unable to read from stdin\n"));
+
+		if (input[0] != 'y')
+			die( _("aborted\n"));
+		else
+			printf("\n");
+	}
+}
+
+static void verify_arguments(struct gfs2_sbd *sdp)
+{
+	if (!sdp->expert)
+		test_locking(sdp->lockproto, sdp->locktable);
 	/* Look at this!  Why can't we go bigger than 2GB? */
 	if (sdp->expert) {
 		if (1 > sdp->rgsize || sdp->rgsize > 2048)
@@ -551,7 +580,7 @@ void main_mkfs(int argc, char *argv[])
 	unsigned char uuid[16];
 
 	memset(sdp, 0, sizeof(struct gfs2_sbd));
-	sdp->bsize = GFS2_DEFAULT_BSIZE;
+	sdp->bsize = -1;
 	sdp->jsize = GFS2_DEFAULT_JSIZE;
 	sdp->rgsize = -1;
 	sdp->utsize = GFS2_DEFAULT_UTSIZE;
@@ -578,6 +607,30 @@ void main_mkfs(int argc, char *argv[])
 	if (!sdp->override)
 		are_you_sure(sdp);
 
+	if (device_topology(sdp)) {
+		fprintf(stderr, _("Device topology error\n"));
+		exit(-1);
+	}
+
+	if (sdp->bsize == -1) {
+		/* See if optimal_io_size (the biggest I/O we can submit
+		   without incurring a penalty) is a suitable block size. */
+		if (sdp->optimal_io_size <= getpagesize() &&
+		    sdp->optimal_io_size >= sdp->minimum_io_size)
+			sdp->bsize = sdp->optimal_io_size;
+		/* See if physical_block_size (the smallest unit we can write
+		   without incurring read-modify-write penalty) is suitable. */
+		else if (sdp->physical_block_size <= getpagesize() &&
+			 sdp->physical_block_size >= GFS2_DEFAULT_BSIZE)
+			sdp->bsize = sdp->physical_block_size;
+		else
+			sdp->bsize = GFS2_DEFAULT_BSIZE;
+
+		if (sdp->debug)
+			printf("\nUsing block size: %u\n", sdp->bsize);
+	}
+	verify_bsize(sdp);
+
 	if (compute_constants(sdp)) {
 		fprintf(stderr, _("Bad constants (1)\n"));
 		exit(-1);


More information about the cluster-commits mailing list