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>
bitmap-optimize
Karel Zak 2006-03-08 14:17:28 -05:00 committed by Theodore Ts'o
parent d2955d2216
commit 4db2f59a71
7 changed files with 240 additions and 6 deletions

View 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@

38
configure vendored
View File

@ -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

View 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

View 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

View 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@

View 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

View File

@ -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);