diff options
author | Karel Zak <kzak@redhat.com> | 2006-03-08 14:17:28 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2006-03-08 14:17:28 -0500 |
commit | 4db2f59a718c18202a7ce1d559be18bfa1087747 (patch) | |
tree | 406b54316ab495dfec054b38db6cdf45f87cb876 /lib/blkid/devname.c | |
parent | d2955d2216889467c1694af3b6691da10712508f (diff) | |
download | e2fsprogs-4db2f59a718c18202a7ce1d559be18bfa1087747.tar.gz |
Add device-mapper support to the blkid library
On systems where is multi-path storage device is problem with duplicated
filesystems. The solution is select "the best" device. This is possible
by device-mapper library.
Short quotation from RH bugzilla:
With my patch, all dm devices remains in libblkid cache.
Only the top level dm devices are given high priority
and more appropriate node names (i.e. /dev/mapper/*) are used.
For example, if we have linear mapped dm device "ov1" over
dm device "disk1p3" which is multipath mapped to /dev/sdd3 and /dev/sdh3:
# dmsetup.static ls --tree
ov1 (253:5) <-- /dev/mapper/ov1 or /dev/dm-5
`-disk1p3 (253:4) <-- /dev/mapper/disk1p3 or /dev/dm-4
`-disk1 (253:0)
|- (8:112) <-- /dev/sdh
`- (8:48) <-- /dev/sdd
Original version of blkid will show:
# ./orig/blkid -t LABEL=mpdisk1p3 -l
/dev/sdd3: LABEL="mpdisk1p3" ... TYPE="ext3"
With my patch, blkid will show:
# ./deptree/blkid -t LABEL=mpdisk1p3 -l
/dev/mapper/ov1: LABEL="mpdisk1p3" ... TYPE="ext3"
In blkid cache, all devices are listed:
# ./orig/blkid -t LABEL=mpdisk1p3
/dev/sdd3: LABEL="mpdisk1p3" ... TYPE="ext3"
/dev/sdh3: LABEL="mpdisk1p3" ... TYPE="ext3"
/dev/dm-4: LABEL="mpdisk1p3" ... TYPE="ext3"
/dev/dm-5: LABEL="mpdisk1p3" ... TYPE="ext3"
# ./deptree/blkid -t LABEL=mpdisk1p3
/dev/mapper/ov1: LABEL="mpdisk1p3" ... TYPE="ext3"
/dev/sdd3: LABEL="mpdisk1p3" ... TYPE="ext3"
/dev/sdh3: LABEL="mpdisk1p3" ... TYPE="ext3"
/dev/dm-4: LABEL="mpdisk1p3" ... TYPE="ext3"
For more details see discussion on:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=156324
Addresses Red Hat Bug: #156324
Signed-off-by: Karel Zak <kzak@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'lib/blkid/devname.c')
-rw-r--r-- | lib/blkid/devname.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/lib/blkid/devname.c b/lib/blkid/devname.c index 3b1ad89b..0a13c477 100644 --- a/lib/blkid/devname.c +++ b/lib/blkid/devname.c @@ -11,6 +11,8 @@ * %End-Header% */ +#define _GNU_SOURCE 1 + #include <stdio.h> #include <string.h> #if HAVE_UNISTD_H @@ -35,6 +37,10 @@ #include "blkidP.h" +#ifdef HAVE_DEVMAPPER +#include <libdevmapper.h> +#endif + /* * Find a dev struct in the cache by device name, if available. * @@ -75,6 +81,10 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) return dev; } +#ifdef HAVE_DEVMAPPER +static int dm_device_is_leaf(const dev_t dev); +#endif + /* * Probe a single block device to add to the device cache. */ @@ -90,6 +100,10 @@ static void probe_one(blkid_cache cache, const char *ptname, list_for_each(p, &cache->bic_devs) { blkid_dev tmp = list_entry(p, struct blkid_struct_dev, bid_devs); +#ifdef HAVE_DEVMAPPER + if (!dm_device_is_leaf(devno)) + continue; +#endif if (tmp->bid_devno == devno) { if (only_if_new) return; @@ -137,6 +151,155 @@ set_pri: return; } +#ifdef HAVE_DEVMAPPER +/* + * device-mapper support + */ +static int dm_device_has_dep(const dev_t dev, const char *name) +{ + struct dm_task *task; + struct dm_deps *deps; + struct dm_info info; + int i; + + task = dm_task_create(DM_DEVICE_DEPS); + if (!task) + return 0; + + dm_task_set_name(task, name); + dm_task_run(task); + dm_task_get_info(task, &info); + + if (!info.exists) { + dm_task_destroy(task); + return 0; + } + + deps = dm_task_get_deps(task); + if (!deps || deps->count == 0) { + dm_task_destroy(task); + return 0; + } + + for (i = 0; i < deps->count; i++) { + dev_t dep_dev = deps->device[i]; + + if (dev == dep_dev) { + dm_task_destroy(task); + return 1; + } + } + + dm_task_destroy(task); + return 0; +} + +static int dm_device_is_leaf(const dev_t dev) +{ + struct dm_task *task; + struct dm_names *names; + unsigned int next = 0; + int n, ret = 1; + + task = dm_task_create(DM_DEVICE_LIST); + if (!task) + return 1; + + dm_task_run(task); + names = dm_task_get_names(task); + if (!names || !names->dev) { + dm_task_destroy(task); + return 1; + } + + n = 0; + do { + names = (void *)names + next; + + if (dm_device_has_dep(dev, names->name)) + ret = 0; + + next = names->next; + } while (next); + + dm_task_destroy(task); + + return ret; +} + +static dev_t dm_get_devno(const char *name) +{ + struct dm_task *task; + struct dm_info info; + dev_t ret = 0; + + task = dm_task_create(DM_DEVICE_INFO); + if (!task) + return ret; + + dm_task_set_name(task, name); + dm_task_run(task); + dm_task_get_info(task, &info); + + if (!info.exists) { + dm_task_destroy(task); + return ret; + } + + ret = makedev(info.major, info.minor); + + dm_task_destroy(task); + + return ret; +} + +static void dm_probe_all(blkid_cache cache, int only_if_new) +{ + struct dm_task *task; + struct dm_names *names; + unsigned int next = 0; + int n; + + task = dm_task_create(DM_DEVICE_LIST); + if (!task) + return; + + dm_task_run(task); + names = dm_task_get_names(task); + if (!names || !names->dev) { + dm_task_destroy(task); + return; + } + + n = 0; + do { + int rc; + char *device = NULL; + dev_t dev = 0; + + names = (void *)names + next; + + rc = asprintf(&device, "/dev/mapper/%s", names->name); + if (rc < 0) + goto try_next; + + dev = dm_get_devno(names->name); + if (dev == 0) + goto try_next; + + if (!dm_device_is_leaf(dev)) + goto try_next; + + probe_one(cache, device, dev, BLKID_PRI_DM, only_if_new); + +try_next: + next = names->next; + } while (next); + + dm_task_destroy(task); +} +#endif /* HAVE_DEVMAPPER */ + #define PROC_PARTITIONS "/proc/partitions" #define VG_DIR "/proc/lvm/VGs" @@ -290,6 +453,9 @@ static int probe_all(blkid_cache cache, int only_if_new) return 0; blkid_read_cache(cache); +#ifdef HAVE_DEVMAPPER + dm_probe_all(cache, only_if_new); +#endif evms_probe_all(cache, only_if_new); #ifdef VG_DIR lvm_probe_all(cache, only_if_new); |