summaryrefslogtreecommitdiff
path: root/lib/blkid/devname.c
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2006-03-08 14:17:28 -0500
committerTheodore Ts'o <tytso@mit.edu>2006-03-08 14:17:28 -0500
commit4db2f59a718c18202a7ce1d559be18bfa1087747 (patch)
tree406b54316ab495dfec054b38db6cdf45f87cb876 /lib/blkid/devname.c
parentd2955d2216889467c1694af3b6691da10712508f (diff)
downloade2fsprogs-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.c166
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);