master - libdm: report: make it possible to use blank value as selection for string list report field
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b5022102bbaf97...
Commit: b5022102bbaf978cddd7ca9b27a1a12d5aeef44d
Parent: b7410c95cfbf53b2197611a0950450f7251643fc
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Sep 17 10:19:15 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Sep 17 10:19:15 2015 +0200
libdm: report: make it possible to use blank value as selection for string list report field
$ lvs -o name,tags vg
LV LV Tags
lvol0
lvol1 mytag
Before this patch:
$ lvs -o name,tags vg -S 'tags=""'
Failed to parse string list value for selection field lv_tags.
Selection syntax error at 'tags=""'.
Use 'help' for selection to get more help.
(and the same for -S 'tags={}' and -S 'tags=[]')
With this patch applied:
$ lvs -o name,tags vg -S 'tags=""'
LV LV Tags
lvol0
(and the same for -S 'tags={}' and -S 'tags=[]')
---
WHATS_NEW_DM | 1 +
libdm/libdm-report.c | 38 ++++++++++++++++++++++++++++----------
test/shell/select-report.sh | 4 ++++
3 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 31064e3..7f0e65e 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.109 -
======================================
+ Make it possible to use blank value as selection for string list report field.
Version 1.02.108 - 15th September 2015
======================================
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 10ab7df..681ad04 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -1644,11 +1644,21 @@ static int _cmp_field_time(struct dm_report *rh,
static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
+ unsigned int sel_list_size = dm_list_size(sel->list);
struct dm_str_list *sel_item;
unsigned int i = 1;
+ if (!val->items[0].len) {
+ if (sel_list_size == 1) {
+ /* match blank string list with selection defined as blank string only */
+ sel_item = dm_list_item(dm_list_first(sel->list), struct dm_str_list);
+ return !strcmp(sel_item->str, "");
+ }
+ return 0;
+ }
+
/* if item count differs, it's clear the lists do not match */
- if (val->items[0].len != dm_list_size(sel->list))
+ if (val->items[0].len != sel_list_size)
return 0;
/* both lists are sorted so they either match 1:1 or not */
@@ -1666,15 +1676,21 @@ static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *v
static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
+ unsigned int sel_list_size = dm_list_size(sel->list);
struct dm_str_list *sel_item;
unsigned int i, last_found = 1;
int r = 0;
- /* if value has no items and selection has at leas one, it's clear there's no match */
- if ((val->items[0].len == 0) && dm_list_size(sel->list))
+ if (!val->items[0].len) {
+ if (sel_list_size == 1) {
+ /* match blank string list with selection defined as blank string only */
+ sel_item = dm_list_item(dm_list_first(sel->list), struct dm_str_list);
+ return !strcmp(sel_item->str, "");
+ }
return 0;
+ }
- /* Check selection is a subset of the value. */
+ /* check selection is a subset of the value */
dm_list_iterate_items(sel_item, sel->list) {
r = 0;
for (i = last_found; i <= val->items[0].len; i++) {
@@ -1698,9 +1714,14 @@ static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
struct dm_str_list *sel_item;
unsigned int i;
- /* if value has no items and selection has at least one, it's clear there's no match */
- if ((val->items[0].len == 0) && dm_list_size(sel->list))
+ /* match blank string list with selection that contains blank string */
+ if (!val->items[0].len) {
+ dm_list_iterate_items(sel_item, sel->list) {
+ if (!strcmp(sel_item->str, ""))
+ return 1;
+ }
return 0;
+ }
dm_list_iterate_items(sel_item, sel->list) {
/*
@@ -2460,11 +2481,8 @@ static int _add_item_to_string_list(struct dm_pool *mem, const char *begin,
{
struct dm_str_list *item;
- if (begin == end)
- return_0;
-
if (!(item = dm_pool_zalloc(mem, sizeof(*item))) ||
- !(item->str = dm_pool_strndup(mem, begin, end - begin))) {
+ !(item->str = begin == end ? "" : dm_pool_strndup(mem, begin, end - begin))) {
log_error("_add_item_to_string_list: memory allocation failed for string list item");
return 0;
}
diff --git a/test/shell/select-report.sh b/test/shell/select-report.sh
index fde7dc0..b859199 100644
--- a/test/shell/select-report.sh
+++ b/test/shell/select-report.sh
@@ -106,6 +106,10 @@ sel pv 'tags=["pv_tag4" || "pv_tag3"]' "$dev1" "$dev6"
sel pv 'tags!=["pv_tag1"]' "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6"
# check mixture of && and || - this is not allowed
not sel pv 'tags=["pv_tag1" && "pv_tag2" || "pv_tag3"]'
+# check selection with blank value
+sel lv 'tags=""' xyz orig snap
+sel lv 'tags={}' xyz orig snap
+sel lv 'tags=[]' xyz orig snap
##########################
# NUMBER FIELD SELECTION #
8 years, 6 months
master - lvmlockd: unlock lv if command fails before lock completes
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b7410c95cfbf53...
Commit: b7410c95cfbf53b2197611a0950450f7251643fc
Parent: fcfca57e2e15c5cae3ccac225669d97c65b6b9db
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 16 15:22:21 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 16 15:56:54 2015 -0500
lvmlockd: unlock lv if command fails before lock completes
If lvmlockd acquires an lv lock for a command, but the
command exits before the reply, then the command has
not activated the lv and lvmlockd should unlock it.
This only applies when the lv was not already locked.
(There will always be a chance that the lv lock is held
while the lv is not active, i.e. if the command fails in
the small window between getting the lv lock and before
doing the activation. In that case, rerunning the
activation command corrects the inconsistency.)
This commit helps by automatically clearing the
inconsistency (lv locked by not activated) in the most
common case when the lv lock operation is slow to
complete and the command is canceled by the user.
This commit also adds and cleans up references to the
client id in a bunch of log messages, which is useful
to follow processing on each independent lock request.
---
daemons/lvmlockd/lvmlockd-core.c | 142 +++++++++++++++++++++++++---------
daemons/lvmlockd/lvmlockd-internal.h | 3 +
2 files changed, 109 insertions(+), 36 deletions(-)
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index 7d5b158..487b6ec 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -1031,10 +1031,12 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
memset(&vb, 0, sizeof(vb));
+ r->last_client_id = act->client_id;
+
if (r->type == LD_RT_LV)
- log_debug("S %s R %s res_lock mode %s (%s)", ls->name, r->name, mode_str(act->mode), act->lv_name);
+ log_debug("S %s R %s res_lock cl %u mode %s (%s)", ls->name, r->name, act->client_id, mode_str(act->mode), act->lv_name);
else
- log_debug("S %s R %s res_lock mode %s", ls->name, r->name, mode_str(act->mode));
+ log_debug("S %s R %s res_lock cl %u mode %s", ls->name, r->name, act->client_id, mode_str(act->mode));
if (r->mode == LD_LK_SH && act->mode == LD_LK_SH)
goto add_lk;
@@ -1045,10 +1047,10 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
rv = lm_lock(ls, r, act->mode, act, &vb, retry, act->flags & LD_AF_ADOPT);
if (r->use_vb)
- log_debug("S %s R %s res_lock %d read vb %x %x %u",
+ log_debug("S %s R %s res_lock rv %d read vb %x %x %u",
ls->name, r->name, rv, vb.version, vb.flags, vb.r_version);
else
- log_debug("S %s R %s res_lock %d", ls->name, r->name, rv);
+ log_debug("S %s R %s res_lock rv %d", ls->name, r->name, rv);
if (rv < 0)
return rv;
@@ -1298,6 +1300,26 @@ add_lk:
lk->client_id = 0;
}
+ /*
+ * LV_LOCK means the action acquired the lv lock in the lock manager
+ * (as opposed to finding that the lv lock was already held). If
+ * the client for this LV_LOCK action fails before we send the result,
+ * then we automatically unlock the lv since the lv wasn't activated.
+ * (There will always be an odd chance the lv lock is held while the
+ * lv is not active, but this helps.) The most common case where this
+ * is helpful is when the lv lock operation is slow/delayed and the
+ * command is canceled by the user.
+ *
+ * LV_UNLOCK means the lv unlock action was generated by lvmlockd when
+ * it tried to send the reply for an lv lock action (with LV_LOCK set),
+ * and failed to send the reply to the client/command. The
+ * last_client_id saved on the resource is compared to this LV_UNLOCK
+ * action before the auto unlock is done in case another action locked
+ * the lv between the failed client lock action and the auto unlock.
+ */
+ if (r->type == LD_RT_LV)
+ act->flags |= LD_AF_LV_LOCK;
+
list_add_tail(&lk->list, &r->locks);
return rv;
@@ -1309,7 +1331,9 @@ static int res_convert(struct lockspace *ls, struct resource *r,
uint32_t r_version;
int rv;
- log_debug("S %s R %s res_convert mode %d", ls->name, r->name, act->mode);
+ r->last_client_id = act->client_id;
+
+ log_debug("S %s R %s res_convert cl %u mode %d", ls->name, r->name, act->client_id, act->mode);
if (act->mode == LD_LK_EX && lk->mode == LD_LK_SH && r->sh_count > 1)
return -EAGAIN;
@@ -1387,7 +1411,7 @@ static int res_cancel(struct lockspace *ls, struct resource *r,
return -ENOENT;
do_cancel:
- log_debug("S %s R %s res_cancel client %d", ls->name, r->name, cact->client_id);
+ log_debug("S %s R %s res_cancel cl %u", ls->name, r->name, cact->client_id);
cact->result = -ECANCELED;
list_del(&cact->list);
add_client_result(cact);
@@ -1435,22 +1459,32 @@ static int res_unlock(struct lockspace *ls, struct resource *r,
}
if (act->op != LD_OP_CLOSE)
- log_debug("S %s R %s res_unlock no locks", ls->name, r->name);
+ log_debug("S %s R %s res_unlock cl %u no locks", ls->name, r->name, act->client_id);
return -ENOENT;
do_unlock:
+ if ((act->flags & LD_AF_LV_UNLOCK) && (r->last_client_id != act->client_id)) {
+ log_debug("S %s R %s res_unlock cl %u for failed client ignored, last client %u",
+ ls->name, r->name, act->client_id, r->last_client_id);
+ return -ENOENT;
+ }
+
+ r->last_client_id = act->client_id;
+
if (act->op == LD_OP_CLOSE)
- log_debug("S %s R %s res_unlock from close", ls->name, r->name);
+ log_debug("S %s R %s res_unlock cl %u from close", ls->name, r->name, act->client_id);
else if (r->type == LD_RT_LV)
- log_debug("S %s R %s res_unlock (%s)", ls->name, r->name, act->lv_name);
+ log_debug("S %s R %s res_unlock cl %u (%s)", ls->name, r->name, act->client_id, act->lv_name);
else
- log_debug("S %s R %s res_unlock", ls->name, r->name);
+ log_debug("S %s R %s res_unlock cl %u", ls->name, r->name, act->client_id);
/* send unlock to lm when last sh lock is unlocked */
if (lk->mode == LD_LK_SH) {
r->sh_count--;
- if (r->sh_count > 0)
+ if (r->sh_count > 0) {
+ log_debug("S %s R %s res_unlock sh_count %u", ls->name, r->name, r->sh_count);
goto rem_lk;
+ }
}
if ((r->type == LD_RT_GL) && (r->mode == LD_LK_EX)) {
@@ -1498,14 +1532,14 @@ static int res_update(struct lockspace *ls, struct resource *r,
lk = find_lock_client(r, act->client_id);
if (!lk) {
- log_error("S %s R %s res_update client %u lock not found",
+ log_error("S %s R %s res_update cl %u lock not found",
ls->name, r->name, act->client_id);
return -ENOENT;
}
if (r->mode != LD_LK_EX) {
- log_error("S %s R %s res_update version on non-ex lock",
- ls->name, r->name);
+ log_error("S %s R %s res_update cl %u version on non-ex lock",
+ ls->name, r->name, act->client_id);
return -EINVAL;
}
@@ -1516,7 +1550,7 @@ static int res_update(struct lockspace *ls, struct resource *r,
else
lk->version = act->version;
- log_debug("S %s R %s res_update lk version to %u", ls->name, r->name, lk->version);
+ log_debug("S %s R %s res_update cl %u lk version to %u", ls->name, r->name, act->client_id, lk->version);
return 0;
}
@@ -1716,6 +1750,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
continue;
} else {
/* success */
+ r->last_client_id = act->client_id;
act->result = -EALREADY;
list_del(&act->list);
add_client_result(act);
@@ -1750,6 +1785,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
continue;
} else {
/* success */
+ r->last_client_id = act->client_id;
act->result = -EALREADY;
list_del(&act->list);
add_client_result(act);
@@ -1787,6 +1823,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
if ((lk->mode == LD_LK_EX) ||
(lk->mode == LD_LK_SH && act->mode == LD_LK_SH)) {
+ r->last_client_id = act->client_id;
act->result = 0;
list_del(&act->list);
add_client_result(act);
@@ -1794,6 +1831,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
/* persistent lock is sh, transient request is ex */
/* FIXME: can we remove this case? do a convert here? */
log_debug("res_process %s existing persistent lock new transient", r->name);
+ r->last_client_id = act->client_id;
act->result = -EEXIST;
list_del(&act->list);
add_client_result(act);
@@ -1828,10 +1866,12 @@ static void res_process(struct lockspace *ls, struct resource *r,
if (lk->mode != act->mode) {
/* FIXME: convert and change to persistent? */
log_debug("res_process %s existing transient lock new persistent", r->name);
+ r->last_client_id = act->client_id;
act->result = -EEXIST;
list_del(&act->list);
add_client_result(act);
} else {
+ r->last_client_id = act->client_id;
lk->flags |= LD_LF_PERSISTENT;
lk->client_id = 0;
act->result = 0;
@@ -1880,7 +1920,6 @@ static void res_process(struct lockspace *ls, struct resource *r,
* lv lock conflicts won't be transient so don't retry them.
*/
-
if (r->mode == LD_LK_EX)
return;
@@ -3491,14 +3530,14 @@ static void client_resume(struct client *cl)
if (!cl->poll_ignore || cl->fd == -1 || cl->pi == -1) {
/* shouldn't happen */
- log_error("client_resume %d bad state ig %d fd %d pi %d",
+ log_error("client_resume %u bad state ig %d fd %d pi %d",
cl->id, cl->poll_ignore, cl->fd, cl->pi);
return;
}
pthread_mutex_lock(&pollfd_mutex);
if (pollfd[cl->pi].fd != POLL_FD_IGNORE) {
- log_error("client_resume %d pi %d fd %d not IGNORE",
+ log_error("client_resume %u pi %d fd %d not IGNORE",
cl->id, cl->pi, cl->fd);
}
pollfd[cl->pi].fd = cl->fd;
@@ -3509,16 +3548,17 @@ static void client_resume(struct client *cl)
}
/* called from client_thread, cl->mutex is held */
-static void client_send_result(struct client *cl, struct action *act)
+static int client_send_result(struct client *cl, struct action *act)
{
response res;
char result_flags[128];
int dump_len = 0;
int dump_fd = -1;
+ int rv = 0;
if (cl->dead) {
- log_debug("client send %d skip dead", cl->id);
- return;
+ log_debug("send cl %u skip dead", cl->id);
+ return -1;
}
memset(result_flags, 0, sizeof(result_flags));
@@ -3580,7 +3620,7 @@ static void client_send_result(struct client *cl, struct action *act)
if (act->lv_args[0])
lv_args = act->lv_args;
- log_debug("send %s[%d.%u] %s %s rv %d vg_args %s lv_args %s",
+ log_debug("send %s[%d] cl %u %s %s rv %d vg_args %s lv_args %s",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_str(act->op), rt_str(act->rt),
act->result, vg_args ? vg_args : "", lv_args ? lv_args : "");
@@ -3612,7 +3652,7 @@ static void client_send_result(struct client *cl, struct action *act)
else
act->result = -EINVAL;
- log_debug("send %s[%d.%u] dump result %d dump_len %d",
+ log_debug("send %s[%d] cl %u dump result %d dump_len %d",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
act->result, dump_len);
@@ -3625,7 +3665,7 @@ static void client_send_result(struct client *cl, struct action *act)
* A normal reply.
*/
- log_debug("send %s[%d.%u] %s %s rv %d %s %s",
+ log_debug("send %s[%d] cl %u %s %s rv %d %s %s",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_str(act->op), rt_str(act->rt),
act->result, (act->result == -ENOLS) ? "ENOLS" : "", result_flags);
@@ -3639,7 +3679,13 @@ static void client_send_result(struct client *cl, struct action *act)
NULL);
}
- buffer_write(cl->fd, &res.buffer);
+ if (!buffer_write(cl->fd, &res.buffer)) {
+ rv = -errno;
+ if (rv >= 0)
+ rv = -1;
+ log_debug("send cl %u fd %d error %d", cl->id, cl->fd, rv);
+ }
+
buffer_destroy(&res.buffer);
client_resume(cl);
@@ -3649,6 +3695,8 @@ static void client_send_result(struct client *cl, struct action *act)
send_dump_buf(dump_fd, dump_len);
close(dump_fd);
}
+
+ return rv;
}
/* called from client_thread */
@@ -4303,10 +4351,10 @@ static void client_recv_action(struct client *cl)
rv = buffer_read(cl->fd, &req.buffer);
if (!rv) {
if (errno == ECONNRESET) {
- log_debug("client recv %d ECONNRESET", cl->id);
+ log_debug("client recv %u ECONNRESET", cl->id);
cl->dead = 1;
} else {
- log_error("client recv %d buffer_read error %d", cl->id, errno);
+ log_error("client recv %u buffer_read error %d", cl->id, errno);
}
buffer_destroy(&req.buffer);
client_resume(cl);
@@ -4315,7 +4363,7 @@ static void client_recv_action(struct client *cl)
req.cft = dm_config_from_string(req.buffer.mem);
if (!req.cft) {
- log_error("client recv %d config_from_string error", cl->id);
+ log_error("client recv %u config_from_string error", cl->id);
buffer_destroy(&req.buffer);
client_resume(cl);
return;
@@ -4324,7 +4372,7 @@ static void client_recv_action(struct client *cl)
str = daemon_request_str(req, "request", NULL);
rv = str_to_op_rt(str, &op, &rt);
if (rv < 0) {
- log_error("client recv %d bad request name \"%s\"", cl->id, str ? str : "");
+ log_error("client recv %u bad request name \"%s\"", cl->id, str ? str : "");
dm_config_destroy(req.cft);
buffer_destroy(&req.buffer);
client_resume(cl);
@@ -4447,7 +4495,7 @@ static void client_recv_action(struct client *cl)
dm_config_destroy(req.cft);
buffer_destroy(&req.buffer);
- log_debug("recv %s[%d.%u] %s %s \"%s\" mode %s flags %x",
+ log_debug("recv %s[%d] cl %u %s %s \"%s\" mode %s flags %x",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_str(act->op), rt_str(act->rt), act->vg_name, mode_str(act->mode), opts);
@@ -4514,6 +4562,8 @@ static void *client_thread_main(void *arg_in)
{
struct client *cl;
struct action *act;
+ struct action *act_un;
+ int rv;
while (1) {
pthread_mutex_lock(&client_mutex);
@@ -4537,11 +4587,30 @@ static void *client_thread_main(void *arg_in)
if (cl) {
pthread_mutex_lock(&cl->mutex);
- client_send_result(cl, act);
+ rv = client_send_result(cl, act);
pthread_mutex_unlock(&cl->mutex);
} else {
- log_debug("no client for result");
+ log_debug("no client %u for result", act->client_id);
+ rv = -1;
}
+
+ /*
+ * The client failed after we acquired an LV lock for
+ * it, but before getting this reply saying it's done.
+ * So the lv will not be active and we should release
+ * the lv lock it requested.
+ */
+ if ((rv < 0) && (act->flags & LD_AF_LV_LOCK)) {
+ log_debug("auto unlock lv for failed client %u", act->client_id);
+ if ((act_un = alloc_action())) {
+ memcpy(act_un, act, sizeof(struct action));
+ act_un->mode = LD_LK_UN;
+ act_un->flags |= LD_AF_LV_UNLOCK;
+ act_un->flags &= ~LD_AF_LV_LOCK;
+ add_lock_action(act_un);
+ }
+ }
+
free_action(act);
continue;
}
@@ -4571,6 +4640,7 @@ static void *client_thread_main(void *arg_in)
log_debug("client rem %d pi %d fd %d ig %d",
cl->id, cl->pi, cl->fd, cl->poll_ignore);
*/
+
/*
* If cl->dead was set in main_loop, then the
* fd has already been closed and the pollfd
@@ -5620,7 +5690,7 @@ static void process_listener(int poll_fd)
list_add_tail(&cl->list, &client_list);
pthread_mutex_unlock(&client_mutex);
- log_debug("client add id %d pi %d fd %d", cl->id, cl->pi, cl->fd);
+ log_debug("new cl %u pi %d fd %d", cl->id, cl->pi, cl->fd);
}
/*
@@ -5763,14 +5833,14 @@ static int main_loop(daemon_state *ds_arg)
if (cl->recv) {
/* should not happen */
- log_error("main client %d already recv", cl->id);
+ log_error("main client %u already recv", cl->id);
} else if (cl->dead) {
/* should not happen */
- log_error("main client %d already dead", cl->id);
+ log_error("main client %u already dead", cl->id);
} else if (is_dead) {
- log_debug("close %s[%d.%u] fd %d",
+ log_debug("close %s[%d] cl %u fd %d",
cl->name[0] ? cl->name : "client",
cl->pid, cl->id, cl->fd);
cl->dead = 1;
diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h
index a90dd99..3afa75a 100644
--- a/daemons/lvmlockd/lvmlockd-internal.h
+++ b/daemons/lvmlockd/lvmlockd-internal.h
@@ -103,6 +103,8 @@ struct client {
#define LD_AF_DUP_GL_LS 0x00002000
#define LD_AF_ADOPT 0x00010000
#define LD_AF_WARN_GL_REMOVED 0x00020000
+#define LD_AF_LV_LOCK 0x00040000
+#define LD_AF_LV_UNLOCK 0x00080000
/*
* Number of times to repeat a lock request after
@@ -141,6 +143,7 @@ struct resource {
int8_t mode;
unsigned int sh_count; /* number of sh locks on locks list */
uint32_t version;
+ uint32_t last_client_id; /* last client_id to lock or unlock resource */
unsigned int lm_init : 1; /* lm_data is initialized */
unsigned int adopt : 1; /* temp flag in remove_inactive_lvs */
unsigned int version_zero_valid : 1;
8 years, 6 months
master - format-text: label: fix missing dev assignment for struct label in _text_pv_write
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fcfca57e2e15c5...
Commit: fcfca57e2e15c5cae3ccac225669d97c65b6b9db
Parent: 0ac10bb23a9e356b87ead9e1304a6482f6761b9b
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Sep 15 17:38:02 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Sep 15 18:07:32 2015 +0200
format-text: label: fix missing dev assignment for struct label in _text_pv_write
When using lvm shell, some structures which are cached in memory may be
reused. This happens for the struct label (a part of lvmcache_info
structure) when lvmetad is used in which case the PV scan is not
done that would normally overwrite these label structures in memory
and making them up-to-date.
This is all consequence of the fact that struct lvmcache_info and
struct label are not always assigned in the same part of the code.
For example, if lvmetad *is not* used, parts of the struct label are
reassigned in label_read fn while struct lvmcache_info is created
elsewhere. No part of the code reused struct label (and its "dev"
field) before calling label_read fn. That's why the real bug is
hidden when using lvm shell without lvmetad.
However, with lvmetad and lvm shell, the situation is a bit different.
The label_read fn is not called if lvmetad *is* used, hence the
struct label may have ended up not initialized properly.
There was missing assignment for the dev field in struct label
in _text_pv_write fn which caused this problem to appear in
lvm shell with lvmetad, for example:
Before this patch:
lvm> pvcreate /dev/sda
Physical volume "/dev/sda" successfully created
lvm> pvs /dev/sda
PV VG Fmt Attr PSize PFree
unknown device lvm2 --- 128.00m 128.00m
With this patch applied:
lvm> pvcreate /dev/sda
Physical volume "/dev/sda" successfully created
lvm> pvs /dev/sda
PV VG Fmt Attr PSize PFree
/dev/sda lvm2 --- 128.00m 128.00m
Also, this problem had not appeared before changes introduced
by commits e1a63905d14cc73352b905c70cb4084b7e521e33 through
3a6f91d7139119bea664050a957cbc21490398bc which, among other
things, added proper label field type reporting. Before, label
reporting was the same as using struct physical_volume which
has its own dev field assigned and so this problem was not exposed.
---
WHATS_NEW | 1 +
lib/format_text/format-text.c | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index c50eecb..e50ffd2 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.132 -
======================================
+ Fix PV label processing failure after pvcreate in lvm shell with lvmetad.
Version 2.02.131 - 15th September 2015
======================================
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 4544f26..e0ec8ed 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1339,6 +1339,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
label = lvmcache_get_label(info);
label->sector = pv->label_sector;
+ label->dev = pv->dev;
lvmcache_update_pv(info, pv, fmt);
8 years, 6 months
v2_02_131 annotated tag has been created
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=10619ffc87ca3f...
Commit: 10619ffc87ca3f7c3e2bc9cb7ecafb692d13b2d8
Parent: 0000000000000000000000000000000000000000
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: 2015-09-15 12:18 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: 2015-09-15 12:18 +0000
annotated tag: v2_02_131 has been created
at 10619ffc87ca3f7c3e2bc9cb7ecafb692d13b2d8 (tag)
tagging a729b1aa294ab4525e09c83f392560bcf59a5b81 (commit)
replaces v2_02_130
Release 2.02.131.
66 files changed, 2457 insertions(+), 1719 deletions(-)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iEYEABECAAYFAlX4DKAACgkQIoGRwVZ+LBdiTQCg7ot+g1jnQcLU26on6n6NfNJC
btUAoPBnpR9WaSm0r0dkbrC/L8XBlkF5
=axmX
-----END PGP SIGNATURE-----
Alasdair G Kergon (4):
style: Standardise some error paths.
post-release
man: Add all_man Makefile target.
pre-release
Bryn M. Reeves (9):
dmsetup: fix bounds leak in _do_stats_create_regions()
libdm: add missing error handling in _stats_parse_histogram()
libdm: check dm_pool_begin_object() return value.
libdm: handle pool errors in dm_histogram_to_string()
libdm: fix dm_stats leak in dm_stats_create()
libdm: only free the first histogram explicitly (Coverity)
libdm: clean up _build_histogram_arg()
libdm: fix display of nsec suffixes in histogram strings
libdm: clean up stats local variable use
David Teigland (13):
man lvmlockd: mention device used for first vgcreate
man lvmlockd: fix typo
vgchange: lock-stop only needs shared lock
lockd: add start_init arg to lockd_start_vg
lvmlockd: rename ADOPT_CLIENT_ID
lvmlockd: flag for internal actions
lvmlockd: check all variations of lvb values
lockd: fix rescanning VG metadata
lvmlockd: optimize dlm global lockspace creation
lvmlockd: remove shortcut for lockspace thread cleanup
lvmlockd: prevent vgremove of dlm VG while lockspace is used
man lvmlockd: move and update text about vgremove
vgcreate: initialize new PVs only in first vg_write
Peter Rajnoha (3):
filters: make sure regex filter is evaluated before any filter that needs disk access
WHATS_NEW: commit b77497cbd86a854add3ffa4ce09a35f165c0d2ba
dev-cache: ignore persistent cache if configuration changed
Zdenek Kabelac (34):
configure: relocate generated headers
configure: support --disable-dependency-tracking
configure: simpler version reading
configure: regenerate
makefiles: deps depends on header links
makefiles: do not generate tags for everyone
tests: update install rules
specs: package lvmlockctl man page
cleanup: assign seg_name once
specs: install lvmlockctl only when built
tests: skip raid testing on 4.[1,2] fc24 kernels
makefiles: ensure no old .h are left
tests: better check for compiled version
tests: ensure dd flushed all data before exit
lib: when moving segtypes, move LV bits
cache: warn if caching causes troubles
cache: disallow stripes/size for cache pool
tests: check cache stripe and raid behavior
tests: fix check lv_not_exist
tests: remove only existing loops
spec: upgrade
configure: correct message
configure: relocate configure.h
thin: lvconvert use passed PVs for _pmspare
thin: improve swapping of identifiers
pool: validate pool_metadata has proper suffix
makefiles: distclean missing files
tests: new thin tests
tests: wait for sync before deactivation
vgimporeclone: use correct cache dir path
libdm: no validate for pool without messages
thin: show message on error path
tests: lvextend of full thin pool
tests: early check for snapshot-merge
8 years, 6 months
master - post-release
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=0ac10bb23a9e35...
Commit: 0ac10bb23a9e356b87ead9e1304a6482f6761b9b
Parent: a729b1aa294ab4525e09c83f392560bcf59a5b81
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue Sep 15 14:09:10 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue Sep 15 14:09:10 2015 +0100
post-release
---
VERSION | 2 +-
VERSION_DM | 2 +-
WHATS_NEW | 3 +++
WHATS_NEW_DM | 3 +++
4 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/VERSION b/VERSION
index fbf246a..a57faee 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.02.131(2)-git (2015-09-15)
+2.02.132(2)-git (2015-09-15)
diff --git a/VERSION_DM b/VERSION_DM
index 1c01d02..bb84883 100644
--- a/VERSION_DM
+++ b/VERSION_DM
@@ -1 +1 @@
-1.02.108-git (2015-09-15)
+1.02.109-git (2015-09-15)
diff --git a/WHATS_NEW b/WHATS_NEW
index b15ae48..c50eecb 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,3 +1,6 @@
+Version 2.02.132 -
+======================================
+
Version 2.02.131 - 15th September 2015
======================================
Rename 'make install_full_man' to install_all_man and add all_man target.
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 4e2f515..31064e3 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,3 +1,6 @@
+Version 1.02.109 -
+======================================
+
Version 1.02.108 - 15th September 2015
======================================
Do not check for full thin pool when activating without messages (1.02.107).
8 years, 6 months
master - pre-release
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a729b1aa294ab4...
Commit: a729b1aa294ab4525e09c83f392560bcf59a5b81
Parent: 548c09acfca8970cafe74f43e1944b5f20f540be
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue Sep 15 13:17:50 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue Sep 15 13:17:50 2015 +0100
pre-release
---
VERSION | 2 +-
VERSION_DM | 2 +-
WHATS_NEW | 4 ++--
WHATS_NEW_DM | 4 ++--
libdm/libdm-stats.c | 2 +-
5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/VERSION b/VERSION
index 4f600d1..fbf246a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.02.131(2)-git (2015-09-05)
+2.02.131(2)-git (2015-09-15)
diff --git a/VERSION_DM b/VERSION_DM
index 25d799d..1c01d02 100644
--- a/VERSION_DM
+++ b/VERSION_DM
@@ -1 +1 @@
-1.02.108-git (2015-09-05)
+1.02.108-git (2015-09-15)
diff --git a/WHATS_NEW b/WHATS_NEW
index 8f87617..b15ae48 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,5 @@
-Version 2.02.131 -
-=====================================
+Version 2.02.131 - 15th September 2015
+======================================
Rename 'make install_full_man' to install_all_man and add all_man target.
Fix vgimportclone cache_dir path name (2.02.115).
Swapping of LV identifiers handles more complex LVs.
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 9e30786..4e2f515 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,5 @@
-Version 1.02.108 -
-=====================================
+Version 1.02.108 - 15th September 2015
+======================================
Do not check for full thin pool when activating without messages (1.02.107).
Version 1.02.107 - 5th September 2015
diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c
index ee62fe6..d3ae1f2 100644
--- a/libdm/libdm-stats.c
+++ b/libdm/libdm-stats.c
@@ -199,7 +199,7 @@ static void _stats_histograms_destroy(struct dm_pool *mem,
return;
/*
- * Only the first histogram needs to be freed explicitly.
+ * Free everything in the pool back to the first histogram.
*/
if (region->counters[0].histogram)
dm_pool_free(mem, region->counters[0].histogram);
8 years, 6 months
master - man: Add all_man Makefile target.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=548c09acfca897...
Commit: 548c09acfca8970cafe74f43e1944b5f20f540be
Parent: 2ce8ee0214c84a4afd12589bbe2fe521c2518b87
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue Sep 15 13:14:16 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue Sep 15 13:14:16 2015 +0100
man: Add all_man Makefile target.
Use 'make all_man' to generate all man pages (regardless of
configuration options) or 'make install_all_man' to install them.
---
Makefile.in | 7 +++++--
WHATS_NEW | 1 +
make.tmpl.in | 2 +-
man/Makefile.in | 14 ++++++++++++--
4 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index d9ac815..68fbc79 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -131,6 +131,9 @@ rpm: dist
generate: conf.generate
$(MAKE) -C conf generate
+all_man:
+ $(MAKE) -C man all_man
+
install_system_dirs:
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
@@ -150,8 +153,8 @@ install_systemd_generators:
install_systemd_units:
$(MAKE) -C scripts install_systemd_units
-install_full_man:
- $(MAKE) -C man install_full_man
+install_all_man:
+ $(MAKE) -C man install_all_man
ifeq ("@PYTHON_BINDINGS@", "yes")
install_python_bindings:
diff --git a/WHATS_NEW b/WHATS_NEW
index c661702..8f87617 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.131 -
=====================================
+ Rename 'make install_full_man' to install_all_man and add all_man target.
Fix vgimportclone cache_dir path name (2.02.115).
Swapping of LV identifiers handles more complex LVs.
Use passed list of PVS when allocating space in lvconvert --thinpool.
diff --git a/make.tmpl.in b/make.tmpl.in
index 7124144..1217278 100644
--- a/make.tmpl.in
+++ b/make.tmpl.in
@@ -275,7 +275,7 @@ POTFILES = $(SOURCES:%.c=%.pot)
.PHONY: all pofile distclean clean cleandir cflow device-mapper
.PHONY: install install_cluster install_device-mapper install_lvm2
.PHONY: install_lib_shared install_dm_plugin install_lvm2_plugin
-.PHONY: install_ocf install_systemd_generators install_full_man help
+.PHONY: install_ocf install_systemd_generators install_all_man all_man man help
.PHONY: python_bindings install_python_bindings
.PHONY: $(SUBDIRS) $(SUBDIRS.install) $(SUBDIRS.clean) $(SUBDIRS.distclean)
.PHONY: $(SUBDIRS.pofile) $(SUBDIRS.install_cluster) $(SUBDIRS.cflow)
diff --git a/man/Makefile.in b/man/Makefile.in
index 6ddbaa9..6ef7186 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -42,7 +42,15 @@ MAN8DM=dmsetup.8 dmstats.8
MAN8CLUSTER=
MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
-ifeq ($(MAKECMDGOALS),install_full_man)
+ifeq ($(MAKECMDGOALS),all_man)
+ MAN_ALL="yes"
+endif
+
+ifeq ($(MAKECMDGOALS),install_all_man)
+ MAN_ALL="yes"
+endif
+
+ifeq ($(MAN_ALL),"yes")
MAN8+=$(FSADMMAN) $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN)
MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN)
MAN8CLUSTER+=$(CLVMDMAN) $(CMIRRORDMAN)
@@ -109,6 +117,8 @@ device-mapper: $(MAN8DM)
man: $(MAN5) $(MAN7) $(MAN8) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS)
+all_man: man
+
$(MAN5) $(MAN7) $(MAN8) $(MAN8DM) $(MAN8CLUSTER): Makefile
Makefile: Makefile.in
@@ -150,4 +160,4 @@ install_systemd_generators: $(MAN8SYSTEMD_GENERATORS)
install: install_lvm2 install_device-mapper install_cluster
-install_full_man: install install_systemd_generators
+install_all_man: install install_systemd_generators
8 years, 6 months
master - vgcreate: initialize new PVs only in first vg_write
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2ce8ee0214c84a...
Commit: 2ce8ee0214c84a4afd12589bbe2fe521c2518b87
Parent: cee9ed22441187a2a3a6290d1e07428df0171144
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Sep 11 16:12:03 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Sep 14 13:22:22 2015 -0500
vgcreate: initialize new PVs only in first vg_write
When a command does a sequence of
vg_write + vg_commit + vg_write + vg_commit,
initialization of non-PV devices happens during the
first vg_write, and does not need to be repeated by
the second vg_write.
When creating a lockd VG, this sequence occurs because
the VG is first created, then the lockd data is created,
then the lockd data is then written to the VG metadata.
---
lib/metadata/metadata.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index b45f850..9bd42c9 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3011,7 +3011,7 @@ out:
int vg_write(struct volume_group *vg)
{
struct dm_list *mdah;
- struct pv_to_create *pv_to_create;
+ struct pv_to_create *pv_to_create, *pv_to_create_safe;
struct metadata_area *mda;
struct lv_list *lvl;
int revert = 0, wrote = 0;
@@ -3067,10 +3067,11 @@ int vg_write(struct volume_group *vg)
memlock_unlock(vg->cmd);
vg->seqno++;
- dm_list_iterate_items(pv_to_create, &vg->pvs_to_create) {
+ dm_list_iterate_items_safe(pv_to_create, pv_to_create_safe, &vg->pvs_to_create) {
if (!_pvcreate_write(vg->cmd, pv_to_create))
return 0;
- }
+ dm_list_del(&pv_to_create->list);
+ }
/* Write to each copy of the metadata area */
dm_list_iterate_items(mda, &vg->fid->metadata_areas_in_use) {
8 years, 6 months
master - tests: early check for snapshot-merge
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=cee9ed22441187...
Commit: cee9ed22441187a2a3a6290d1e07428df0171144
Parent: e7e15631ddd9150fa7643ae2debac797dabc5d25
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Sep 14 11:02:48 2015 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Sep 14 20:18:54 2015 +0200
tests: early check for snapshot-merge
---
test/shell/snapshot-merge.sh | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/test/shell/snapshot-merge.sh b/test/shell/snapshot-merge.sh
index 44d6c24..ff4f8d1 100644
--- a/test/shell/snapshot-merge.sh
+++ b/test/shell/snapshot-merge.sh
@@ -11,6 +11,9 @@
. lib/inittest
+# test if snapshot-merge target is available
+aux target_at_least snapshot-merge 1 0 0 || skip
+
which mkfs.ext3 || skip
lvdev_() {
@@ -45,8 +48,6 @@ mkdir test_mnt
# test full merge of a single LV
setup_merge_ $vg $lv1
-# now that snapshot LV is created: test if snapshot-merge target is available
-aux target_at_least snapshot-merge 1 0 0 || skip
# make sure lvconvert --merge requires explicit LV listing
not lvconvert --merge
8 years, 6 months
master - tests: lvextend of full thin pool
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e7e15631ddd915...
Commit: e7e15631ddd9150fa7643ae2debac797dabc5d25
Parent: ffeeb5c1e70e554defa45ee8aa28dcaeb47c705f
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Sep 14 20:09:21 2015 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Sep 14 20:18:54 2015 +0200
tests: lvextend of full thin pool
---
test/shell/lvextend-thin-full.sh | 79 ++++++++++++++++++++++++++++++++++++++
1 files changed, 79 insertions(+), 0 deletions(-)
diff --git a/test/shell/lvextend-thin-full.sh b/test/shell/lvextend-thin-full.sh
new file mode 100644
index 0000000..6b1b9e0
--- /dev/null
+++ b/test/shell/lvextend-thin-full.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+# Copyright (C) 2015 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# play with thin-pool resize in corner cases
+#
+
+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
+
+. lib/inittest
+
+test -e LOCAL_LVMPOLLD && skip
+
+aux have_thin 1 0 0 || skip
+
+test -n "$LVM_TEST_THIN_RESTORE_CMD" || LVM_TEST_THIN_RESTORE_CMD=$(which thin_restore) || skip
+"$LVM_TEST_THIN_RESTORE_CMD" -V || skip
+
+#
+# Temporary solution to create some occupied thin metadata
+# This heavily depends on thin metadata output format to stay as is.
+# Currently it expects 2MB thin metadata and 200MB data volume size
+# Argument specifies how many devices should be created.
+fake_metadata_() {
+ echo '<superblock uuid="" time="1" transaction="'$2'" data_block_size="128" nr_data_blocks="3200">'
+ for i in $(seq 1 $1)
+ do
+ echo ' <device dev_id="'$i'" mapped_blocks="37" transaction="0" creation_time="0" snap_time="1">'
+ echo ' <range_mapping origin_begin="0" data_begin="0" length="37" time="0"/>'
+ echo ' </device>'
+ done
+ echo "</superblock>"
+}
+
+aux have_thin 1 10 0 || skip
+
+aux prepare_pvs 3 256
+
+vgcreate -s 1M $vg $(cat DEVICES)
+
+aux lvmconf 'activation/thin_pool_autoextend_percent = 30' \
+ 'activation/thin_pool_autoextend_threshold = 70'
+
+fake_metadata_ 400 0 >data
+lvcreate -L200 -T $vg/pool
+lvchange -an $vg
+
+lvcreate -L2M -n $lv1 $vg
+"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
+lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
+
+# Cannot resize if set to 0%
+not lvextend --use-policies --config 'activation{thin_pool_autoextend_percent = 0}' $vg/pool 2>&1 | tee err
+grep "0%" err
+
+# Locally active LV is needed
+not lvextend --use-policies $vg/pool 2>&1 | tee err
+grep "locally" err
+
+lvchange -ay $vg
+
+# Creation of new LV is not allowed when thinpool is over threshold
+not lvcreate -V10 $vg/pool
+
+
+lvextend --use-policies $vg/pool "$dev2" "$dev3"
+#should lvextend -l+100%FREE $vg/pool2
+
+lvs -a $vg
+
+vgremove -ff $vg
8 years, 6 months