diff --git a/ChangeLog b/ChangeLog index 09f1cf0c..f61ee591 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2010-04-12 Milan Broz * Fix package config to use proper package version. * Avoid class C++ keyword in library header. + * Detect and use devmapper udev support if available (disable by --disable-udev). 2010-04-06 Milan Broz * Prefer some device paths in status display. diff --git a/configure.in b/configure.in index 3b8cd6c8..e7011ee4 100644 --- a/configure.in +++ b/configure.in @@ -42,7 +42,7 @@ LIBS=$saved_LIBS AM_PATH_LIBGCRYPT(1.1.42,,[AC_MSG_ERROR('You need the gcrypt library')]) -AC_CHECK_FUNCS([setlocale, posix_memalign]) +AC_CHECK_FUNCS([posix_memalign]) AC_C_CONST AC_C_BIGENDIAN @@ -76,10 +76,21 @@ AM_CONDITIONAL(STATIC_LIBRARY, test x$enable_shared_library = xno) AC_ARG_ENABLE(selinux, [ --disable-selinux disable selinux support [[default=auto]]],[], []) +AC_ARG_ENABLE([udev],AS_HELP_STRING([--disable-udev],[disable udev support]),[], enable_udev=yes) + saved_LIBS=$LIBS AC_CHECK_LIB(devmapper, dm_task_set_name,,[AC_MSG_ERROR('You need the device-mapper library')]) AC_CHECK_LIB(devmapper, dm_task_set_message,, [AC_MSG_ERROR([The device-mapper library on your system is too old.])]) + +AC_CHECK_FUNCS([dm_task_set_cookie], [have_cookie=yes], [have_cookie=no]) +if test "x$enable_udev" = xyes; then + if test "x$have_cookie" = xno; then + AC_MSG_ERROR([The device-mapper library on your system has no udev support, consider --disable-udev.]) + fi + AC_DEFINE(USE_UDEV, 1, [Try to use udev synchronisation?]) +fi + DEVMAPPER_LIBS=$LIBS LIBS=$saved_LIBS if test "x$enable_selinux" != xno; then diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 2834d334..036b9a70 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -22,6 +22,21 @@ static int _dm_use_count = 0; static struct crypt_device *_context = NULL; +/* Compatibility for old device-mapper without udev support */ +#ifndef HAVE_DM_TASK_SET_COOKIE +static int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { return 0; } +static int dm_udev_wait(uint32_t cookie) { return 0; }; +#endif + +static int _dm_use_udev() +{ +#ifdef USE_UDEV /* cannot be enabled if devmapper is too old */ + return dm_udev_get_sync_support(); +#else + return 0; +#endif +} + static void set_dm_error(int level, const char *file, int line, const char *f, ...) { @@ -40,14 +55,15 @@ static void set_dm_error(int level, const char *file, int line, va_end(va); } -static int _dm_simple(int task, const char *name); +static int _dm_simple(int task, const char *name, int udev_wait); int dm_init(struct crypt_device *context, int check_kernel) { if (!_dm_use_count++) { - log_dbg("Initialising device-mapper backend%s.", - check_kernel ? "" : " (NO kernel check requested)"); - if (check_kernel && !_dm_simple(DM_DEVICE_LIST_VERSIONS, NULL)) { + log_dbg("Initialising device-mapper backend%s, UDEV is %sabled.", + check_kernel ? "" : " (NO kernel check requested)", + _dm_use_udev() ? "en" : "dis"); + if (check_kernel && !_dm_simple(DM_DEVICE_LIST_VERSIONS, NULL, 0)) { log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n")); return -1; } @@ -207,10 +223,14 @@ out: } /* DM helpers */ -static int _dm_simple(int task, const char *name) +static int _dm_simple(int task, const char *name, int udev_wait) { int r = 0; struct dm_task *dmt; + uint32_t cookie = 0; + + if (!_dm_use_udev()) + udev_wait = 0; if (!(dmt = dm_task_create(task))) return 0; @@ -218,8 +238,13 @@ static int _dm_simple(int task, const char *name) if (name && !dm_task_set_name(dmt, name)) goto out; + if (udev_wait && !dm_task_set_cookie(dmt, &cookie, 0)); + r = dm_task_run(dmt); + if (r && udev_wait) + (void)dm_udev_wait(cookie); + out: dm_task_destroy(dmt); return r; @@ -248,8 +273,8 @@ static int _error_device(const char *name, size_t size) if (!dm_task_run(dmt)) goto error; - if (!_dm_simple(DM_DEVICE_RESUME, name)) { - _dm_simple(DM_DEVICE_CLEAR, name); + if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) { + _dm_simple(DM_DEVICE_CLEAR, name, 0); goto error; } @@ -270,7 +295,7 @@ int dm_remove_device(const char *name, int force, uint64_t size) return -EINVAL; do { - r = _dm_simple(DM_DEVICE_REMOVE, name) ? 0 : -EINVAL; + r = _dm_simple(DM_DEVICE_REMOVE, name, 1) ? 0 : -EINVAL; if (--retries && r) { log_dbg("WARNING: other process locked internal device %s, %s.", name, retries ? "retrying remove" : "giving up"); @@ -350,6 +375,7 @@ int dm_create_device(const char *name, char dev_uuid[DM_UUID_LEN] = {0}; int r = -EINVAL; uint32_t read_ahead = 0; + uint32_t cookie = 0; params = get_params(device, skip, offset, cipher, key_size, key); if (!params) @@ -373,8 +399,10 @@ int dm_create_device(const char *name, if (!dm_task_set_uuid(dmt, dev_uuid)) goto out_no_removal; - } + if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, 0)) + goto out_no_removal; + } if (read_only && !dm_task_set_ro(dmt)) goto out_no_removal; @@ -398,10 +426,15 @@ int dm_create_device(const char *name, goto out; if (uuid && !dm_task_set_uuid(dmt, dev_uuid)) goto out; + if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, 0)) + goto out; if (!dm_task_run(dmt)) goto out; } + if (_dm_use_udev()) + (void)dm_udev_wait(cookie); + if (!dm_task_get_info(dmt, &dmi)) goto out; @@ -620,11 +653,11 @@ static int _dm_message(const char *name, const char *msg) int dm_suspend_and_wipe_key(const char *name) { - if (!_dm_simple(DM_DEVICE_SUSPEND, name)) + if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0)) return -EINVAL; if (!_dm_message(name, "key wipe")) { - _dm_simple(DM_DEVICE_RESUME, name); + _dm_simple(DM_DEVICE_RESUME, name, 1); return -EINVAL; } @@ -648,7 +681,7 @@ int dm_resume_and_reinstate_key(const char *name, hex_key(&msg[8], key_size, key); if (!_dm_message(name, msg) || - !_dm_simple(DM_DEVICE_RESUME, name)) + !_dm_simple(DM_DEVICE_RESUME, name, 1)) r = -EINVAL; safe_free(msg);