diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index 314b0398c..74a24dca1 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,7 @@ Version 1.02.39 - ===================================== + Add dmsetup udevflags command to decode udev flags in given cookie value. + Add udev flags support in libdevmapper. Make libdm ABI consistent when built with/without selinux support. Version 1.02.38 - 25th September 2009 diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c index 861c009ef..8554eba33 100644 --- a/libdm/ioctl/libdm-iface.c +++ b/libdm/ioctl/libdm-iface.c @@ -1492,8 +1492,14 @@ static int _mknodes_v4(struct dm_task *dmt) */ static int _udev_complete(struct dm_task *dmt) { - if (dmt->cookie_set) - return dm_udev_complete(dmt->event_nr); + uint32_t cookie; + + if (dmt->cookie_set) { + /* strip flags from the cookie and use cookie magic instead */ + cookie = (dmt->event_nr & ~DM_UDEV_FLAGS_MASK) | + (DM_COOKIE_MAGIC << DM_UDEV_FLAGS_SHIFT); + return dm_udev_complete(cookie); + } return 1; } diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 204372aad..f25cef660 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -164,7 +164,7 @@ int dm_task_set_major_minor(struct dm_task *dmt, int major, int minor, int allow int dm_task_set_uid(struct dm_task *dmt, uid_t uid); int dm_task_set_gid(struct dm_task *dmt, gid_t gid); int dm_task_set_mode(struct dm_task *dmt, mode_t mode); -int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie); +int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags); int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr); int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start); int dm_task_set_message(struct dm_task *dmt, const char *message); @@ -1014,7 +1014,38 @@ int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field, void dm_report_field_set_value(struct dm_report_field *field, const void *value, const void *sortvalue); +/* Cookie prefixes. + * The cookie value consists of a prefix (16 bits) and a base (16 bits). + * We can use the prefix to store the flags. These flags are sent to + * kernel within given dm task. When returned back to userspace in + * DM_COOKIE udev environment variable, we can control several aspects + * of udev rules we use by decoding the cookie prefix. When doing the + * notification, we replace the cookie prefix with DM_COOKIE_MAGIC, + * so we notify the right semaphore. + */ #define DM_COOKIE_MAGIC 0x0D4D +#define DM_UDEV_FLAGS_MASK 0xFFFF0000 +#define DM_UDEV_FLAGS_SHIFT 16 +/* + * DM_UDEV_DISABLE_SUBSYTEM_RULES_FLAG is set in case we need to disable + * subsystem udev rules, but still we need the general DM udev rules to + * be applied (to create the nodes and symlinks under /dev and /dev/disk). + */ +#define DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 0x0001 +/* + * DM_UDEV_DISABLE_DISK_RULES_FLAG is set in case we need to disable + * general DM rules that set symlinks in /dev/disk directory. + */ +#define DM_UDEV_DISABLE_DISK_RULES_FLAG 0x0002 +/* + * DM_UDEV_LOW_PRIORITY_FLAG is set in case we need to instruct the + * udev rules to give low priority to the device that is currently + * processed. For example, this provides a way to select which symlinks + * could be overwritten by high priority ones if their names are equal. + * Common situation is a name based on FS UUID while using origin and + * snapshot devices. + */ +#define DM_UDEV_LOW_PRIORITY_FLAG 0x0004 int dm_cookie_supported(void); diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index 248d3ac75..3079c24b9 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -876,7 +876,7 @@ int dm_udev_get_sync_support(void) return 0; } -int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie) +int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { *cookie = 0; @@ -1129,7 +1129,7 @@ bad: return 0; } -int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie) +int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { int semid; @@ -1151,11 +1151,11 @@ int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie) goto bad; } - dmt->event_nr = *cookie; + dmt->event_nr = (0x0000FFFF & *cookie) | (flags << 16); dmt->cookie_set = 1; - log_debug("Udev cookie 0x%" PRIx32 " (semid %d) assigned to dm_task", - dmt->event_nr, semid); + log_debug("Udev cookie 0x%" PRIx32 " (semid %d) assigned to dm_task " + "with flags 0x%" PRIx16, *cookie, semid, flags); return 1; diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index 75fb20194..ef111265a 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -841,7 +841,7 @@ static int _deactivate_node(const char *name, uint32_t major, uint32_t minor, ui if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); - if (!dm_task_set_cookie(dmt, cookie)) + if (!dm_task_set_cookie(dmt, cookie, 0)) goto out; r = dm_task_run(dmt); @@ -881,7 +881,7 @@ static int _rename_node(const char *old_name, const char *new_name, uint32_t maj if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); - if (!dm_task_set_cookie(dmt, cookie)) + if (!dm_task_set_cookie(dmt, cookie, 0)) goto out; r = dm_task_run(dmt); @@ -924,7 +924,7 @@ static int _resume_node(const char *name, uint32_t major, uint32_t minor, if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags)) log_error("Failed to set read ahead"); - if (!dm_task_set_cookie(dmt, cookie)) + if (!dm_task_set_cookie(dmt, cookie, 0)) goto out; if ((r = dm_task_run(dmt))) diff --git a/tools/dmsetup.c b/tools/dmsetup.c index c3539a7fc..c0b9316e3 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -595,7 +595,7 @@ static int _create(int argc, char **argv, void *data __attribute((unused))) if (_switches[NOTABLE_ARG]) dm_udev_set_sync_support(0); - if (!dm_task_set_cookie(dmt, &cookie) || + if (!dm_task_set_cookie(dmt, &cookie, 0) || !dm_task_run(dmt)) goto out; @@ -630,7 +630,7 @@ static int _rename(int argc, char **argv, void *data __attribute((unused))) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; - if (!dm_task_set_cookie(dmt, &cookie) || + if (!dm_task_set_cookie(dmt, &cookie, 0) || !dm_task_run(dmt)) goto out; @@ -758,15 +758,70 @@ static int _splitname(int argc, char **argv, void *data __attribute((unused))) return r; } -static int _udevcomplete(int argc, char **argv, void *data __attribute((unused))) +static uint32_t _get_cookie_value(char *str_value) { - uint32_t cookie; + unsigned long int value; char *p; - if (!(cookie = (uint32_t) strtoul(argv[1], &p, 0)) || *p) { + if (!(value = strtoul(str_value, &p, 0)) || + *p || + (value == ULONG_MAX && errno == ERANGE) || + value > 0xFFFFFFFF) { err("Incorrect cookie value"); return 0; } + else + return (uint32_t) value; +} + +static int _udevflags(int args, char **argv, void *data __attribute((unused))) +{ + uint32_t cookie; + uint16_t flags; + int i; + static const char *dm_flag_names[] = {"DISABLE_SUBSYSTEM_RULES", + "DISABLE_DISK_RULES", + "LOW_PRIORITY", + 0, 0, 0, 0, 0}; + + if (!(cookie = _get_cookie_value(argv[1]))) + return 0; + + flags = cookie >> DM_UDEV_FLAGS_SHIFT; + + for (i = 0; i < DM_UDEV_FLAGS_SHIFT; i++) + if (1 << i & flags) { + if (i < DM_UDEV_FLAGS_SHIFT / 2 && dm_flag_names[i]) + printf("DM_UDEV_%s_FLAG='1'\n", dm_flag_names[i]); + else if (i < DM_UDEV_FLAGS_SHIFT / 2) + /* + * This is just a fallback. Each new DM flag + * should have its symbolic name assigned. + */ + printf("DM_UDEV_FLAG%d='1'\n", i); + else + /* + * We can't assign symbolic names to subsystem + * flags. Their semantics vary based on the + * subsystem that is currently used. + */ + printf("DM_SUBSYSTEM_UDEV_FLAG%d='1'\n", + i - DM_UDEV_FLAGS_SHIFT / 2); + } + + return 1; +} + +static int _udevcomplete(int argc, char **argv, void *data __attribute((unused))) +{ + uint32_t cookie; + + if (!(cookie = _get_cookie_value(argv[1]))) + return 0; + + /* strip flags from the cookie and use cookie magic instead */ + cookie = (cookie & ~DM_UDEV_FLAGS_MASK) | + (DM_COOKIE_MAGIC << DM_UDEV_FLAGS_SHIFT); return dm_udev_complete(cookie); } @@ -953,7 +1008,7 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display) _read_ahead_flags)) goto out; - if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie)) + if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, 0)) goto out; r = dm_task_run(dmt); @@ -2436,6 +2491,7 @@ static struct command _commands[] = { {"table", "[] [--target ] [--showkeys]", 0, 1, _status}, {"wait", " []", 0, 2, _wait}, {"mknodes", "[]", 0, 1, _mknodes}, + {"udevflags", "", 1, 1, _udevflags}, {"udevcomplete", "", 1, 1, _udevcomplete}, {"udevcomplete_all", "", 0, 0, _udevcomplete_all}, {"udevcookies", "", 0, 0, _udevcookies},