From cda69e17ef44ad6d42442312d81e6d853fa1f49f Mon Sep 17 00:00:00 2001 From: Peter Rajnoha Date: Thu, 7 Jan 2010 19:54:21 +0000 Subject: [PATCH] Add activation/udev_rules config option in lvm.conf. Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags. --- WHATS_NEW | 1 + WHATS_NEW_DM | 1 + doc/example.conf | 9 ++++++- lib/activate/dev_manager.c | 23 +++++++++++++++-- lib/activate/fs.c | 52 ++++++++++++++++++++++---------------- lib/activate/fs.h | 5 ++-- lib/commands/toolcontext.c | 4 +++ lib/commands/toolcontext.h | 1 + lib/config/defaults.h | 1 + libdm/.exported_symbols | 1 + libdm/libdevmapper.h | 2 ++ libdm/libdm-deptree.c | 21 ++++++++++----- 12 files changed, 88 insertions(+), 33 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 2a75ad19a..d2a3cf64d 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.57 - ==================================== + Add activation/udev_rules config option in lvm.conf. Add macro outfc() and export out_text_with_comment(). Add macros outsize() and outhint(). Use offsetof() macro for FIELD() macro in lib/report/report.c. diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index 7a5df35ea..7f06a2f62 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,6 @@ Version 1.02.41 - ==================================== + Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags. Add --noudevrules option for dmsetup to disable /dev node management by udev. Update code to show all fields for 'dmsetup info -c -o all'. Return error from dm_tree_deactivate_children(). diff --git a/doc/example.conf b/doc/example.conf index 045006712..4b92b1f87 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -323,7 +323,7 @@ global { } activation { - # Set to 0 to disable udev syncronisation (if compiled into the binaries). + # Set to 0 to disable udev synchronisation (if compiled into the binaries). # Processes will not wait for notification from udev. # They will continue irrespective of any possible udev processing # in the background. You should only use this if udev is not running @@ -333,6 +333,13 @@ activation { # waiting for udev, run 'dmsetup udevcomplete_all' manually to wake them up. udev_sync = 1 + # Set to 0 to disable the udev rules installed by LVM2 (if built with + # --enable-udev_rules). LVM2 will then manage the /dev nodes and symlinks + # for active logical volumes directly itself. + # N.B. Manual intervention may be required if this setting is changed + # while any logical volumes are active. + udev_rules = 1 + # How to fill in missing stripes if activating an incomplete volume. # Using "error" will make inaccessible parts of the device return # I/O errors on access. You can instead use a device path, in which diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index bac0c7b52..bf6928600 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -658,6 +658,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, { char *dlid, *name; struct dm_info info, info2; + uint16_t udev_flags = 0; if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; @@ -695,7 +696,20 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, } } - if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) { + if (layer || !lv_is_visible(lv)) + udev_flags |= DM_UDEV_DISABLE_SUBSYSTEM_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; + + if (!dm->cmd->current_settings.udev_rules) + udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG | + DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG; + + if (info.exists && !dm_tree_add_dev_with_udev_flags(dtree, info.major, + info.minor, udev_flags)) { log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree", info.major, info.minor); return 0; @@ -1034,6 +1048,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, if (lv_is_cow(lv)) udev_flags |= DM_UDEV_LOW_PRIORITY_FLAG; + if (!dm->cmd->current_settings.udev_rules) + udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG | + DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG; + /* * Add LV to dtree. * If we're working with precommitted metadata, clear any @@ -1151,7 +1169,8 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root if (*layer) continue; - fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname); + fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname, + dm->cmd->current_settings.udev_rules); } return r; diff --git a/lib/activate/fs.c b/lib/activate/fs.c index 6e4f91a9e..d1691b854 100644 --- a/lib/activate/fs.c +++ b/lib/activate/fs.c @@ -108,7 +108,7 @@ static void _rm_blks(const char *dir) } static int _mk_link(const char *dev_dir, const char *vg_name, - const char *lv_name, const char *dev) + const char *lv_name, const char *dev, int check_udev) { char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX]; char vg_path[PATH_MAX]; @@ -166,7 +166,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name, return 0; } - if (dm_udev_get_sync_support()) { + if (dm_udev_get_sync_support() && check_udev) { /* Check udev created the correct link. */ if (!stat(link_path, &buf_lp) && !stat(lv_path, &buf)) { @@ -190,7 +190,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name, log_sys_error("unlink", lv_path); return 0; } - } else if (dm_udev_get_sync_support()) + } else if (dm_udev_get_sync_support() && check_udev) log_warn("The link %s should had been created by udev " "but it was not found. Falling back to " "direct link creation.", lv_path); @@ -208,7 +208,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name, } static int _rm_link(const char *dev_dir, const char *vg_name, - const char *lv_name) + const char *lv_name, int check_udev) { struct stat buf; char lv_path[PATH_MAX]; @@ -221,7 +221,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name, if (lstat(lv_path, &buf) && errno == ENOENT) return 1; - else if (dm_udev_get_sync_support()) + else if (dm_udev_get_sync_support() && check_udev) log_warn("The link %s should have been removed by udev " "but it is still present. Falling back to " "direct link removal.", lv_path); @@ -248,25 +248,26 @@ typedef enum { static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name, const char *lv_name, const char *dev, - const char *old_lv_name) + const char *old_lv_name, int check_udev) { switch (type) { case FS_ADD: if (!_mk_dir(dev_dir, vg_name) || - !_mk_link(dev_dir, vg_name, lv_name, dev)) + !_mk_link(dev_dir, vg_name, lv_name, dev, check_udev)) return_0; break; case FS_DEL: - if (!_rm_link(dev_dir, vg_name, lv_name) || + if (!_rm_link(dev_dir, vg_name, lv_name, check_udev) || !_rm_dir(dev_dir, vg_name)) return_0; break; /* FIXME Use rename() */ case FS_RENAME: - if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name)) + if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name, + check_udev)) stack; - if (!_mk_link(dev_dir, vg_name, lv_name, dev)) + if (!_mk_link(dev_dir, vg_name, lv_name, dev, check_udev)) stack; } @@ -278,6 +279,7 @@ static DM_LIST_INIT(_fs_ops); struct fs_op_parms { struct dm_list list; fs_op_t type; + int check_udev; char *dev_dir; char *vg_name; char *lv_name; @@ -295,7 +297,7 @@ static void _store_str(char **pos, char **ptr, const char *str) static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name, const char *lv_name, const char *dev, - const char *old_lv_name) + const char *old_lv_name, int check_udev) { struct fs_op_parms *fsp; size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) + @@ -309,6 +311,7 @@ static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name, pos = fsp->names; fsp->type = type; + fsp->check_udev = check_udev; _store_str(&pos, &fsp->dev_dir, dev_dir); _store_str(&pos, &fsp->vg_name, vg_name); @@ -329,40 +332,43 @@ static void _pop_fs_ops(void) dm_list_iterate_safe(fsph, fspht, &_fs_ops) { fsp = dm_list_item(fsph, struct fs_op_parms); _do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name, - fsp->dev, fsp->old_lv_name); + fsp->dev, fsp->old_lv_name, fsp->check_udev); dm_list_del(&fsp->list); dm_free(fsp); } } static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name, - const char *lv_name, const char *dev, const char *old_lv_name) + const char *lv_name, const char *dev, const char *old_lv_name, + int check_udev) { if (memlock()) { if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev, - old_lv_name)) + old_lv_name, check_udev)) return_0; return 1; } - return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name); + return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, + old_lv_name, check_udev); } int fs_add_lv(const struct logical_volume *lv, const char *dev) { return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name, - dev, ""); + dev, "", lv->vg->cmd->current_settings.udev_rules); } int fs_del_lv(const struct logical_volume *lv) { return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name, - "", ""); + "", "", lv->vg->cmd->current_settings.udev_rules); } -int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name) +int fs_del_lv_byname(const char *dev_dir, const char *vg_name, + const char *lv_name, int check_udev) { - return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", ""); + return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "", check_udev); } int fs_rename_lv(struct logical_volume *lv, const char *dev, @@ -370,12 +376,14 @@ int fs_rename_lv(struct logical_volume *lv, const char *dev, { if (strcmp(old_vgname, lv->vg->name)) { return - (_fs_op(FS_DEL, lv->vg->cmd->dev_dir, old_vgname, old_lvname, "", "") && - _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name, dev, "")); + (_fs_op(FS_DEL, lv->vg->cmd->dev_dir, old_vgname, + old_lvname, "", "", lv->vg->cmd->current_settings.udev_rules) && + _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, + lv->name, dev, "", lv->vg->cmd->current_settings.udev_rules)); } else return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name, - dev, old_lvname); + dev, old_lvname, lv->vg->cmd->current_settings.udev_rules); } void fs_unlock(void) diff --git a/lib/activate/fs.h b/lib/activate/fs.h index 998f48fc1..28b2c73f5 100644 --- a/lib/activate/fs.h +++ b/lib/activate/fs.h @@ -25,9 +25,10 @@ */ int fs_add_lv(const struct logical_volume *lv, const char *dev); int fs_del_lv(const struct logical_volume *lv); -int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name); +int fs_del_lv_byname(const char *dev_dir, const char *vg_name, + const char *lv_name, int check_udev); int fs_rename_lv(struct logical_volume *lv, const char *dev, - const char *old_vgname, const char *old_lvname); + const char *old_vgname, const char *old_lvname); void fs_unlock(void); #endif diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index bb3e5d21d..a076e93f6 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -267,6 +267,10 @@ static int _process_config(struct cmd_context *cmd) return 0; } + cmd->default_settings.udev_rules = find_config_tree_int(cmd, + "activation/udev_rules", + DEFAULT_UDEV_RULES); + cmd->default_settings.udev_sync = find_config_tree_int(cmd, "activation/udev_sync", DEFAULT_UDEV_SYNC); diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 2ffc86d9d..eac572179 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -34,6 +34,7 @@ struct config_info { int archive; /* should we archive ? */ int backup; /* should we backup ? */ int read_ahead; /* DM_READ_AHEAD_NONE or _AUTO */ + int udev_rules; int udev_sync; int cache_vgmetadata; const char *msg_prefix; diff --git a/lib/config/defaults.h b/lib/config/defaults.h index da13fc2b3..94057e4d9 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -67,6 +67,7 @@ #define DEFAULT_PVMETADATACOPIES 1 #define DEFAULT_LABELSECTOR UINT64_C(1) #define DEFAULT_READ_AHEAD "auto" +#define DEFAULT_UDEV_RULES 1 #define DEFAULT_UDEV_SYNC 0 #define DEFAULT_EXTENT_SIZE 4096 /* In KB */ #define DEFAULT_MAX_PV 0 diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols index 554b90a91..1555e4227 100644 --- a/libdm/.exported_symbols +++ b/libdm/.exported_symbols @@ -50,6 +50,7 @@ dm_format_dev dm_tree_create dm_tree_free dm_tree_add_dev +dm_tree_add_dev_with_udev_flags dm_tree_add_new_dev dm_tree_add_new_dev_with_udev_flags dm_tree_node_get_name diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index c6546a63b..4c4734fd0 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -267,6 +267,8 @@ void dm_tree_free(struct dm_tree *tree); * Add nodes to the tree for a given device and all the devices it uses. */ int dm_tree_add_dev(struct dm_tree *tree, uint32_t major, uint32_t minor); +int dm_tree_add_dev_with_udev_flags(struct dm_tree *tree, uint32_t major, + uint32_t minor, uint16_t udev_flags); /* * Add a new node to the tree if it doesn't already exist. diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index 0128217a1..a9836953f 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -454,7 +454,8 @@ failed: static struct dm_tree_node *_add_dev(struct dm_tree *dtree, struct dm_tree_node *parent, - uint32_t major, uint32_t minor) + uint32_t major, uint32_t minor, + uint16_t udev_flags) { struct dm_task *dmt = NULL; struct dm_info info; @@ -471,7 +472,7 @@ static struct dm_tree_node *_add_dev(struct dm_tree *dtree, return_NULL; if (!(node = _create_dm_tree_node(dtree, name, uuid, &info, - NULL, 0))) + NULL, udev_flags))) goto_out; new = 1; } @@ -497,7 +498,7 @@ static struct dm_tree_node *_add_dev(struct dm_tree *dtree, /* Add dependencies to tree */ for (i = 0; i < deps->count; i++) if (!_add_dev(dtree, node, MAJOR(deps->device[i]), - MINOR(deps->device[i]))) { + MINOR(deps->device[i]), udev_flags)) { node = NULL; goto_out; } @@ -652,7 +653,13 @@ void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode, int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor) { - return _add_dev(dtree, &dtree->root, major, minor) ? 1 : 0; + return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0; +} + +int dm_tree_add_dev_with_udev_flags(struct dm_tree *dtree, uint32_t major, + uint32_t minor, uint16_t udev_flags) +{ + return _add_dev(dtree, &dtree->root, major, minor, udev_flags) ? 1 : 0; } const char *dm_tree_node_get_name(struct dm_tree_node *node) @@ -873,7 +880,8 @@ 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, dmt->cookie_set); + rm_dev_node(name, dmt->cookie_set && + !(udev_flags & DM_UDEV_DISABLE_DM_RULES_FLAG)); /* FIXME Remove node from tree or mark invalid? */ @@ -1963,7 +1971,8 @@ int dm_tree_node_add_target_area(struct dm_tree_node *node, } /* FIXME Check correct macro use */ - if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev), MINOR(info.st_rdev)))) + if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev), + MINOR(info.st_rdev), 0))) return_0; } -- 2.43.5