From 39270f9647ff35d3b1b9fe68f79b18f40d8eba0c Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 31 Jul 2009 18:30:31 +0000 Subject: [PATCH] Set cookies in activation code and wait for udev to complete processing. --- WHATS_NEW | 3 +- WHATS_NEW_DM | 2 ++ lib/activate/dev_manager.c | 29 ++++++++++++++---- libdm/.exported_symbols | 2 ++ libdm/libdevmapper.h | 3 ++ libdm/libdm-deptree.c | 63 ++++++++++++++++++++++++++++---------- 6 files changed, 77 insertions(+), 25 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index ef7415540..35d69fc48 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,7 +1,6 @@ Version 2.02.51 - ================================ - Add udevcomplete and --noudevwait to dmsetup. - Add libdevmapper functions to support synchronisation with udev. + Set cookies in activation code and wait for udev to complete processing. Added configure --enable-udev_rules --enable-udev_sync. Added configure --with-udev-prefix --with-udevdir. Added udev dir to hold udev rules. diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index 62661a39d..4f676cf60 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,7 @@ Version 1.02.36 - ================================ + Add udevcomplete and --noudevwait to dmsetup. + Add libdevmapper functions to support synchronisation with udev. Version 1.02.35 - 28th July 2009 ================================ diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 87a5c69ea..a6024632f 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -1131,8 +1131,12 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root) if (!*layer) continue; - if (!dm_tree_deactivate_children(root, uuid, strlen(uuid))) + dm_tree_set_cookie(root, 0); + if (!dm_tree_deactivate_children(root, uuid, strlen(uuid))) { + dm_udev_cleanup(dm_tree_get_cookie(root)); return_0; + } + dm_udev_wait(dm_tree_get_cookie(root)); } return 1; @@ -1165,8 +1169,12 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio break; case DEACTIVATE: /* Deactivate LV and all devices it references that nothing else has open. */ - if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) + dm_tree_set_cookie(root, 0); + if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) { + dm_udev_cleanup(dm_tree_get_cookie(root)); goto_out; + } + dm_udev_wait(dm_tree_get_cookie(root)); if (!_remove_lv_symlinks(dm, root)) log_error("Failed to remove all device symlinks associated with %s.", lv->name); break; @@ -1185,15 +1193,24 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio goto_out; /* Preload any devices required before any suspensions */ - if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) + dm_tree_set_cookie(root, 0); + if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) { + dm_udev_cleanup(dm_tree_get_cookie(root)); goto_out; + } + dm_udev_wait(dm_tree_get_cookie(root)); if (dm_tree_node_size_changed(root)) dm->flush_required = 1; - if ((action == ACTIVATE) && - !dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) - goto_out; + if (action == ACTIVATE) { + dm_tree_set_cookie(root, 0); + if (!dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1)) { + dm_udev_cleanup(dm_tree_get_cookie(root)); + goto_out; + } + dm_udev_wait(dm_tree_get_cookie(root)); + } if (!_create_lv_symlinks(dm, root)) { log_error("Failed to create symlinks for %s.", lv->name); diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols index d7d89d60c..085e5c99d 100644 --- a/libdm/.exported_symbols +++ b/libdm/.exported_symbols @@ -79,6 +79,8 @@ dm_tree_node_add_target_area dm_tree_node_set_read_ahead dm_tree_skip_lockfs dm_tree_use_no_flush_suspend +dm_tree_set_cookie +dm_tree_get_cookie dm_is_dm_major dm_mknodes dm_malloc_aux diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index f1692f3ef..12f75a73b 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -433,6 +433,9 @@ void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode, uint32_t read_ahead, uint32_t read_ahead_flags); +void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie); +uint32_t dm_tree_get_cookie(struct dm_tree_node *node); + /***************************************************************************** * Library functions *****************************************************************************/ diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index 5c5ea97f2..47b5e63bb 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -141,6 +141,7 @@ struct dm_tree { struct dm_tree_node root; int skip_lockfs; /* 1 skips lockfs (for non-snapshots) */ int no_flush; /* 1 sets noflush (mirrors/multipath) */ + uint32_t cookie; }; struct dm_tree *dm_tree_create(void) @@ -819,10 +820,10 @@ static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count, return r; } -static int _deactivate_node(const char *name, uint32_t major, uint32_t minor) +static int _deactivate_node(const char *name, uint32_t major, uint32_t minor, uint32_t *cookie) { struct dm_task *dmt; - int r; + int r = 0; log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor); @@ -833,26 +834,33 @@ static int _deactivate_node(const char *name, uint32_t major, uint32_t minor) if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) { log_error("Failed to set device number for %s deactivation", name); - dm_task_destroy(dmt); - return 0; + goto out; } if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); + if (!dm_task_set_cookie(dmt, cookie)) + goto out; + r = dm_task_run(dmt); + if (!r) + (void) dm_udev_complete(*cookie); + /* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */ rm_dev_node(name); /* FIXME Remove node from tree or mark invalid? */ +out: dm_task_destroy(dmt); return r; } -static int _rename_node(const char *old_name, const char *new_name, uint32_t major, uint32_t minor) +static int _rename_node(const char *old_name, const char *new_name, uint32_t major, + uint32_t minor, uint32_t *cookie) { struct dm_task *dmt; int r = 0; @@ -875,8 +883,14 @@ 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)) + goto out; + r = dm_task_run(dmt); + if (!r) + (void) dm_udev_complete(*cookie); + out: dm_task_destroy(dmt); @@ -886,10 +900,10 @@ out: /* FIXME Merge with _suspend_node? */ static int _resume_node(const char *name, uint32_t major, uint32_t minor, uint32_t read_ahead, uint32_t read_ahead_flags, - struct dm_info *newinfo) + struct dm_info *newinfo, uint32_t *cookie) { struct dm_task *dmt; - int r; + int r = 0; log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor); @@ -901,14 +915,12 @@ static int _resume_node(const char *name, uint32_t major, uint32_t minor, /* FIXME Kernel should fill in name on return instead */ if (!dm_task_set_name(dmt, name)) { log_error("Failed to set readahead device name for %s", name); - dm_task_destroy(dmt); - return 0; + goto out; } if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) { log_error("Failed to set device number for %s resumption.", name); - dm_task_destroy(dmt); - return 0; + goto out; } if (!dm_task_no_open_count(dmt)) @@ -917,9 +929,15 @@ 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)) + goto out; + if ((r = dm_task_run(dmt))) r = dm_task_get_info(dmt, newinfo); + else + (void) dm_udev_complete(*cookie); +out: dm_task_destroy(dmt); return r; @@ -1000,7 +1018,7 @@ int dm_tree_deactivate_children(struct dm_tree_node *dnode, !info.exists || info.open_count) continue; - if (!_deactivate_node(name, info.major, info.minor)) { + if (!_deactivate_node(name, info.major, info.minor, &dnode->dtree->cookie)) { log_error("Unable to deactivate %s (%" PRIu32 ":%" PRIu32 ")", name, info.major, info.minor); @@ -1144,7 +1162,8 @@ int dm_tree_activate_children(struct dm_tree_node *dnode, /* Rename? */ if (child->props.new_name) { - if (!_rename_node(name, child->props.new_name, child->info.major, child->info.minor)) { + if (!_rename_node(name, child->props.new_name, child->info.major, + child->info.minor, &child->dtree->cookie)) { log_error("Failed to rename %s (%" PRIu32 ":%" PRIu32 ") to %s", name, child->info.major, child->info.minor, child->props.new_name); @@ -1158,8 +1177,8 @@ int dm_tree_activate_children(struct dm_tree_node *dnode, continue; if (!_resume_node(child->name, child->info.major, child->info.minor, - child->props.read_ahead, - child->props.read_ahead_flags, &newinfo)) { + child->props.read_ahead, child->props.read_ahead_flags, + &newinfo, &child->dtree->cookie)) { log_error("Unable to resume %s (%" PRIu32 ":%" PRIu32 ")", child->name, child->info.major, child->info.minor); @@ -1525,8 +1544,8 @@ int dm_tree_preload_children(struct dm_tree_node *dnode, continue; if (!_resume_node(child->name, child->info.major, child->info.minor, - child->props.read_ahead, - child->props.read_ahead_flags, &newinfo)) { + child->props.read_ahead, child->props.read_ahead_flags, + &newinfo, &child->dtree->cookie)) { log_error("Unable to resume %s (%" PRIu32 ":%" PRIu32 ")", child->name, child->info.major, child->info.minor); @@ -1842,3 +1861,13 @@ int dm_tree_node_add_target_area(struct dm_tree_node *node, return 1; } + +void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie) +{ + node->dtree->cookie = cookie; +} + +uint32_t dm_tree_get_cookie(struct dm_tree_node *node) +{ + return node->dtree->cookie; +} -- 2.43.5