Whamcloud - gitweb
Add device-mapper support to the blkid library
authorKarel Zak <kzak@redhat.com>
Wed, 8 Mar 2006 19:17:28 +0000 (14:17 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 8 Mar 2006 19:17:28 +0000 (14:17 -0500)
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>
MCONFIG.in
configure
configure.in
lib/blkid/Makefile.in
lib/blkid/blkid.pc.in
lib/blkid/blkidP.h
lib/blkid/devname.c

index 991aaa0..5463dac 100644 (file)
@@ -66,13 +66,16 @@ MKINSTALLDIRS = @MKINSTALLDIRS@
 #
 # Library definitions
 #
+DEVMAPPER_LIBS = @DEVMAPPER_LIBS@
+STATIC_DEVMAPPER_LIBS = @STATIC_DEVMAPPER_LIBS@
+
 LIB = $(top_builddir)/lib
 LIBSS = $(LIB)/libss@LIB_EXT@
 LIBCOM_ERR = $(LIB)/libcom_err@LIB_EXT@
 LIBE2P = $(LIB)/libe2p@LIB_EXT@
 LIBEXT2FS = $(LIB)/libext2fs@LIB_EXT@
 LIBUUID = $(LIB)/libuuid@LIB_EXT@ @SOCKET_LIB@ 
-LIBBLKID = $(LIB)/libblkid@LIB_EXT@
+LIBBLKID = $(LIB)/libblkid@LIB_EXT@ $(DEVMAPPER_LIBS)
 LIBINTL = @LIBINTL@
 DEPLIBUUID = $(LIB)/libuuid@LIB_EXT@
 
@@ -81,7 +84,7 @@ STATIC_LIBCOM_ERR = $(LIB)/libcom_err@STATIC_LIB_EXT@
 STATIC_LIBE2P = $(LIB)/libe2p@STATIC_LIB_EXT@
 STATIC_LIBEXT2FS = $(LIB)/libext2fs@STATIC_LIB_EXT@
 STATIC_LIBUUID = $(LIB)/libuuid@STATIC_LIB_EXT@ @SOCKET_LIB@ 
-STATIC_LIBBLKID = $(LIB)/libblkid@STATIC_LIB_EXT@
+STATIC_LIBBLKID = $(LIB)/libblkid@STATIC_LIB_EXT@ $(STATIC_DEVMAPPER_LIBS)
 DEPSTATIC_LIBUUID = $(LIB)/libuuid@STATIC_LIB_EXT@
 
 PROFILED_LIBSS = $(LIB)/libss@PROFILED_LIB_EXT@
index e9d719b..2651745 100755 (executable)
--- a/configure
+++ b/configure
@@ -309,7 +309,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS E2FSPROGS_YEAR E2FSPROGS_MONTH E2FSPROGS_DAY E2FSPROGS_VERSION build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LD CPP EGREP LINUX_INCLUDE MAINTAINER_CMT HTREE_CMT ELF_CMT BSDLIB_CMT PROFILE_CMT CHECKER_CMT LIB_EXT STATIC_LIB_EXT PROFILED_LIB_EXT SWAPFS_CMT DEBUGFS_CMT IMAGER_CMT RESIZER_CMT E2FSCK_TYPE FSCK_PROG FSCK_MAN E2INITRD_PROG E2INITRD_MAN GETTEXT_PACKAGE PACKAGE VERSION SET_MAKE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE RANLIB ac_ct_RANLIB ALLOCA GLIBC21 HAVE_POSIX_PRINTF HAVE_ASPRINTF HAVE_SNPRINTF HAVE_WPRINTF LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB BINARY_TYPE LN LN_S MV CP RM CHMOD AWK SED PERL LDCONFIG AR ac_ct_AR STRIP ac_ct_STRIP BUILD_CC SIZEOF_SHORT SIZEOF_INT SIZEOF_LONG SIZEOF_LONG_LONG SOCKET_LIB DLOPEN_LIB LINUX_CMT CYGWIN_CMT UNIX_CMT root_prefix root_bindir root_sbindir root_libdir root_sysconfdir LDFLAG_STATIC SS_DIR ET_DIR DO_TEST_SUITE INTL_FLAGS BUILD_CFLAGS BUILD_LDFLAGS LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS E2FSPROGS_YEAR E2FSPROGS_MONTH E2FSPROGS_DAY E2FSPROGS_VERSION build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LD CPP EGREP LINUX_INCLUDE MAINTAINER_CMT HTREE_CMT ELF_CMT BSDLIB_CMT PROFILE_CMT CHECKER_CMT LIB_EXT STATIC_LIB_EXT PROFILED_LIB_EXT SWAPFS_CMT DEBUGFS_CMT IMAGER_CMT RESIZER_CMT E2FSCK_TYPE FSCK_PROG FSCK_MAN E2INITRD_PROG E2INITRD_MAN DEVMAPPER_REQ DEVMAPPER_PC_LIBS DEVMAPPER_LIBS STATIC_DEVMAPPER_LIBS GETTEXT_PACKAGE PACKAGE VERSION SET_MAKE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE RANLIB ac_ct_RANLIB ALLOCA GLIBC21 HAVE_POSIX_PRINTF HAVE_ASPRINTF HAVE_SNPRINTF HAVE_WPRINTF LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB BINARY_TYPE LN LN_S MV CP RM CHMOD AWK SED PERL LDCONFIG AR ac_ct_AR STRIP ac_ct_STRIP BUILD_CC SIZEOF_SHORT SIZEOF_INT SIZEOF_LONG SIZEOF_LONG_LONG SOCKET_LIB DLOPEN_LIB LINUX_CMT CYGWIN_CMT UNIX_CMT root_prefix root_bindir root_sbindir root_libdir root_sysconfdir LDFLAG_STATIC SS_DIR ET_DIR DO_TEST_SUITE INTL_FLAGS BUILD_CFLAGS BUILD_LDFLAGS LIBOBJS LTLIBOBJS'
 ac_subst_files='MCONFIG MAKEFILE_ELF MAKEFILE_BSDLIB MAKEFILE_PROFILE MAKEFILE_CHECKER MAKEFILE_LIBRARY'
 
 # Initialize some variables set by options.
@@ -861,6 +861,7 @@ Optional Features:
   --enable-dynamic-e2fsck build e2fsck dynamically
   --enable-fsck           build fsck wrapper program
   --enable-e2initrd-helper build e2initrd-helper program
+  --enable-blkid-devmapper  build with device-mapper support
   --disable-nls           do not use Native Language Support
   --disable-rpath         do not hardcode runtime library paths
 
@@ -3450,6 +3451,37 @@ echo "Building e2initrd helper by default"
 fi;
 
 
+# Check whether --enable-blkid-devmapper or --disable-blkid-devmapper was given.
+if test "${enable_blkid_devmapper+set}" = set; then
+  enableval="$enable_blkid_devmapper"
+  if test "$enableval" = "no"
+then
+       echo "Disabling device-mapper support"
+       DEVMAPPER_REQ=''
+       DEVMAPPER_LIBS=''
+       STATIC_DEVMAPPER_LIBS=''
+else
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_DEVMAPPER 1
+_ACEOF
+
+       echo "Enabling device-mapper support"
+
+       DEVMAPPER_REQ='libselinux libsepol'
+       DEVMAPPER_PC_LIBS='-ldevmapper'
+       DEVMAPPER_LIBS='-ldevmapper -lselinux -lsepol'
+       STATIC_DEVMAPPER_LIBS='/usr/lib/libdevmapper.a /usr/lib/libselinux.a /usr/lib/libsepol.a'
+
+fi
+
+else
+  echo "Disabling device-mapper support by default"
+
+fi;
+
+
+
+
 MAKEFILE_LIBRARY=$srcdir/lib/Makefile.library
 
 GETTEXT_PACKAGE=e2fsprogs
@@ -14969,6 +15001,10 @@ s,@FSCK_PROG@,$FSCK_PROG,;t t
 s,@FSCK_MAN@,$FSCK_MAN,;t t
 s,@E2INITRD_PROG@,$E2INITRD_PROG,;t t
 s,@E2INITRD_MAN@,$E2INITRD_MAN,;t t
+s,@DEVMAPPER_REQ@,$DEVMAPPER_REQ,;t t
+s,@DEVMAPPER_PC_LIBS@,$DEVMAPPER_PC_LIBS,;t t
+s,@DEVMAPPER_LIBS@,$DEVMAPPER_LIBS,;t t
+s,@STATIC_DEVMAPPER_LIBS@,$STATIC_DEVMAPPER_LIBS,;t t
 s,@GETTEXT_PACKAGE@,$GETTEXT_PACKAGE,;t t
 s,@PACKAGE@,$PACKAGE,;t t
 s,@VERSION@,$VERSION,;t t
index 44166b3..744301c 100644 (file)
@@ -480,6 +480,34 @@ echo "Building e2initrd helper by default"
 )
 AC_SUBST(E2INITRD_PROG)
 AC_SUBST(E2INITRD_MAN)
