From 9fdc84c32827cd0f7a489df35a66bdc029d78ac1 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 18 Oct 2005 12:39:20 +0000 Subject: [PATCH] Move deactivation code into libdevmapper. --- WHATS_NEW | 2 +- lib/activate/dev_manager.c | 202 +++++++++++-------------------------- 2 files changed, 59 insertions(+), 145 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 3b3cf772c..b406d2eed 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,6 +1,6 @@ Version 2.02.00 - =================================== - Replacement deactivation code. + Replacement deactivation code using libdevmapper dependency tree. Simplify dev_manager_info(). Attempt to load missing targets using modprobe. Add -a to lvscan. diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 58363abde..8e7d008bd 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -167,6 +167,8 @@ static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *laye char *dlid; size_t len; + /* FIXME Prepend 'LVM2-' */ + if (!layer) layer = ""; @@ -2187,137 +2189,10 @@ void dev_manager_exit(void) /* * New deactivation code */ -static struct deptree *_create_partial_deptree(uint32_t major, uint32_t minor) -{ - struct deptree *dtree; - - if (!(dtree = dm_deptree_create())) { - log_error("partial deptree creation failed"); - return NULL; - } - - if (!dm_deptree_add_dev(dtree, major, minor)) { - log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to deptree", - major, minor); - dm_deptree_free(dtree); - return NULL; - } - - return dtree; -} - -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; -} - -static int _deactivate_children(struct deptree_node *dnode, const char *root_uuid) -{ - 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, root_uuid, ID_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)) - _deactivate_children(child, root_uuid); - } - - return 1; -} - -/* - * Deactivate LV and all devices it references that nothing else has open. - */ -int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv) +static int _add_lv_to_deptree(struct dev_manager *dm, struct deptree *dtree, struct logical_volume *lv) { char *dlid, *name, *uuid; struct dm_info info; - struct deptree *dtree; - struct deptree_node *dnode; - int r = 0; if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) { stack; @@ -2335,40 +2210,79 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv) return 0; } - if (!info.exists) { - /* FIXME Search for invisible devices left by previous incomplete removal */ - log_debug("Ignoring deactivation request for inactive %s [%s]", name, dlid); - return 1; + if (info.exists && !dm_deptree_add_dev(dtree, info.major, info.minor)) { + log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to deptree", + info.major, info.minor); + return 0; } - if (!(dtree = _create_partial_deptree(info.major, info.minor))) { + /* FIXME Check for any related nodes left behind e.g. -real */ + + return 1; +} + +static struct deptree *_create_partial_deptree(struct dev_manager *dm, struct logical_volume *lv) +{ + struct deptree *dtree; + struct list *snh, *snht; + + if (!(dtree = dm_deptree_create())) { + log_error("partial deptree creation failed"); + return NULL; + } + + if (!_add_lv_to_deptree(dm, dtree, lv)) { + stack; + goto fail; + } + + /* Add any snapshots of this LV */ + list_iterate_safe(snh, snht, &lv->snapshot_segs) { + if (!_add_lv_to_deptree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow)) { + stack; + goto fail; + } + } + + return dtree; + +fail: + dm_deptree_free(dtree); + return NULL; +} + +/* + * Deactivate LV and all devices it references that nothing else has open. + */ +int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv) +{ + struct deptree *dtree; + struct deptree_node *dnode; + char *dlid; + int r = 0; + + if (!(dtree = _create_partial_deptree(dm, lv))) { stack; return 0; } - if (info.open_count) { - log_error("Unable to deactivate open (%" PRId32 ") device %s [%s]", info.open_count, name, dlid); + if (!(dnode = dm_deptree_find_node(dtree, 0, 0))) { + log_error("Lost dependency tree root node"); goto out; } - if (!(dnode = dm_deptree_find_node(dtree, info.major, info.minor))) { - log_error("Lost dependency tree node for %s (%" PRIu32 ":%" PRIu32 ") [%s]", - name, info.major, info.minor, dlid); + if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, ""))) { + log_error("dlid build failed for %s", lv->name); goto out; } - if (!_deactivate_node(name, info.major, info.minor)) { + if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN)) { stack; goto out; } fs_del_lv(lv); - if (!_deactivate_children(dnode, uuid)) { - stack; - goto out; - } - r = 1; out: