[dm-devel] [PATCH] self-contained "kpartx kicker"
k-ueda at ct.jp.nec.com
k-ueda at ct.jp.nec.com
Thu Apr 7 01:16:15 UTC 2005
Hello,
I think that self-contained "kpartx kicker" which doesn't require
shell is needed for / on dm-multipath.
The attached patch makes kpartx works like /etc/dev.d/block/multipath.dev
if kpartx is called as "kpartx.dev".
The patch is for multipath-tools-0.4.4-pre8.
Any comments are welcome.
Background
----------
If you have / on a partition on dm-multipath device, kpartx has to
be launched on the initramfs.
/etc/dev.d/block/multipath.dev does it over hotplug event, but
multipath.dev is shell script.
In the initramfs of Fedora / RedHat, /bin/sh and any libraries aren't
included. I feel it is their policy and I think it isn't recommended
to run shell scritp on the initramfs of Fedora / RedHat.
So other kpartx kicker as a command is needed for Fedora / RedHat.
Proposal
--------
o Add the feature to kpartx which works like multipath.dev when it is
called as "kpartx.dev" over hotplug event.
(Following patch is an implementation for this proposal.)
o Add the feature to kpartx which scans some directory (like
/dev/mapper, /sys/block and so on) to search dm device and makes
device-map for only dm device.
If this feature is included, it is only necessary to launch the
feature once.
(No patch.)
o Add the feature to multipath command which launch kpartx after
the multipath device is created.
(No patch.)
I feel that the first one is straitforward solution, as using hotplug
is current trend.
Patch
-----
diff -rup multipath-tools-0.4.4-pre8/kpartx/kpartx.c kpartx-0.4.4-pre8/kpartx/kpartx.c
--- multipath-tools-0.4.4-pre8/kpartx/kpartx.c 2005-02-20 17:15:50.000000000 -0500
+++ kpartx-0.4.4-pre8/kpartx/kpartx.c 2005-04-06 20:47:51.000000000 -0400
@@ -22,6 +22,7 @@
#include <ctype.h>
#include <libdevmapper.h>
#include <devmapper.h>
+#include <linux/kdev_t.h>
#include "crc32.h"
@@ -124,7 +125,43 @@ find_devname_offset (char * device)
return (int)(q - device) + 1;
}
-
+
+static char *
+get_hotplug_device()
+{
+ unsigned int major, minor, off, len;
+ char *mapname = NULL, *devname = NULL, *device = NULL;
+ struct stat buf;
+
+ if(strcmp(getenv("ACTION"), "add"))
+ return NULL;
+
+ /* Get dm mapname for hotpluged device. */
+ if (!(devname = getenv("DEVNAME")))
+ return NULL;
+ if (stat(devname, &buf))
+ return NULL;
+ major = (unsigned int)MAJOR(buf.st_rdev);
+ minor = (unsigned int)MINOR(buf.st_rdev);
+ if (!(mapname = dm_mapname(major, minor))) /* Not dm device. */
+ return NULL;
+
+ off = find_devname_offset(devname);
+ len = strlen(mapname);
+ /* Dirname + mapname + \0 */
+ if (!(device = (char *)malloc(sizeof(char) * (off + len + 1))))
+ return NULL;
+
+ /* Create new device name. */
+ snprintf(device, off + 1, "%s", devname);
+ snprintf(device + off, len + 1, "%s", mapname);
+ if (strlen(device) != (off + len)) {
+ return NULL;
+ }
+
+ return device;
+}
+
int
main(int argc, char **argv){
int fd, i, j, k, n, op, off, arg;
@@ -132,12 +169,14 @@ main(int argc, char **argv){
struct pt *ptp;
enum action what = LIST;
char *p, *type, *diskdevice, *device;
+ char *progname;
int lower, upper;
int verbose = 0;
char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16];
char * loopdev = NULL;
char * delim = NULL;
int loopro = 0;
+ int hotplug = 0;
struct stat buf;
initpts();
@@ -147,8 +186,22 @@ main(int argc, char **argv){
type = device = diskdevice = NULL;
memset(&all, 0, sizeof(all));
memset(&partname, 0, sizeof(partname));
-
- if (argc < 2) {
+
+ /* Check whether hotplug mode. */
+ progname = strrchr(argv[0], '/');
+ if (!progname)
+ progname = argv[0];
+ else
+ progname++;
+ if (!strcmp(progname, "kpartx.dev")) { /* Hotplug mode */
+ hotplug = 1;
+
+ /* Setup for original kpartx variables */
+ if (!(device = get_hotplug_device()))
+ exit(1);
+ diskdevice = device;
+ what = ADD;
+ } else if (argc < 2) {
usage();
exit(1);
}
@@ -193,7 +246,8 @@ main(int argc, char **argv){
exit(1);
}
- if (optind == argc-2) {
+ if (hotplug) {
+ } else if (optind == argc-2) {
device = argv[optind];
diskdevice = argv[optind+1];
} else if (optind == argc-1) {
diff -rup multipath-tools-0.4.4-pre8/kpartx/devmapper.c kpartx-0.4.4-pre8/kpartx/devmapper.c
--- multipath-tools-0.4.4-pre8/kpartx/devmapper.c 2005-04-04 08:49:46.000000000 -0400
+++ kpartx-0.4.4-pre8/kpartx/devmapper.c 2005-04-06 20:48:51.000000000 -0400
@@ -121,3 +121,47 @@ dm_map_present (char * str)
dm_task_destroy (dmt);
return r;
}
+
+/* Copy from libmultipath/devmapper.c */
+char *
+dm_mapname(int major, int minor)
+{
+ unsigned next = 0;
+ struct dm_names *names;
+ struct dm_task *dmt;
+ char *mapname = NULL;
+ int len;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+ return 0;
+
+ dm_task_no_open_count(dmt);
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (!(names = dm_task_get_names(dmt)))
+ goto out;
+
+ if (!names->dev) {
+ printf("No devices found\n");
+ goto out;
+ }
+
+ do {
+ names = (void *) names + next;
+ if ((int) MAJOR(names->dev) == major &&
+ (int) MINOR(names->dev) == minor) {
+ printf("%s", names->name);
+ len = strlen(names->name) + 1;
+ mapname = malloc(len);
+ strncpy(mapname, names->name, len);
+ goto out;
+ }
+ next = names->next;
+ } while (next);
+
+ out:
+ dm_task_destroy(dmt);
+ return mapname;
+}
diff -rup multipath-tools-0.4.4-pre8/kpartx/devmapper.h kpartx-0.4.4-pre8/kpartx/devmapper.h
--- multipath-tools-0.4.4-pre8/kpartx/devmapper.h 2005-03-30 16:48:27.000000000 -0500
+++ kpartx-0.4.4-pre8/kpartx/devmapper.h 2005-04-06 20:35:51.000000000 -0400
@@ -2,3 +2,4 @@ int dm_prereq (char *, int, int, int);
int dm_simplecmd (int, const char *);
int dm_addmap (int, const char *, const char *, const char *, unsigned long);
int dm_map_present (char *);
+char * dm_mapname(int major, int minor);
Best regards,
Ky (Kiyoshi Ueda)
More information about the dm-devel
mailing list