Gitweb:
http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: a8f852725fb3deb0f74f75daeb7eab631f8db8e9
Parent: c4b41dc01efd1ebbdbe2b6337543a0ff43bcefa5
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Mar 2 08:46:35 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Mar 2 08:53:34 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 bb13e46..b1ffdc3 100644
--- a/gfs2/libgfs2/device_geometry.c
+++ b/gfs2/libgfs2/device_geometry.c
@@ -10,10 +10,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 80a718c..9250663 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -18,6 +18,7 @@
#include <signal.h>
#include <sys/time.h>
#include <libintl.h>
+
#define _(String) gettext(String)
#include <linux/types.h>
@@ -191,7 +192,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);
@@ -258,12 +260,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 */
@@ -271,9 +271,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)
@@ -553,7 +582,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;
@@ -580,6 +609,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);