1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Move deactivation code into libdevmapper.

This commit is contained in:
Alasdair Kergon 2005-10-18 12:39:20 +00:00
parent 3e8c6b731a
commit 9fdc84c328
2 changed files with 59 additions and 145 deletions

View File

@ -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.

View File

@ -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: