1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00

unfinished suspend functions

This commit is contained in:
Alasdair Kergon 2005-10-25 19:09:41 +00:00
parent bcc400dafa
commit a6c7043e03
3 changed files with 138 additions and 2 deletions

View File

@ -83,4 +83,6 @@ dm_hash_get_first
dm_hash_get_next
dm_driver_version
dm_deptree_deactivate_children
dm_deptree_suspend_children
dm_deptree_children_use_uuid
dm_set_selinux_context

View File

@ -254,6 +254,23 @@ int dm_deptree_deactivate_children(struct deptree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len);
/*
* Suspend a device plus all dependencies.
* Ignores devices that don't have a uuid starting with uuid_prefix.
*/
int dm_deptree_suspend_children(struct deptree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len);
/*
* Is the uuid prefix present in the tree?
* Only returns 0 if every node was checked successfully.
* Returns 1 if the tree walk has to be aborted.
*/
int dm_deptree_children_use_uuid(struct deptree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len);
/*****************************************************************************
* Library functions
*****************************************************************************/

View File

@ -402,7 +402,8 @@ struct deptree_node *dm_deptree_next_child(void **handle,
/*
* 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)
static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
struct dm_info *info)
{
struct dm_task *dmt;
int r;
@ -418,6 +419,9 @@ static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
return 0;
}
if (!with_open_count && !dm_task_no_open_count(dmt))
log_error("Failed to disable open_count");
if ((r = dm_task_run(dmt)))
r = dm_task_get_info(dmt, info);
@ -449,6 +453,38 @@ static int _deactivate_node(const char *name, uint32_t major, uint32_t minor)
r = dm_task_run(dmt);
/* FIXME Remove node from tree or mark invalid? */
dm_task_destroy(dmt);
return r;
}
static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
struct dm_info *newinfo)
{
struct dm_task *dmt;
int r;
log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
log_error("Suspend 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 suspension.", name);
dm_task_destroy(dmt);
return 0;
}
if (!dm_task_no_open_count(dmt))
log_error("Failed to disable open_count");
if ((r = dm_task_run(dmt)))
r = dm_task_get_info(dmt, newinfo);
dm_task_destroy(dmt);
return r;
@ -486,7 +522,7 @@ int dm_deptree_deactivate_children(struct deptree_node *dnode,
continue;
/* Refresh open_count */
if (!_info_by_dev(dinfo->major, dinfo->minor, &info) ||
if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
!info.exists || info.open_count)
continue;
@ -503,3 +539,84 @@ int dm_deptree_deactivate_children(struct deptree_node *dnode,
return 1;
}
/* FIXME Walk breadth first? */
int dm_deptree_suspend_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, newinfo;
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 (uuid_prefix && strncmp(uuid, uuid_prefix, uuid_prefix_len))
continue;
/* FIXME Ensure parents are already suspended */
if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
!info.exists)
continue;
if (!_suspend_node(name, info.major, info.minor, &newinfo)) {
log_error("Unable to suspend %s (%" PRIu32
":%" PRIu32 ")", name, info.major,
info.minor);
continue;
}
/* Update cached info */
child->info = newinfo;
if (dm_deptree_node_num_children(child, 0))
dm_deptree_suspend_children(child, uuid_prefix, uuid_prefix_len);
}
return 1;
}
/*
* Returns 1 if unsure.
*/
int dm_deptree_children_use_uuid(struct deptree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
{
void *handle = NULL;
struct deptree_node *child = dnode;
const char *uuid;
while ((child = dm_deptree_next_child(&handle, dnode, 0))) {
if (!(uuid = dm_deptree_node_get_uuid(child))) {
log_error("Failed to get uuid for deptree node.");
return 1;
}
if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))
return 1;
if (dm_deptree_node_num_children(child, 0))
dm_deptree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
}
return 0;
}