From: Peter Rajnoha Date: Mon, 26 Oct 2009 14:29:33 +0000 (+0000) Subject: Several changes to udev support code: X-Git-Tag: v2_02_91~2567 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=421671b1c2aadc9babe96e353b788feaf272a832;p=lvm2.git Several changes to udev support code: - we have these levels when the udev rules are processed: 10-dm.rules --> [11-dm-.rules] --> [12-dm-permissions.rules] --> 13-dm-disk.rules --> [...all the other foreign rules...] --> 95-dm-notify.rules - each level can be disabled now by DM_UDEV_DISABLE_{DM, SUBSYSTEM, DISK, OTHER}_RULES_FLAG - add DM_UDEV_DISABLE_DM_RULES_FLAG to disable 10-dm.rules - add DM_UDEV_DISABLE_OTHER_RULES_FLAG to disable all the other (non-dm) rules. We cutoff these rules by using the 'last_rule', so this one should really be used with great care and in well-founded situations. We use this for lvm's hidden and layer devices now. - add a parameter for add_dev_node, rm_dev_node and rename_dev_node so it's possible to switch on/off udev checks - use DM_UDEV_DISABLE_DM_RULES_FLAG and DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG if there's no cookie set and we have resume, remove and rename ioctl. This could happen when someone uses the libdevmapper that is compiled with udev_sync but the software does not make use of it. This way we can switch off the rules and fallback to libdevmapper node creation so there's no udev/libdevmapper race. --- diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index ea8f1d173..a4ae9e0e1 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -1026,7 +1026,8 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, if (layer || !lv_is_visible(lv)) udev_flags |= DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG | - DM_UDEV_DISABLE_DISK_RULES_FLAG; + DM_UDEV_DISABLE_DISK_RULES_FLAG | + DM_UDEV_DISABLE_OTHER_RULES_FLAG; if (lv_is_cow(lv)) udev_flags |= DM_UDEV_LOW_PRIORITY_FLAG; diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c index 8554eba33..e49ac7127 100644 --- a/libdm/ioctl/libdm-iface.c +++ b/libdm/ioctl/libdm-iface.c @@ -731,24 +731,24 @@ static int _dm_task_run_v1(struct dm_task *dmt) switch (dmt->type) { case DM_DEVICE_CREATE: add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev), - dmt->uid, dmt->gid, dmt->mode); + dmt->uid, dmt->gid, dmt->mode, 0); break; case DM_DEVICE_REMOVE: - rm_dev_node(dmt->dev_name); + rm_dev_node(dmt->dev_name, 0); break; case DM_DEVICE_RENAME: - rename_dev_node(dmt->dev_name, dmt->newname); + rename_dev_node(dmt->dev_name, dmt->newname, 0); break; case DM_DEVICE_MKNODES: if (dmi->flags & DM_EXISTS_FLAG) add_dev_node(dmt->dev_name, MAJOR(dmi->dev), - MINOR(dmi->dev), - dmt->uid, dmt->gid, dmt->mode); + MINOR(dmi->dev), dmt->uid, + dmt->gid, dmt->mode, 0); else - rm_dev_node(dmt->dev_name); + rm_dev_node(dmt->dev_name, 0); break; case DM_DEVICE_STATUS: @@ -1534,6 +1534,8 @@ static int _create_and_load_v4(struct dm_task *dmt) task->uid = dmt->uid; task->gid = dmt->gid; task->mode = dmt->mode; + /* FIXME: Just for udev_check in dm_task_run. Can we avoid this? */ + task->cookie_set = dmt->cookie_set; r = dm_task_run(task); dm_task_destroy(task); @@ -1690,6 +1692,36 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, if (dmt->no_open_count) dmi->flags |= DM_SKIP_BDGET_FLAG; + /* + * Prevent udev vs. libdevmapper race when processing nodes and + * symlinks. This can happen when the udev rules are installed and + * udev synchronisation code is enabled in libdevmapper but the + * software using libdevmapper does not make use of it (by not calling + * dm_task_set_cookie before). We need to instruct the udev rules not + * to be applied at all in this situation so we can gracefully fallback + * to libdevmapper's node and symlink creation code. + */ + if (dm_udev_get_sync_support() && !dmt->cookie_set && + (dmt->type == DM_DEVICE_RESUME || + dmt->type == DM_DEVICE_REMOVE || + dmt->type == DM_DEVICE_RENAME)) { + log_debug("Cookie value is not set while trying to call " + "DM_DEVICE_RESUME, DM_DEVICE_REMOVE or DM_DEVICE_RENAME " + "ioctl. Please, consider using libdevmapper's udev " + "synchronisation interface or disable it explicitly " + "by calling dm_udev_set_sync_support(0)."); + log_debug("Switching off device-mapper and all subsystem related " + "udev rules. Falling back to libdevmapper node creation."); + /* + * Disable general dm and subsystem rules but keep dm disk rules + * if not flagged out explicitly before. We need /dev/disk content + * for the software that expects it. + */ + dmi->event_nr |= (DM_UDEV_DISABLE_DM_RULES_FLAG | + DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG) << + DM_UDEV_FLAGS_SHIFT; + } + log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s" "%s%c%c%s %.0" PRIu64 " %s [%u]", _cmd_data_v4[dmt->type].name, @@ -1741,6 +1773,7 @@ int dm_task_run(struct dm_task *dmt) { struct dm_ioctl *dmi; unsigned command; + int check_udev; #ifdef DM_COMPAT if (_dm_version == 1) @@ -1795,24 +1828,28 @@ repeat_ioctl: } } + check_udev = dmt->cookie_set && + !(dmt->event_nr >> DM_UDEV_FLAGS_SHIFT & + DM_UDEV_DISABLE_DM_RULES_FLAG); + switch (dmt->type) { case DM_DEVICE_CREATE: if (dmt->dev_name && *dmt->dev_name) add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev), dmt->uid, dmt->gid, - dmt->mode); + dmt->mode, check_udev); break; - case DM_DEVICE_REMOVE: /* FIXME Kernel needs to fill in dmi->name */ if (dmt->dev_name) - rm_dev_node(dmt->dev_name); + rm_dev_node(dmt->dev_name, check_udev); break; case DM_DEVICE_RENAME: /* FIXME Kernel needs to fill in dmi->name */ if (dmt->dev_name) - rename_dev_node(dmt->dev_name, dmt->newname); + rename_dev_node(dmt->dev_name, dmt->newname, + check_udev); break; case DM_DEVICE_RESUME: @@ -1824,10 +1861,10 @@ repeat_ioctl: case DM_DEVICE_MKNODES: if (dmi->flags & DM_EXISTS_FLAG) add_dev_node(dmi->name, MAJOR(dmi->dev), - MINOR(dmi->dev), - dmt->uid, dmt->gid, dmt->mode); + MINOR(dmi->dev), dmt->uid, + dmt->gid, dmt->mode, 0); else if (dmt->dev_name) - rm_dev_node(dmt->dev_name); + rm_dev_node(dmt->dev_name, 0); break; case DM_DEVICE_STATUS: diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 59460dab5..721e08a00 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -1035,17 +1035,33 @@ void dm_report_field_set_value(struct dm_report_field *field, const void *value, #define DM_COOKIE_MAGIC 0x0D4D #define DM_UDEV_FLAGS_MASK 0xFFFF0000 #define DM_UDEV_FLAGS_SHIFT 16 + +/* + * DM_UDEV_DISABLE_DM_RULES_FLAG is set in case we need to disable + * basic device-mapper udev rules that create symlinks in /dev/ + * directory. However, we can't reliably prevent creating default + * nodes by udev (commonly /dev/dm-X, where X is a number). + */ +#define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001 /* * 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 +#define DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 0x0002 /* * 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 +#define DM_UDEV_DISABLE_DISK_RULES_FLAG 0x0004 +/* + * DM_UDEV_DISABLE_OTHER_RULES_FLAG is set in case we need to disable + * all the other rules that are not general device-mapper nor subsystem + * related (the rules belong to other software or packages). Use this + * flag with care since it will cutoff the rule processing after the + * last device-mapper/subsytem rule is applied. + */ +#define DM_UDEV_DISABLE_OTHER_RULES_FLAG 0x0008 /* * 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 @@ -1054,7 +1070,7 @@ void dm_report_field_set_value(struct dm_report_field *field, const void *value, * Common situation is a name based on FS UUID while using origin and * snapshot devices. */ -#define DM_UDEV_LOW_PRIORITY_FLAG 0x0004 +#define DM_UDEV_LOW_PRIORITY_FLAG 0x0010 int dm_cookie_supported(void); diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index 3079c24b9..4232d5572 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -179,6 +179,7 @@ struct dm_task *dm_task_create(int type) dmt->no_open_count = 0; dmt->read_ahead = DM_READ_AHEAD_AUTO; dmt->read_ahead_flags = 0; + dmt->event_nr = 0; dmt->cookie_set = 0; return dmt; @@ -401,7 +402,7 @@ int dm_set_selinux_context(const char *path, mode_t mode) } static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor, - uid_t uid, gid_t gid, mode_t mode) + uid_t uid, gid_t gid, mode_t mode, int check_udev) { char path[PATH_MAX]; struct stat info; @@ -426,7 +427,7 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor, dev_name); return 0; } - } else if (dm_udev_get_sync_support()) + } else if (dm_udev_get_sync_support() && check_udev) log_warn("%s not set up by udev: Falling back to direct " "node creation.", path); @@ -451,7 +452,7 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor, return 1; } -static int _rm_dev_node(const char *dev_name) +static int _rm_dev_node(const char *dev_name, int check_udev) { char path[PATH_MAX]; struct stat info; @@ -460,7 +461,7 @@ static int _rm_dev_node(const char *dev_name) if (stat(path, &info) < 0) return 1; - else if (dm_udev_get_sync_support()) + else if (dm_udev_get_sync_support() && check_udev) log_warn("Node %s was not removed by udev. " "Falling back to direct node removal.", path); @@ -474,7 +475,8 @@ static int _rm_dev_node(const char *dev_name) return 1; } -static int _rename_dev_node(const char *old_name, const char *new_name) +static int _rename_dev_node(const char *old_name, const char *new_name, + int check_udev) { char oldpath[PATH_MAX]; char newpath[PATH_MAX]; @@ -489,7 +491,7 @@ static int _rename_dev_node(const char *old_name, const char *new_name) "is already present", newpath); return 0; } - else if (dm_udev_get_sync_support()) { + else if (dm_udev_get_sync_support() && check_udev) { if (stat(oldpath, &info) < 0 && errno == ENOENT) /* assume udev already deleted this */ @@ -499,7 +501,7 @@ static int _rename_dev_node(const char *old_name, const char *new_name) "by udev but old node is still present. " "Falling back to direct old node removal.", oldpath, newpath); - return _rm_dev_node(old_name); + return _rm_dev_node(old_name, 0); } } @@ -513,7 +515,7 @@ static int _rename_dev_node(const char *old_name, const char *new_name) return 0; } } - else if (dm_udev_get_sync_support()) + else if (dm_udev_get_sync_support() && check_udev) log_warn("The node %s should have been renamed to %s " "by udev but new node is not present. " "Falling back to direct node rename.", @@ -652,15 +654,16 @@ typedef enum { static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major, uint32_t minor, uid_t uid, gid_t gid, mode_t mode, const char *old_name, uint32_t read_ahead, - uint32_t read_ahead_flags) + uint32_t read_ahead_flags, int check_udev) { switch (type) { case NODE_ADD: - return _add_dev_node(dev_name, major, minor, uid, gid, mode); + return _add_dev_node(dev_name, major, minor, uid, gid, + mode, check_udev); case NODE_DEL: - return _rm_dev_node(dev_name); + return _rm_dev_node(dev_name, check_udev); case NODE_RENAME: - return _rename_dev_node(old_name, dev_name); + return _rename_dev_node(old_name, dev_name, check_udev); case NODE_READ_AHEAD: return _set_dev_node_read_ahead(dev_name, read_ahead, read_ahead_flags); @@ -683,6 +686,7 @@ struct node_op_parms { uint32_t read_ahead; uint32_t read_ahead_flags; char *old_name; + int check_udev; char names[0]; }; @@ -696,7 +700,7 @@ static void _store_str(char **pos, char **ptr, const char *str) static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major, uint32_t minor, uid_t uid, gid_t gid, mode_t mode, const char *old_name, uint32_t read_ahead, - uint32_t read_ahead_flags) + uint32_t read_ahead_flags, int check_udev) { struct node_op_parms *nop; struct dm_list *noph, *nopht; @@ -730,6 +734,7 @@ static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major, nop->mode = mode; nop->read_ahead = read_ahead; nop->read_ahead_flags = read_ahead_flags; + nop->check_udev = check_udev; _store_str(&pos, &nop->dev_name, dev_name); _store_str(&pos, &nop->old_name, old_name); @@ -748,35 +753,37 @@ static void _pop_node_ops(void) nop = dm_list_item(noph, struct node_op_parms); _do_node_op(nop->type, nop->dev_name, nop->major, nop->minor, nop->uid, nop->gid, nop->mode, nop->old_name, - nop->read_ahead, nop->read_ahead_flags); + nop->read_ahead, nop->read_ahead_flags, + nop->check_udev); dm_list_del(&nop->list); dm_free(nop); } } int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor, - uid_t uid, gid_t gid, mode_t mode) + uid_t uid, gid_t gid, mode_t mode, int check_udev) { log_debug("%s: Stacking NODE_ADD (%" PRIu32 ",%" PRIu32 ") %u:%u 0%o", dev_name, major, minor, uid, gid, mode); - return _stack_node_op(NODE_ADD, dev_name, major, minor, uid, gid, mode, - "", 0, 0); + return _stack_node_op(NODE_ADD, dev_name, major, minor, uid, + gid, mode, "", 0, 0, check_udev); } -int rename_dev_node(const char *old_name, const char *new_name) +int rename_dev_node(const char *old_name, const char *new_name, int check_udev) { log_debug("%s: Stacking NODE_RENAME to %s", old_name, new_name); - return _stack_node_op(NODE_RENAME, new_name, 0, 0, 0, 0, 0, old_name, - 0, 0); + return _stack_node_op(NODE_RENAME, new_name, 0, 0, 0, + 0, 0, old_name, 0, 0, check_udev); } -int rm_dev_node(const char *dev_name) +int rm_dev_node(const char *dev_name, int check_udev) { log_debug("%s: Stacking NODE_DEL (replaces other stacked ops)", dev_name); - return _stack_node_op(NODE_DEL, dev_name, 0, 0, 0, 0, 0, "", 0, 0); + return _stack_node_op(NODE_DEL, dev_name, 0, 0, 0, + 0, 0, "", 0, 0, check_udev); } int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead, @@ -788,8 +795,8 @@ int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead, log_debug("%s: Stacking NODE_READ_AHEAD %" PRIu32 " (flags=%" PRIu32 ")", dev_name, read_ahead, read_ahead_flags); - return _stack_node_op(NODE_READ_AHEAD, dev_name, 0, 0, 0, 0, 0, "", - read_ahead, read_ahead_flags); + return _stack_node_op(NODE_READ_AHEAD, dev_name, 0, 0, 0, 0, + 0, "", read_ahead, read_ahead_flags, 0); } void update_devs(void) diff --git a/libdm/libdm-common.h b/libdm/libdm-common.h index 9f11902ee..fcb334f84 100644 --- a/libdm/libdm-common.h +++ b/libdm/libdm-common.h @@ -23,9 +23,10 @@ struct target *create_target(uint64_t start, const char *type, const char *params); int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major, - uid_t uid, gid_t gid, mode_t mode); -int rm_dev_node(const char *dev_name); -int rename_dev_node(const char *old_name, const char *new_name); + uid_t uid, gid_t gid, mode_t mode, int check_udev); +int rm_dev_node(const char *dev_name, int check_udev); +int rename_dev_node(const char *old_name, const char *new_name, + int check_udev); int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead); int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead, uint32_t read_ahead_flags); diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index 7a3333de9..c98fb3474 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -873,7 +873,7 @@ static int _deactivate_node(const char *name, uint32_t major, uint32_t minor, r = dm_task_run(dmt); /* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */ - rm_dev_node(name); + rm_dev_node(name, dmt->cookie_set); /* FIXME Remove node from tree or mark invalid? */ diff --git a/tools/dmsetup.c b/tools/dmsetup.c index c0b9316e3..a7f1d257f 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -779,10 +779,12 @@ 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", + static const char *dm_flag_names[] = {"DISABLE_DM_RULES", + "DISABLE_SUBSYSTEM_RULES", "DISABLE_DISK_RULES", + "DISABLE_OTHER_RULES", "LOW_PRIORITY", - 0, 0, 0, 0, 0}; + 0, 0, 0}; if (!(cookie = _get_cookie_value(argv[1]))) return 0; diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in index 211c0c31a..9c2e25680 100644 --- a/udev/10-dm.rules.in +++ b/udev/10-dm.rules.in @@ -21,8 +21,16 @@ TEST!="$env{DM_SBIN_PATH}/dmsetup", ENV{DM_SBIN_PATH}="/usr/sbin" TEST!="$env{DM_SBIN_PATH}/dmsetup", GOTO="dm_end" # Decode udev control flags and set environment variables appropriately. +# These flags are encoded in DM_COOKIE variable that was introduced in +# kernel version 2.6.31. Therefore, we can use this feature with +# kernels >= 2.6.31 only. ENV{DM_COOKIE}=="?*", IMPORT{program}="$env{DM_SBIN_PATH}/dmsetup udevflags $env{DM_COOKIE}" +# Normally, we would test for DM_UDEV_DISABLE_DM_RULES_FLAG here and skip +# the rules if set. However, we need to set DM_* environment variables +# for now to properly filter out inappropriate events. This dependency +# might be removed in the future. + ACTION!="add|change", GOTO="dm_end" # Normally, we operate on "change" events only. But when @@ -58,18 +66,19 @@ ENV{DM_SUSPENDED}=="Suspended", ENV{DM_SUSPENDED}="1" # possible future changes. ENV{DM_UDEV_RULES_VSN}="1" -ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}" +ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}" # We have to ignore further rule application for inappropriate events # and devices. But still send the notification if cookie exists. -ENV{DM_UUID}=="mpath-?*", ENV{DM_ACTION}=="PATH_FAILED", GOTO="dm_last_rule" -ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="dm_last_rule" -ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="dm_last_rule" +ENV{DM_UUID}=="mpath-?*", ENV{DM_ACTION}=="PATH_FAILED", GOTO="dm_disable" +ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="dm_disable" +ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="dm_disable" GOTO="dm_end" -LABEL="dm_last_rule" -ENV{DM_COOKIE}=="?*", RUN+="$env{DM_SBIN_PATH}/dmsetup udevcomplete $env{DM_COOKIE}" -OPTIONS+="last_rule" +LABEL="dm_disable" +ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1" +ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1" +ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" LABEL="dm_end" diff --git a/udev/11-dm-lvm.rules b/udev/11-dm-lvm.rules index bcec09502..674a7de52 100644 --- a/udev/11-dm-lvm.rules +++ b/udev/11-dm-lvm.rules @@ -17,7 +17,7 @@ ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end" # Use DM name and split it up into its VG/LV/layer constituents. IMPORT{program}="$env{DM_SBIN_PATH}/dmsetup splitname --nameprefixes --noheadings --rows $env{DM_NAME}" -# Do not create symlinks for hidden subdevices. +# Do not create symlinks for inappropriate subdevices. ENV{DM_LV_NAME}=="?*_mimage_[0-9]*|pvmove?*|?*_vorigin", GOTO="lvm_end" # Create symlinks for top-level devices only. diff --git a/udev/13-dm-disk.rules b/udev/13-dm-disk.rules index 16a6edd25..94250ddf6 100644 --- a/udev/13-dm-disk.rules +++ b/udev/13-dm-disk.rules @@ -7,17 +7,26 @@ # "add" event is processed on coldplug only! ACTION!="add|change", GOTO="dm_end" -ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="dm_end" -ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="dm_end" +ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="dm_other" +ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="dm_other" SYMLINK+="disk/by-id/dm-name-$env{DM_NAME}" ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}" -ENV{DM_SUSPENDED}=="1", GOTO="dm_end" +ENV{DM_SUSPENDED}=="1", GOTO="dm_other" IMPORT{program}="$env{DM_SBIN_PATH}/blkid -o udev -p $tempnode" ENV{DM_UDEV_LOW_PRIORITY_FLAG}=="1", OPTIONS="link_priority=-100" ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}" ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}" +# Cutoff all subsequent rules if instructed by a flag. +# This flag should be used in well-founded situations only to prevent +# any problems that could arise when processing this event further by +# foreign rules (various temporary and hidden devices mostly). +LABEL="dm_other" +ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="dm_end" +ENV{DM_COOKIE}=="?*", RUN+="$env{DM_SBIN_PATH}/dmsetup udevcomplete $env{DM_COOKIE}" +OPTIONS+="last_rule" + LABEL="dm_end" diff --git a/udev/Makefile.in b/udev/Makefile.in index 341479f03..0a0050af3 100644 --- a/udev/Makefile.in +++ b/udev/Makefile.in @@ -16,8 +16,8 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ VPATH = @srcdir@ -DM_RULES=10-dm.rules 12-dm-disk.rules 95-dm-notify.rules -LVM_RULES=11-lvm.rules +DM_RULES=10-dm.rules 13-dm-disk.rules 95-dm-notify.rules +LVM_RULES=11-dm-lvm.rules DM_DIR=$(shell grep "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | awk '{print $$3}') CLEAN_TARGETS=10-dm.rules