From 3e8c6b731a60ba92f9b1007fa4f02e440ff0755c Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 18 Oct 2005 12:37:53 +0000 Subject: [PATCH] Add deactivation functions --- libdm/.exported_symbols | 1 + libdm/libdevmapper.h | 7 +++ libdm/libdm-deptree.c | 104 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols index cb7eb0b3c..5f7d31f32 100644 --- a/libdm/.exported_symbols +++ b/libdm/.exported_symbols @@ -82,3 +82,4 @@ dm_hash_get_data dm_hash_get_first dm_hash_get_next dm_driver_version +dm_deptree_deactivate_children diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 4df4a0798..e9b517346 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -246,6 +246,13 @@ const struct dm_info *dm_deptree_node_get_info(struct deptree_node *node); */ int dm_deptree_node_num_children(struct deptree_node *node, uint32_t inverted); +/* + * Deactivate a device with its dependencies if the uuid prefix matches + */ +int dm_deptree_deactivate_children(struct deptree_node *dnode, + const char *uuid_prefix, + size_t uuid_prefix_len); + /***************************************************************************** * Library functions *****************************************************************************/ diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index e8969d4aa..b83f5d58f 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -399,3 +399,107 @@ struct deptree_node *dm_deptree_next_child(void **handle, return (*dlink) ? list_item(*dlink, struct deptree_link)->node : NULL; } +/* + * Deactivate a device with its dependencies if the uuid prefix matches + */ +static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info) +{ + struct dm_task *dmt; + int r; + + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) { + log_error("_info_by_dev: dm_task creation failed"); + return 0; + } + + if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) { + log_error("_info_by_dev: Failed to set device number"); + dm_task_destroy(dmt); + return 0; + } + + if ((r = dm_task_run(dmt))) + r = dm_task_get_info(dmt, info); + + dm_task_destroy(dmt); + + return r; +} + +static int _deactivate_node(const char *name, uint32_t major, uint32_t minor) +{ + struct dm_task *dmt; + int r; + + log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor); + + if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) { + log_error("Deactivation dm_task creation failed for %s", name); + return 0; + } + + 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; + } + + if (!dm_task_no_open_count(dmt)) + log_error("Failed to disable open_count"); + + r = dm_task_run(dmt); + + dm_task_destroy(dmt); + + return r; +} + +int dm_deptree_deactivate_children(struct deptree_node *dnode, const char *uuid_prefix, size_t uuid_prefix_len) +{ + void *handle = NULL; + struct deptree_node *child = dnode; + struct dm_info info; + const struct dm_info *dinfo; + const char *name; + const char *uuid; + + while ((child = dm_deptree_next_child(&handle, dnode, 0))) { + if (!(dinfo = dm_deptree_node_get_info(child))) { + stack; + continue; + } + + if (!(name = dm_deptree_node_get_name(child))) { + stack; + continue; + } + + if (!(uuid = dm_deptree_node_get_uuid(child))) { + stack; + continue; + } + + /* Ignore if it doesn't belong to this VG */ + if (strncmp(uuid, uuid_prefix, uuid_prefix_len)) { + stack; + continue; + } + + /* Refresh open_count */ + if (!_info_by_dev(dinfo->major, dinfo->minor, &info) || + !info.exists || info.open_count) + continue; + + if (!_deactivate_node(name, info.major, info.minor)) { + log_error("Unable to deactivate %s (%" PRIu32 + ":%" PRIu32 ")", name, info.major, + info.minor); + continue; + } + + if (dm_deptree_node_num_children(child, 0)) + dm_deptree_deactivate_children(child, uuid_prefix, uuid_prefix_len); + } + + return 1; +}