summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2013-03-18 15:39:14 -0500
committerPetr Rockai <prockai@redhat.com>2013-04-11 15:24:55 +0200
commitff2e223c147ec2de02ec9b3e34c6f7c7fde547c3 (patch)
tree62bf5fe3a2d6ce2c61cda0b7b78d740b1870c8a3
parent29eb84768d06d19314ef4a2dc2aa00368fe85cd9 (diff)
downloadlvm2-ff2e223c147ec2de02ec9b3e34c6f7c7fde547c3.tar.gz
toollib: read vgs before processing
In process_each_vg,lv, read all vgs, then process each, rather than reading and processing one at a time. Locking is currently hidden within vg_read, so another effect of this change is that all locks are acquired and held together at the start rather than being acquired and released individually.
-rw-r--r--lib/datastruct/str_list.c38
-rw-r--r--lib/datastruct/str_list.h1
-rw-r--r--tools/toollib.c169
3 files changed, 173 insertions, 35 deletions
diff --git a/lib/datastruct/str_list.c b/lib/datastruct/str_list.c
index dfce69c38..374de5c2f 100644
--- a/lib/datastruct/str_list.c
+++ b/lib/datastruct/str_list.c
@@ -50,6 +50,44 @@ int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
return 1;
}
+int str_list_add_order(struct dm_pool *mem, struct dm_list *sll, const char *str)
+{
+ struct str_list *sl_tmp;
+ struct str_list *sl_new;
+
+ if (!str)
+ return_0;
+
+ /* Already in list? */
+ if (str_list_match_item(sll, str))
+ return 1;
+
+ if (!(sl_new = dm_pool_alloc(mem, sizeof(*sl_new))))
+ return_0;
+
+ sl_new->str = str;
+
+ if (dm_list_empty(sll)) {
+ dm_list_add(sll, &sl_new->list);
+ return 1;
+ }
+
+ dm_list_iterate_items(sl_tmp, sll) {
+ /*
+ * If new str (s1) is less than existing/tmp str (s2),
+ * then break and insert new before existing.
+ */
+ if (strcmp(sl_new->str, sl_tmp->str) < 0)
+ break;
+ }
+
+ sl_new->list.n = &sl_tmp->list;
+ sl_new->list.p = sl_tmp->list.p;
+ sl_tmp->list.p->n = &sl_new->list;
+ sl_tmp->list.p = &sl_new->list;
+ return 1;
+}
+
void str_list_del(struct dm_list *sll, const char *str)
{
struct dm_list *slh, *slht;
diff --git a/lib/datastruct/str_list.h b/lib/datastruct/str_list.h
index 42f47da30..bab6d9bd9 100644
--- a/lib/datastruct/str_list.h
+++ b/lib/datastruct/str_list.h
@@ -18,6 +18,7 @@
struct dm_list *str_list_create(struct dm_pool *mem);
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
+int str_list_add_order(struct dm_pool *mem, struct dm_list *sll, const char *str);
void str_list_del(struct dm_list *sll, const char *str);
int str_list_match_item(const struct dm_list *sll, const char *str);
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, const char **tag_matched);
diff --git a/tools/toollib.c b/tools/toollib.c
index 5a297c7ea..2996176c4 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -16,6 +16,11 @@
#include "tools.h"
#include <sys/stat.h>
+struct vg_list {
+ struct dm_list list;
+ struct volume_group *vg;
+};
+
const char *command_name(struct cmd_context *cmd)
{
return cmd->command->name;
@@ -1419,8 +1424,8 @@ static int get_arg_vgnames(struct cmd_context *cmd,
ret_max = EINVALID_CMD_LINE;
continue;
}
- if (!str_list_add(cmd->mem, arg_vgnames,
- dm_pool_strdup(cmd->mem, vg_name))) {
+ if (!str_list_add_order(cmd->mem, arg_vgnames,
+ dm_pool_strdup(cmd->mem, vg_name))) {
log_error("strlist allocation failed");
return ECMD_FAILED;
}
@@ -1449,8 +1454,8 @@ static int get_all_vgnames(struct cmd_context *cmd, struct dm_list *all_vgnames)
if (!vg_name)
continue;
- if (!str_list_add(cmd->mem, all_vgnames,
- dm_pool_strdup(cmd->mem, vg_name))) {
+ if (!str_list_add_order(cmd->mem, all_vgnames,
+ dm_pool_strdup(cmd->mem, vg_name))) {
log_error("strlist allocation failed");
return ECMD_FAILED;
}
@@ -1459,14 +1464,79 @@ out:
return ret_max;
}
+static struct vg_list *find_vgl(struct dm_list *vgl_list, const char *vg_name)
+{
+ struct vg_list *vgl;
+
+ dm_list_iterate_items(vgl, vgl_list) {
+ if (!strcmp(vg_name, vgl->vg->name))
+ return vgl;
+ }
+ return NULL;
+}
+
+static void release_vg_list(struct cmd_context *cmd, struct dm_list *vgl_list)
+{
+ struct vg_list *vgl;
+
+ dm_list_iterate_items(vgl, vgl_list) {
+ if (vg_read_error(vgl->vg))
+ release_vg(vgl->vg);
+ else
+ unlock_and_release_vg(cmd, vgl->vg, vgl->vg->name);
+ }
+}
+
+static int read_vg_name_list(struct cmd_context *cmd, uint32_t flags,
+ struct dm_list *vg_name_list,
+ struct dm_list *vgl_list)
+{
+ struct volume_group *vg;
+ struct vg_list *vgl;
+ struct str_list *sl;
+ const char *vg_name;
+ int ret_max = ECMD_PROCESSED;
+
+ dm_list_iterate_items(sl, vg_name_list) {
+ vg_name = sl->str;
+
+ if (!(vgl = dm_pool_alloc(cmd->mem, sizeof(*vgl)))) {
+ log_error("vg_list alloc failed");
+ release_vg_list(cmd, vgl_list);
+ return ECMD_FAILED;
+ }
+
+ vg = vg_read(cmd, vg_name, NULL, flags);
+ if (vg_read_error(vg)) {
+ if (!((flags & READ_ALLOW_INCONSISTENT) &&
+ (vg_read_error(vg) == FAILED_INCONSISTENT))) {
+ ret_max = ECMD_FAILED;
+ release_vg(vg);
+ stack;
+ continue;
+ }
+ }
+
+ vgl->vg = vg;
+ dm_list_add(vgl_list, &vgl->list);
+
+ if (sigint_caught())
+ break;
+ }
+
+ return ret_max;
+}
+
static int process_vg_name_list(struct cmd_context *cmd, uint32_t flags,
struct dm_list *vg_name_list,
struct dm_list *arg_vgnames,
struct dm_list *arg_tags,
+ struct dm_list *vgl_list,
void *handle,
process_single_vg_fn_t process_single_vg)
{
struct volume_group *vg;
+ struct vg_list *vgl;
struct str_list *sl;
const char *vgname;
int ret_max = ECMD_PROCESSED;
@@ -1480,16 +1550,11 @@ static int process_vg_name_list(struct cmd_context *cmd, uint32_t flags,
dm_list_iterate_items(sl, vg_name_list) {
vgname = sl->str;
- vg = vg_read(cmd, vgname, NULL, flags);
- if (vg_read_error(vg)) {
- if (!((flags & READ_ALLOW_INCONSISTENT) &&
- (vg_read_error(vg) == FAILED_INCONSISTENT))) {
- ret_max = ECMD_FAILED;
- release_vg(vg);
- stack;
- continue;
- }
- }
+ vgl = find_vgl(vgl_list, vgname);
+ if (!vgl)
+ continue;
+
+ vg = vgl->vg;
process_vg = 0;
@@ -1507,11 +1572,6 @@ static int process_vg_name_list(struct cmd_context *cmd, uint32_t flags,
if (process_vg)
ret = process_single_vg(cmd, vgname, vg, handle);
- if (vg_read_error(vg))
- release_vg(vg);
- else
- unlock_and_release_vg(cmd, vg, vgname);
-
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
@@ -1529,12 +1589,15 @@ int process_each_vg(struct cmd_context *cmd,
struct dm_list all_vgnames;
struct dm_list arg_vgnames;
struct dm_list arg_tags;
+ struct dm_list vgl_list;
struct dm_list *vg_name_list;
+ int ret_max = ECMD_PROCESSED;
int ret;
dm_list_init(&all_vgnames);
dm_list_init(&arg_vgnames);
dm_list_init(&arg_tags);
+ dm_list_init(&vgl_list);
ret = get_arg_vgnames(cmd, argc, argv, &arg_vgnames, &arg_tags);
if (ret != ECMD_PROCESSED)
@@ -1557,10 +1620,27 @@ int process_each_vg(struct cmd_context *cmd,
else
vg_name_list = &arg_vgnames;
+ ret = read_vg_name_list(cmd, flags, vg_name_list, &vgl_list);
+
+ if (ret > ret_max)
+ ret_max = ret;
+ if (sigint_caught())
+ goto out;
+
+ if (dm_list_empty(&vgl_list)) {
+ stack;
+ goto out;
+ }
+
ret = process_vg_name_list(cmd, flags, vg_name_list,
- &arg_vgnames, &arg_tags,
- handle, process_single_vg);
- return ret;
+ &arg_vgnames, &arg_tags,
+ &vgl_list,
+ handle, process_single_vg);
+ if (ret > ret_max)
+ ret_max = ret;
+out:
+ release_vg_list(cmd, &vgl_list);
+ return ret_max;
}
/*
@@ -1637,8 +1717,8 @@ static int get_arg_lvnames(struct cmd_context *cmd,
} else
lv_name = NULL;
- if (!str_list_add(cmd->mem, arg_vgnames,
- dm_pool_strdup(cmd->mem, vgname))) {
+ if (!str_list_add_order(cmd->mem, arg_vgnames,
+ dm_pool_strdup(cmd->mem, vgname))) {
log_error("strlist allocation failed");
return ECMD_FAILED;
}
@@ -1671,10 +1751,12 @@ static int process_lv_vg_name_list(struct cmd_context *cmd, uint32_t flags,
struct dm_list *arg_vgnames,
struct dm_list *arg_lvnames,
struct dm_list *arg_tags,
+ struct dm_list *vgl_list,
void *handle,
process_single_lv_fn_t process_single_lv)
{
struct volume_group *vg;
+ struct vg_list *vgl;
struct str_list *sl, *sll;
struct dm_list *tags_arg;
struct dm_list lvnames;
@@ -1685,6 +1767,12 @@ static int process_lv_vg_name_list(struct cmd_context *cmd, uint32_t flags,
dm_list_iterate_items(sl, vg_name_list) {
vgname = sl->str;
+ vgl = find_vgl(vgl_list, vgname);
+ if (!vgl)
+ continue;
+
+ vg = vgl->vg;
+
/*
* arg_lvnames contains some elements that are just "vgname"
* which means process all lvs in the vg. Other elements
@@ -1716,19 +1804,9 @@ static int process_lv_vg_name_list(struct cmd_context *cmd, uint32_t flags,
}
}
- vg = vg_read(cmd, vgname, NULL, flags);
- if (vg_read_error(vg)) {
- ret_max = ECMD_FAILED;
- release_vg(vg);
- stack;
- continue;
- }
-
ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg,
handle, process_single_lv);
- unlock_and_release_vg(cmd, vg, vgname);
-
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
@@ -1747,13 +1825,16 @@ int process_each_lv(struct cmd_context *cmd,
struct dm_list arg_vgnames;
struct dm_list arg_lvnames;
struct dm_list arg_tags;
+ struct dm_list vgl_list;
struct dm_list *vg_name_list;
+ int ret_max = ECMD_PROCESSED;
int ret;
dm_list_init(&all_vgnames);
dm_list_init(&arg_vgnames);
dm_list_init(&arg_lvnames);
dm_list_init(&arg_tags);
+ dm_list_init(&vgl_list);
ret = get_arg_lvnames(cmd, argc, argv,
&arg_vgnames, &arg_lvnames, &arg_tags);
@@ -1777,9 +1858,27 @@ int process_each_lv(struct cmd_context *cmd,
else
vg_name_list = &arg_vgnames;
+ ret = read_vg_name_list(cmd, flags, vg_name_list, &vgl_list);
+
+ if (ret > ret_max)
+ ret_max = ret;
+ if (sigint_caught())
+ goto out;
+
+ if (dm_list_empty(&vgl_list)) {
+ stack;
+ goto out;
+ }
+
ret = process_lv_vg_name_list(cmd, flags, vg_name_list,
&arg_vgnames, &arg_lvnames, &arg_tags,
+ &vgl_list,
handle, process_single_lv);
- return ret;
+ if (ret > ret_max)
+ ret_max = ret;
+out:
+ release_vg_list(cmd, &vgl_list);
+
+ return ret_max;
}