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;
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;
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);
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)
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);
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;
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);
/* 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);
/* 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))
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;
!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);
/* 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);
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);
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);
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;
+}