From b9ffd32cd30f792123040c1cfdbd3f5599c40248 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 9 Jan 2007 19:44:07 +0000 Subject: [PATCH] Add dm_tree_use_no_flush_suspend(). --- WHATS_NEW_DM | 1 + libdm/.exported_symbols | 1 + libdm/libdevmapper.h | 10 ++++++++++ libdm/libdm-deptree.c | 21 +++++++++++++++++---- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index 3a5018572..9d2bc19f4 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,6 @@ Version 1.02.14 - ============================= + Add dm_tree_use_no_flush_suspend(). Lots of dmevent changes. Export dm_basename(). Cope with a trailing space when comparing tables prior to possible reload. diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols index cd2433563..34a623ad9 100644 --- a/libdm/.exported_symbols +++ b/libdm/.exported_symbols @@ -66,6 +66,7 @@ dm_tree_node_add_mirror_target dm_tree_node_add_mirror_target_log dm_tree_node_add_target_area dm_tree_skip_lockfs +dm_tree_use_no_flush_suspend dm_is_dm_major dm_mknodes dm_malloc_aux diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index d58620c59..3fda02a7c 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -315,6 +315,16 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode, */ void dm_tree_skip_lockfs(struct dm_tree_node *dnode); +/* + * Set the 'noflush' flag when suspending devices. + * If the kernel supports it, instead of erroring outstanding I/O that + * cannot be completed, the I/O is queued and resubmitted when the + * device is resumed. This affects multipath devices when all paths + * have failed and queue_if_no_path is set, and mirror devices when + * block_on_error is set and the mirror log has failed. + */ +void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode); + /* * Is the uuid prefix present in the tree? * Only returns 0 if every node was checked successfully. diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index f722a1adb..03e8fdf44 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -130,6 +130,7 @@ struct dm_tree { struct dm_hash_table *uuids; struct dm_tree_node root; int skip_lockfs; /* 1 skips lockfs (for non-snapshots) */ + int no_flush; /* 1 sets noflush (mirrors/multipath) */ }; /* FIXME Consider exporting this */ @@ -162,6 +163,7 @@ struct dm_tree *dm_tree_create(void) list_init(&dtree->root.uses); list_init(&dtree->root.used_by); dtree->skip_lockfs = 0; + dtree->no_flush = 0; if (!(dtree->mem = dm_pool_create("dtree", 1024))) { log_error("dtree pool creation failed"); @@ -903,13 +905,15 @@ static int _resume_node(const char *name, uint32_t major, uint32_t minor, } static int _suspend_node(const char *name, uint32_t major, uint32_t minor, - int skip_lockfs, struct dm_info *newinfo) + int skip_lockfs, int no_flush, struct dm_info *newinfo) { struct dm_task *dmt; int r; - log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s", name, major, - minor, skip_lockfs ? "" : " with filesystem sync."); + log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s", + name, major, minor, + skip_lockfs ? "" : " with filesystem sync", + no_flush ? "" : " without device flush"); if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) { log_error("Suspend dm_task creation failed for %s", name); @@ -928,6 +932,9 @@ static int _suspend_node(const char *name, uint32_t major, uint32_t minor, if (skip_lockfs && !dm_task_skip_lockfs(dmt)) log_error("Failed to set skip_lockfs flag."); + if (no_flush && !dm_task_no_flush(dmt)) + log_error("Failed to set no_flush flag."); + if ((r = dm_task_run(dmt))) r = dm_task_get_info(dmt, newinfo); @@ -991,6 +998,11 @@ void dm_tree_skip_lockfs(struct dm_tree_node *dnode) dnode->dtree->skip_lockfs = 1; } +void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode) +{ + dnode->dtree->no_flush = 1; +} + int dm_tree_suspend_children(struct dm_tree_node *dnode, const char *uuid_prefix, size_t uuid_prefix_len) @@ -1032,7 +1044,8 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode, continue; if (!_suspend_node(name, info.major, info.minor, - child->dtree->skip_lockfs, &newinfo)) { + child->dtree->skip_lockfs, + child->dtree->no_flush, &newinfo)) { log_error("Unable to suspend %s (%" PRIu32 ":%" PRIu32 ")", name, info.major, info.minor);