+dnl handle --enable-blkid-devmapper
+dnl
+AC_ARG_ENABLE([blkid-devmapper],
+[  --enable-blkid-devmapper  build with device-mapper support],
+[if test "$enableval" = "no"
+then
+       echo "Disabling device-mapper support"
+       DEVMAPPER_REQ=''
+       DEVMAPPER_LIBS=''
+       STATIC_DEVMAPPER_LIBS=''
+else
+       AC_DEFINE(HAVE_DEVMAPPER)
+       echo "Enabling device-mapper support"
+
+       DEVMAPPER_REQ='libselinux libsepol'
+       DEVMAPPER_PC_LIBS='-ldevmapper'
+       DEVMAPPER_LIBS='-ldevmapper -lselinux -lsepol'
+       STATIC_DEVMAPPER_LIBS='/usr/lib/libdevmapper.a /usr/lib/libselinux.a /usr/lib/libsepol.a'
+
+fi]
+,
+echo "Disabling device-mapper support by default"
+)
+AC_SUBST(DEVMAPPER_REQ)
+AC_SUBST(DEVMAPPER_PC_LIBS)
+AC_SUBST(DEVMAPPER_LIBS)
+AC_SUBST(STATIC_DEVMAPPER_LIBS)
+dnl
 dnl
 dnl
 MAKEFILE_LIBRARY=$srcdir/lib/Makefile.library
