[dm-devel] [PATCH] multipath: better argument type checking

Benjamin Marzinski bmarzins at redhat.com
Tue Oct 11 03:18:09 UTC 2011


The way that multipath decided what you passed in as an argument didn't
always work.  If the argument was the name of a file, then multipath
assumed that it was a path.  That meant if you were in /dev/mapper and ran

# multipath -f <mpath_device_name>

It would fail, since it thought you gave it a path name, instead of a
multipath device name.  Now multipath will only treat the argument
as a path name if it is a block device with a different major number than
device-mapper's.  Also, I've switched the MAJOR/MINOR/MKDEV macros to
work like kpartx, so that they can handle minor numbers over 255.

Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
---
 multipath/dev_t.h |   18 +++---------------
 multipath/main.c  |   30 +++++++++++++++++++++---------
 2 files changed, 24 insertions(+), 24 deletions(-)

Index: multipath-tools-111010/multipath/main.c
===================================================================
--- multipath-tools-111010.orig/multipath/main.c
+++ multipath-tools-111010/multipath/main.c
@@ -22,6 +22,8 @@
  * Copyright (c) 2005 Edward Goggin, EMC
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -51,6 +53,7 @@
 #include <errno.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include "dev_t.h"
 
 int logsink;
 
@@ -374,13 +377,29 @@ dump_config (void)
 	return 0;
 }
 
+static int
+get_dev_type(char *dev) {
+	struct stat buf;
+	int i;
+
+	if (stat(dev, &buf) == 0 && S_ISBLK(buf.st_mode)) {
+		if (dm_is_dm_major(MAJOR(buf.st_rdev)))
+			return DEV_DEVMAP;
+		return DEV_DEVNODE;
+	}
+	else if (sscanf(dev, "%d:%d", &i, &i) == 2)
+		return DEV_DEVT;
+	else
+		return DEV_DEVMAP;
+}
+
 int
 main (int argc, char *argv[])
 {
 	int arg;
 	extern char *optarg;
 	extern int optind;
-	int i, r = 1;
+	int r = 1;
 
 	if (getuid() != 0) {
 		fprintf(stderr, "need to be root\n");
@@ -478,14 +497,7 @@ main (int argc, char *argv[])
 			goto out;
 
 		strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
-
-		if (filepresent(conf->dev))
-			conf->dev_type = DEV_DEVNODE;
-		else if (sscanf(conf->dev, "%d:%d", &i, &i) == 2)
-			conf->dev_type = DEV_DEVT;
-		else
-			conf->dev_type = DEV_DEVMAP;
-
+		conf->dev_type = get_dev_type(conf->dev);
 	}
 	conf->daemon = 0;
 
Index: multipath-tools-111010/multipath/dev_t.h
===================================================================
--- multipath-tools-111010.orig/multipath/dev_t.h
+++ multipath-tools-111010/multipath/dev_t.h
@@ -1,15 +1,3 @@
-#define MINORBITS       20
-#define MINORMASK       ((1U << MINORBITS) - 1)
-
-#define MAJOR(dev)      ((unsigned int) ((dev) >> MINORBITS))
-#define MINOR(dev)      ((unsigned int) ((dev) & MINORMASK))
-#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))
-
-#define print_dev_t(buffer, dev)                                        \
-	sprintf((buffer), "%u:%u\n", MAJOR(dev), MINOR(dev))
-
-#define format_dev_t(buffer, dev)                                       \
-	({                                                              \
-		sprintf(buffer, "%u:%u", MAJOR(dev), MINOR(dev));       \
-		buffer;                                                 \
-	})
+#define MAJOR(dev)      ((dev & 0xfff00) >> 8)
+#define MINOR(dev)      ((dev & 0xff) | ((dev >> 12) & 0xfff00))
+#define MKDEV(ma,mi)    ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))




More information about the dm-devel mailing list