index 2dd9260..046f182 100644 (file)
@@ -37,7 +37,7 @@ ELF_SO_VERSION = 1
 ELF_IMAGE = libblkid
 ELF_MYDIR = blkid
 ELF_INSTALL_DIR = $(root_libdir)
-ELF_OTHER_LIBS = -L../.. -luuid
+ELF_OTHER_LIBS = -L../.. -luuid $(DEVMAPPER_LIBS)
 
 BSDLIB_VERSION = 2.0
 BSDLIB_IMAGE = libblkid
index fda7f92..510aa84 100644 (file)
@@ -6,6 +6,6 @@ includedir=@includedir@
 Name: blkid
 Description: Block device id library
 Version: @E2FSPROGS_VERSION@
-Requires: uuid
+Requires: uuid @DEVMAPPER_REQ@
 Cflags: -I${includedir} 
-Libs: -L${libdir} -lblkid
+Libs: -L${libdir} -lblkid @DEVMAPPER_PC_LIBS@
index e6d8e27..dfe0eca 100644 (file)
@@ -118,6 +118,7 @@ extern const char *blkid_devdirs[];
 /*
  * Priority settings for different types of devices
  */
+#define BLKID_PRI_DM   40
 #define BLKID_PRI_EVMS 30
 #define BLKID_PRI_LVM  20
 #define BLKID_PRI_MD   10
index 3b1ad89..0a13c47 100644 (file)
@@ -11,6 +11,8 @@
  * %End-Header%
  */
 
+#define _GNU_SOURCE 1
+
 #include <stdio.h>
 #include <string.h>
 #if HAVE_UNISTD_H
 
 #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);