master - reporter: drop mem on error path
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=49e3fd1ce8d0b1...
Commit: 49e3fd1ce8d0b1023f553673e76b49e65348878f
Parent: 6308a8b06d4dd52e9a8e95bb0ec1933eee547ee4
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Nov 13 17:39:22 2014 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Nov 13 17:44:31 2014 +0100
reporter: drop mem on error path
Coverity noticed.
---
tools/reporter.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tools/reporter.c b/tools/reporter.c
index 24191f1..8399395 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -553,6 +553,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
lock_global = 1;
if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_READ, NULL)) {
log_error("Unable to obtain global lock.");
+ dm_report_free(report_handle);
return ECMD_FAILED;
}
}
9 years, 6 months
master - cache: wrong feature in seg is internal error
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6308a8b06d4dd5...
Commit: 6308a8b06d4dd52e9a8e95bb0ec1933eee547ee4
Parent: 48874703d2deee676d326ed4447c7944ab728767
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Nov 13 17:41:45 2014 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Nov 13 17:44:31 2014 +0100
cache: wrong feature in seg is internal error
---
lib/metadata/cache_manip.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 27f381d..fb5346d 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -40,7 +40,7 @@ const char *get_cache_pool_cachemode_name(const struct lv_segment *seg)
if (seg->feature_flags & DM_CACHE_FEATURE_PASSTHROUGH)
return "passthrough";
- log_error("LV %s has uknown feature flags %" PRIu64,
+ log_error(INTERNAL_ERROR "LV %s has uknown feature flags %" PRIu64 ".",
display_lvname(seg->lv), seg->feature_flags);
return NULL;
9 years, 6 months
master - cleanup: free mempool memory used for LV status in PVSEGS reporting
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=48874703d2deee...
Commit: 48874703d2deee676d326ed4447c7944ab728767
Parent: 4de7699855e06bf341d5f91b9c3fc4ba4de18cd6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Nov 13 14:41:01 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Nov 13 14:41:01 2014 +0100
cleanup: free mempool memory used for LV status in PVSEGS reporting
Addendum to previous commit 4de7699855e06bf341d5f91b9c3fc4ba4de18cd6.
---
tools/reporter.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/tools/reporter.c b/tools/reporter.c
index ec1feb2..24191f1 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -223,7 +223,8 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd,
int ret = ECMD_PROCESSED;
struct lv_segment *seg = pvseg->lvseg;
struct lvinfo lvinfo = { .exists = 0 };
- struct lv_seg_status lv_seg_status = { .type = SEG_STATUS_NONE };
+ struct lv_seg_status lv_seg_status = { .type = SEG_STATUS_NONE,
+ .status = NULL };
struct segment_type _freeseg_type = {
.name = "free",
@@ -269,6 +270,8 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd,
}
out:
+ if (seg && lv_seg_status.status)
+ dm_pool_free(lv_seg_status.mem, lv_seg_status.status);
return ret;
}
9 years, 6 months
master - cleanup: unify LV info and LV segment status reporting in combination with LVS, SEGS and PVSEGS reporting
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=4de7699855e06b...
Commit: 4de7699855e06bf341d5f91b9c3fc4ba4de18cd6
Parent: 83308fdff97e242f6124858b35437ede6ee6a7e8
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Nov 13 14:14:20 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Nov 13 14:28:51 2014 +0100
cleanup: unify LV info and LV segment status reporting in combination with LVS, SEGS and PVSEGS reporting
Move common code into shared internal fn so the logic for getting the
LV info as well LV segment status is not scattered around - call common
_do_info_and_status to gather required parts in reporting handlers.
---
tools/reporter.c | 291 +++++++++++++++++++++++++++++++++---------------------
1 files changed, 179 insertions(+), 112 deletions(-)
diff --git a/tools/reporter.c b/tools/reporter.c
index 65edec5b..ec1feb2 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -39,71 +39,111 @@ static int _vgs_single(struct cmd_context *cmd __attribute__((unused)),
return ECMD_PROCESSED;
}
-static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
- void *handle)
+static void _choose_lv_segment_for_status_report(struct logical_volume *lv, struct lv_segment **lv_seg)
{
- if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL, NULL, NULL, NULL))
- return_ECMD_FAILED;
+ /*
+ * By default, take the first LV segment to report status for.
+ * If there's any other specific segment that needs to be
+ * reported instead for the LV, choose it here and assign it
+ * to lvdm->seg_status->seg. This is the segment whose
+ * status line will be used for report exactly.
+ */
+ *lv_seg = first_seg(lv);
+}
- return ECMD_PROCESSED;
+static void _do_info_and_status(struct cmd_context *cmd,
+ struct logical_volume *lv,
+ struct lvinfo *lvinfo,
+ struct lv_segment *lv_seg,
+ struct lv_seg_status *lv_seg_status,
+ int do_info, int do_status)
+{
+ if (lv_seg_status) {
+ lv_seg_status->mem = lv->vg->vgmem;
+ lv_seg_status->type = SEG_STATUS_NONE;
+ lv_seg_status->status = NULL;
+ }
+
+ if (do_info && !do_status) {
+ /* info only */
+ if (!lv_info(cmd, lv, 0, lvinfo, 1, 1))
+ lvinfo->exists = 0;
+ } else if (!do_info && do_status) {
+ /* status only */
+ if (!lv_seg)
+ _choose_lv_segment_for_status_report(lv, &lv_seg);
+ if (!lv_status(cmd, lv_seg, lv_seg_status))
+ lvinfo->exists = 0;
+ } else if (do_info && do_status) {
+ /* both info and status */
+ if (!lv_seg)
+ _choose_lv_segment_for_status_report(lv, &lv_seg);
+ if (!lv_info_with_seg_status(cmd, lv, lv_seg, 0, lvinfo, lv_seg_status, 1, 1))
+ lvinfo->exists = 0;
+ }
}
-static void _get_lv_info_for_report(struct cmd_context *cmd,
- struct logical_volume *lv,
- struct lvinfo *lvinfo)
+static int _do_lvs_with_info_and_status_single(struct cmd_context *cmd,
+ struct logical_volume *lv,
+ int do_info, int do_status,
+ void *handle)
{
- if (!lv_info(cmd, lv, 0, lvinfo, 1, 1))
- lvinfo->exists = 0;
+ struct lvinfo lvinfo;
+ struct lv_seg_status lv_seg_status;
+ int r = ECMD_FAILED;
+
+ _do_info_and_status(cmd, lv, &lvinfo, NULL, &lv_seg_status, do_info, do_status);
+ if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL,
+ do_info ? &lvinfo : NULL,
+ do_status ? &lv_seg_status : NULL,
+ NULL))
+ goto out;
+
+ r = ECMD_PROCESSED;
+out:
+ if (lv_seg_status.status)
+ dm_pool_free(lv_seg_status.mem, lv_seg_status.status);
+ return r;
}
-static void _get_lv_info_with_segment_status_for_report(struct cmd_context *cmd,
- struct logical_volume *lv,
- struct lvinfo *lvinfo,
- struct lv_segment *lv_seg,
- struct lv_seg_status *lv_seg_status)
+static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
{
- if (!lv_info_with_seg_status(cmd, lv, lv_seg, 0, lvinfo, lv_seg_status, 1, 1))
- lvinfo->exists = 0;
+ return _do_lvs_with_info_and_status_single(cmd, lv, 0, 0, handle);
}
static int _lvs_with_info_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
- struct lvinfo lvinfo;
-
- _get_lv_info_for_report(cmd, lv, &lvinfo);
- if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL, &lvinfo, NULL, NULL))
- return_ECMD_FAILED;
+ return _do_lvs_with_info_and_status_single(cmd, lv, 1, 0, handle);
+}
- return ECMD_PROCESSED;
+static int _lvs_with_status_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
+{
+ return _do_lvs_with_info_and_status_single(cmd, lv, 0, 1, handle);
}
-static void _choose_lv_segment_for_status_report(struct logical_volume *lv, struct lv_segment **lv_seg)
+static int _lvs_with_info_and_status_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
{
- /*
- * By default, take the first LV segment to report status for.
- * If there's any other specific segment that needs to be
- * reported instead for the LV, choose it here and assign it
- * to lvdm->seg_status->seg. This is the segment whose
- * status line will be used for report exactly.
- */
- *lv_seg = first_seg(lv);
+ return _do_lvs_with_info_and_status_single(cmd, lv, 1, 1, handle);
}
-static int _lvs_with_status_single(struct cmd_context *cmd, struct logical_volume *lv,
- void *handle)
+static int _do_segs_with_info_and_status_single(struct cmd_context *cmd,
+ struct lv_segment *seg,
+ int do_info, int do_status,
+ void *handle)
{
struct lvinfo lvinfo;
- struct lv_segment *lv_seg;
- struct lv_seg_status lv_seg_status = { .mem = lv->vg->vgmem,
- .type = SEG_STATUS_NONE,
- .status = NULL };
+ struct lv_seg_status lv_seg_status;
int r = ECMD_FAILED;
- _choose_lv_segment_for_status_report(lv, &lv_seg);
- _get_lv_info_with_segment_status_for_report(cmd, lv, &lvinfo, lv_seg, &lv_seg_status);
-
- if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL, &lvinfo, &lv_seg_status, NULL))
+ _do_info_and_status(cmd, seg->lv, &lvinfo, seg, &lv_seg_status, do_info, do_status);
+ if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL,
+ do_info ? &lvinfo : NULL,
+ do_status ? &lv_seg_status : NULL,
+ NULL))
goto out;
r = ECMD_PROCESSED;
@@ -113,58 +153,77 @@ out:
return r;
}
-static int _segs_single(struct cmd_context *cmd __attribute__((unused)),
- struct lv_segment *seg, void *handle)
+static int _segs_single(struct cmd_context *cmd, struct lv_segment *seg,
+ void *handle)
{
- if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL, NULL, NULL, NULL))
- return_ECMD_FAILED;
+ return _do_segs_with_info_and_status_single(cmd, seg, 0, 0, handle);
+}
- return ECMD_PROCESSED;
+static int _segs_with_info_single(struct cmd_context *cmd, struct lv_segment *seg,
+ void *handle)
+{
+ return _do_segs_with_info_and_status_single(cmd, seg, 1, 0, handle);
}
-static int _segs_with_lv_info_single(struct cmd_context *cmd __attribute__((unused)),
- struct lv_segment *seg, void *handle)
+static int _segs_with_status_single(struct cmd_context *cmd, struct lv_segment *seg,
+ void *handle)
{
- struct lvinfo lvinfo;
+ return _do_segs_with_info_and_status_single(cmd, seg, 0, 1, handle);
+}
- _get_lv_info_for_report(cmd, seg->lv, &lvinfo);
- if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL, &lvinfo, NULL, NULL))
- return_ECMD_FAILED;
+static int _segs_with_info_and_status_single(struct cmd_context *cmd, struct lv_segment *seg,
+ void *handle)
+{
+ return _do_segs_with_info_and_status_single(cmd, seg, 1, 1, handle);
+}
- return ECMD_PROCESSED;
+static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
+{
+ if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+ return ECMD_PROCESSED;
+
+ return process_each_segment_in_lv(cmd, lv, handle, _segs_single);
}
-static int _segs_with_lv_status_single(struct cmd_context *cmd __attribute__((unused)),
- struct lv_segment *seg, void *handle)
+static int _lvsegs_with_info_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
{
- struct lvinfo lvinfo;
- struct lv_seg_status lv_seg_status = { .mem = seg->lv->vg->vgmem,
- .type = SEG_STATUS_NONE,
- .status = NULL };
- int r = ECMD_FAILED;
+ if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+ return ECMD_PROCESSED;
- _get_lv_info_with_segment_status_for_report(cmd, seg->lv, &lvinfo, seg, &lv_seg_status);
- if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL, &lvinfo, &lv_seg_status, NULL))
- goto_out;
+ return process_each_segment_in_lv(cmd, lv, handle, _segs_with_info_single);
+}
- r = ECMD_PROCESSED;
-out:
- if (lv_seg_status.status)
- dm_pool_free(lv_seg_status.mem, lv_seg_status.status);
- return r;
+static int _lvsegs_with_status_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
+{
+ if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+ return ECMD_PROCESSED;
+
+ return process_each_segment_in_lv(cmd, lv, handle, _segs_with_status_single);
+}
+
+static int _lvsegs_with_info_and_status_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
+{
+ if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
+ return ECMD_PROCESSED;
+
+ return process_each_segment_in_lv(cmd, lv, handle, _segs_with_info_and_status_single);
}
static int _do_pvsegs_sub_single(struct cmd_context *cmd,
struct volume_group *vg,
struct pv_segment *pvseg,
- int lv_info_needed,
- int lv_seg_status_needed,
+ int do_info,
+ int do_status,
void *handle)
{
int ret = ECMD_PROCESSED;
struct lv_segment *seg = pvseg->lvseg;
struct lvinfo lvinfo = { .exists = 0 };
- struct lv_seg_status lv_seg_status;
+ struct lv_seg_status lv_seg_status = { .type = SEG_STATUS_NONE };
struct segment_type _freeseg_type = {
.name = "free",
@@ -199,8 +258,8 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd,
.origin_list = DM_LIST_HEAD_INIT(_free_lv_segment.origin_list),
};
- if (seg && lv_info_needed)
- _get_lv_info_for_report(cmd, seg->lv, &lvinfo);
+ if (seg)
+ _do_info_and_status(cmd, seg->lv, &lvinfo, seg, &lv_seg_status, do_info, do_status);
if (!report_object(handle, vg, seg ? seg->lv : &_free_logical_volume, pvseg->pv,
seg ? : &_free_lv_segment, pvseg, &lvinfo, &lv_seg_status,
@@ -215,7 +274,8 @@ static int _do_pvsegs_sub_single(struct cmd_context *cmd,
static int _pvsegs_sub_single(struct cmd_context *cmd,
struct volume_group *vg,
- struct pv_segment *pvseg, void *handle)
+ struct pv_segment *pvseg,
+ void *handle)
{
return _do_pvsegs_sub_single(cmd, vg, pvseg, 0, 0, handle);
}
@@ -228,40 +288,28 @@ static int _pvsegs_with_lv_info_sub_single(struct cmd_context *cmd,
return _do_pvsegs_sub_single(cmd, vg, pvseg, 1, 0, handle);
}
-static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv,
- void *handle)
+static int _pvsegs_with_lv_status_sub_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct pv_segment *pvseg,
+ void *handle)
{
- if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
- return ECMD_PROCESSED;
-
- return process_each_segment_in_lv(cmd, lv, handle, _segs_single);
+ return _do_pvsegs_sub_single(cmd, vg, pvseg, 0, 1, handle);
}
-static int _lvsegs_with_lv_info_single(struct cmd_context *cmd,
- struct logical_volume *lv,
- void *handle)
+static int _pvsegs_with_lv_info_and_status_sub_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct pv_segment *pvseg,
+ void *handle)
{
- if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
- return ECMD_PROCESSED;
-
- return process_each_segment_in_lv(cmd, lv, handle, _segs_with_lv_info_single);
+ return _do_pvsegs_sub_single(cmd, vg, pvseg, 1, 1, handle);
}
-static int _lvsegs_with_lv_status_single(struct cmd_context *cmd,
- struct logical_volume *lv,
- void *handle)
-{
- if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
- return ECMD_PROCESSED;
-
- return process_each_segment_in_lv(cmd, lv, handle, _segs_with_lv_status_single);
-}
-
-static int _pvsegs_single(struct cmd_context *cmd, struct volume_group *vg,
- struct physical_volume *pv, void *handle)
+static int _pvsegs_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct physical_volume *pv,
+ void *handle)
{
- return process_each_segment_in_pv(cmd, vg, pv, handle,
- _pvsegs_sub_single);
+ return process_each_segment_in_pv(cmd, vg, pv, handle, _pvsegs_sub_single);
}
static int _pvsegs_with_lv_info_single(struct cmd_context *cmd,
@@ -269,8 +317,23 @@ static int _pvsegs_with_lv_info_single(struct cmd_context *cmd,
struct physical_volume *pv,
void *handle)
{
- return process_each_segment_in_pv(cmd, vg, pv, handle,
- _pvsegs_with_lv_info_sub_single);
+ return process_each_segment_in_pv(cmd, vg, pv, handle, _pvsegs_with_lv_info_sub_single);
+}
+
+static int _pvsegs_with_lv_status_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct physical_volume *pv,
+ void *handle)
+{
+ return process_each_segment_in_pv(cmd, vg, pv, handle, _pvsegs_with_lv_status_sub_single);
+}
+
+static int _pvsegs_with_lv_info_and_status_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct physical_volume *pv,
+ void *handle)
+{
+ return process_each_segment_in_pv(cmd, vg, pv, handle, _pvsegs_with_lv_info_and_status_sub_single);
}
static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
@@ -501,9 +564,10 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
/* fall through */
case LVS:
r = process_each_lv(cmd, argc, argv, 0, report_handle,
- lv_segment_status_needed ? &_lvs_with_status_single
- : lv_info_needed ? &_lvs_with_info_single
- : &_lvs_single);
+ lv_info_needed && !lv_segment_status_needed ? &_lvs_with_info_single :
+ !lv_info_needed && lv_segment_status_needed ? &_lvs_with_status_single :
+ lv_info_needed && lv_segment_status_needed ? &_lvs_with_info_and_status_single :
+ &_lvs_single);
break;
case VGS:
r = process_each_vg(cmd, argc, argv, 0,
@@ -525,16 +589,19 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
/* fall through */
case SEGS:
r = process_each_lv(cmd, argc, argv, 0, report_handle,
- lv_segment_status_needed ? &_lvsegs_with_lv_status_single
- :lv_info_needed ? &_lvsegs_with_lv_info_single
- : &_lvsegs_single);
+ lv_info_needed && !lv_segment_status_needed ? &_lvsegs_with_info_single :
+ !lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_status_single :
+ lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_info_and_status_single :
+ &_lvsegs_single);
break;
case PVSEGS:
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL, 0,
report_handle,
- lv_info_needed ? &_pvsegs_with_lv_info_single
- : &_pvsegs_single);
+ lv_info_needed && !lv_segment_status_needed ? &_pvsegs_with_lv_info_single :
+ !lv_info_needed && lv_segment_status_needed ? &_pvsegs_with_lv_status_single :
+ lv_info_needed && lv_segment_status_needed ? &_pvsegs_with_lv_info_and_status_single :
+ &_pvsegs_single);
else
r = process_each_vg(cmd, argc, argv, 0,
report_handle, &_pvsegs_in_vg);
9 years, 6 months
master - cleanup: cleanup internal interface to acquire segment status
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=83308fdff97e24...
Commit: 83308fdff97e242f6124858b35437ede6ee6a7e8
Parent: efe5245e47201e1947ce0bf60990a7de2151e296
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Nov 13 11:41:49 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Nov 13 14:28:51 2014 +0100
cleanup: cleanup internal interface to acquire segment status
- Add separate lv_status fn (if we're interested only in seg status,
but not lv info at the same time as it is with existing
lv_info_with_seg_status fn). So we 3 fns:
- lv_info (existing one, runs only info ioctl, fills in struct lvinfo only)
- lv_status (new one, runs status ioctl, fills in struct lv_seg_status only)
- lv_info_with_seg_status (existing one, runs status ioctl, fills
in struct lvinfo as well as lv_seg_status)
- Add more comments in the code explaining the difference between lv_info,
lv_status and lv_info_with_seg_status and their return values.
- Move decision whether lv_info_with_seg_status needs to call only
status ioctl (in case the segment for which we require status is from
the LV for which we require info) or separate status and info ioctl
(in case the segment for which we require status is from different
LV that the one for which we require info) into
lv_info_with_seg_status fn so caller doesn't need to bother about
this at all.
- Cleanup internal interface for this seg status so it's more readable.
---
lib/activate/activate.c | 54 +++++++++++++++++++++++++++++++++++++------
lib/activate/activate.h | 21 ++++++++++++++--
tools/reporter.c | 58 ++++++++++++++++------------------------------
3 files changed, 84 insertions(+), 49 deletions(-)
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index ddbebf7..60dba1b 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -618,7 +618,8 @@ int target_present(struct cmd_context *cmd, const char *target_name,
}
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
- int use_layer, struct lvinfo *info, struct lv_seg_status *seg_status,
+ int use_layer, struct lvinfo *info,
+ struct lv_segment *seg, struct lv_seg_status *seg_status,
int with_open_count, int with_read_ahead)
{
struct dm_info dminfo;
@@ -640,6 +641,9 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
if (!use_layer && lv_is_new_thin_pool(lv))
use_layer = 1;
+ if (seg_status)
+ seg_status->seg = seg;
+
if (!dev_manager_info(cmd->mem, lv,
(use_layer) ? lv_layer(lv) : NULL,
with_open_count, with_read_ahead,
@@ -672,7 +676,7 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
if (!activation())
return 0;
- return _lv_info(cmd, lv, use_layer, info, NULL, with_open_count, with_read_ahead);
+ return _lv_info(cmd, lv, use_layer, info, NULL, NULL, with_open_count, with_read_ahead);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
@@ -690,19 +694,53 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
return r;
}
+/*
+ * Returns 1 if lv_seg_status structure populated,
+ * else 0 on failure or if device not active locally.
+ */
+int lv_status(struct cmd_context *cmd, struct lv_segment *lv_seg,
+ struct lv_seg_status *lv_seg_status)
+{
+ if (!activation())
+ return 0;
+
+ return _lv_info(cmd, lv_seg->lv, 0, NULL, lv_seg, lv_seg_status, 0, 0);
+}
+
+/*
+ * Returns 1 if lv_with_info_and_seg_status structure populated,
+ * else 0 on failure or if device not active locally.
+ *
+ * This is the same as calling lv_info and lv_status,
+ * but* it's done in one go with one ioctl if possible!
+ */
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
- const struct lv_segment *lv_seg, int use_layer,
- struct lv_with_info_and_seg_status *lvdm,
+ struct lv_segment *lv_seg, int use_layer,
+ struct lvinfo *lvinfo, struct lv_seg_status *lv_seg_status,
int with_open_count, int with_read_ahead)
{
+ int r = 0;
+
if (!activation())
return 0;
- if (!_lv_info(cmd, lv, use_layer, lvdm->info, lvdm->seg_status,
- with_open_count, with_read_ahead))
- return 0;
+ if (lv == lv_seg->lv) {
+ r = _lv_info(cmd, lv, use_layer, lvinfo, lv_seg, lv_seg_status,
+ with_open_count, with_read_ahead);
+ goto out;
+ }
- return 1;
+ /*
+ * If the info is requested for an LV and segment
+ * status for segment that belong to another LV,
+ * we need to acquire info and status separately!
+ */
+ return _lv_info(cmd, lv, use_layer, lvinfo, NULL, NULL, with_open_count, with_read_ahead) &&
+ _lv_info(cmd, lv_seg->lv, use_layer, NULL, lv_seg, lv_seg_status, 0, 0);
+
+ r = 1;
+out:
+ return r;
}
#define OPEN_COUNT_CHECK_RETRIES 25
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index 86c53f5..ef375bd 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -111,16 +111,31 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
/*
- * Returns 1 if info structure has been populated, else 0.
+ * Returns 1 if info structure has been populated, else 0 on failure.
+ * When lvinfo* is NULL, it returns 1 if the device is locally active, 0 otherwise.
*/
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer,
struct lvinfo *info, int with_open_count, int with_read_ahead);
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
struct lvinfo *info, int with_open_count, int with_read_ahead);
+/*
+ * Returns 1 if lv_seg_status structure has been populated,
+ * else 0 on failure or if device not active locally.
+ */
+int lv_status(struct cmd_context *cmd, struct lv_segment *lv_seg,
+ struct lv_seg_status *lv_seg_status);
+
+/*
+ * Returns 1 if lv_info_and_seg_status structure has been populated,
+ * else 0 on failure or if device not active locally.
+ *
+ * lv_info_with_seg_status is the same as calling lv_info and then lv_seg_status,
+ * but this fn tries to do that with one ioctl if possible.
+ */
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
- const struct lv_segment *lv_seg, int use_layer,
- struct lv_with_info_and_seg_status *lvdm,
+ struct lv_segment *lv_seg, int use_layer,
+ struct lvinfo *lvinfo, struct lv_seg_status *lv_seg_status,
int with_open_count, int with_read_ahead);
int lv_check_not_in_use(const struct logical_volume *lv);
diff --git a/tools/reporter.c b/tools/reporter.c
index 8fe5698..65edec5b 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -57,10 +57,13 @@ static void _get_lv_info_for_report(struct cmd_context *cmd,
}
static void _get_lv_info_with_segment_status_for_report(struct cmd_context *cmd,
- struct lv_with_info_and_seg_status *lvdm)
+ struct logical_volume *lv,
+ struct lvinfo *lvinfo,
+ struct lv_segment *lv_seg,
+ struct lv_seg_status *lv_seg_status)
{
- if (!lv_info_with_seg_status(cmd, lvdm->seg_status->seg->lv, lvdm->seg_status->seg, 0, lvdm, 1, 1))
- lvdm->info->exists = 0;
+ if (!lv_info_with_seg_status(cmd, lv, lv_seg, 0, lvinfo, lv_seg_status, 1, 1))
+ lvinfo->exists = 0;
}
static int _lvs_with_info_single(struct cmd_context *cmd, struct logical_volume *lv,
@@ -75,7 +78,7 @@ static int _lvs_with_info_single(struct cmd_context *cmd, struct logical_volume
return ECMD_PROCESSED;
}
-static void _choose_lv_segment_for_status_report(struct lv_with_info_and_seg_status *lvdm)
+static void _choose_lv_segment_for_status_report(struct logical_volume *lv, struct lv_segment **lv_seg)
{
/*
* By default, take the first LV segment to report status for.
@@ -84,46 +87,29 @@ static void _choose_lv_segment_for_status_report(struct lv_with_info_and_seg_sta
* to lvdm->seg_status->seg. This is the segment whose
* status line will be used for report exactly.
*/
- lvdm->seg_status->seg = first_seg(lvdm->lv);
+ *lv_seg = first_seg(lv);
}
static int _lvs_with_status_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
struct lvinfo lvinfo;
+ struct lv_segment *lv_seg;
struct lv_seg_status lv_seg_status = { .mem = lv->vg->vgmem,
.type = SEG_STATUS_NONE,
.status = NULL };
- struct lv_with_info_and_seg_status lvdm = { .lv = lv,
- .seg_status = &lv_seg_status };
int r = ECMD_FAILED;
- _choose_lv_segment_for_status_report(&lvdm);
-
- if (lvdm.seg_status->seg->lv != lv) {
- /*
- * If the info is requested on one LV and segment
- * status on another LV, we need to call these separately.
- */
- _get_lv_info_for_report(cmd, lv, &lvinfo);
- lvdm.info = NULL;
- _get_lv_info_with_segment_status_for_report(cmd, &lvdm);
- } else {
- /*
- * If the info is requested on the same LV as status,
- * we can get info and status in one go!
- */
- lvdm.info = &lvinfo;
- _get_lv_info_with_segment_status_for_report(cmd, &lvdm);
- }
+ _choose_lv_segment_for_status_report(lv, &lv_seg);
+ _get_lv_info_with_segment_status_for_report(cmd, lv, &lvinfo, lv_seg, &lv_seg_status);
- if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL, &lvinfo, lvdm.seg_status, NULL))
+ if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL, &lvinfo, &lv_seg_status, NULL))
goto out;
r = ECMD_PROCESSED;
out:
- if (lvdm.seg_status->status)
- dm_pool_free(lvdm.seg_status->mem, lvdm.seg_status->status);
+ if (lv_seg_status.status)
+ dm_pool_free(lv_seg_status.mem, lv_seg_status.status);
return r;
}
@@ -152,23 +138,19 @@ static int _segs_with_lv_status_single(struct cmd_context *cmd __attribute__((un
struct lv_segment *seg, void *handle)
{
struct lvinfo lvinfo;
- struct lv_seg_status lv_seg_status = { .seg = seg,
- .mem = seg->lv->vg->vgmem,
+ struct lv_seg_status lv_seg_status = { .mem = seg->lv->vg->vgmem,
.type = SEG_STATUS_NONE,
.status = NULL };
- struct lv_with_info_and_seg_status lvdm = { .lv = seg->lv,
- .info = &lvinfo,
- .seg_status = &lv_seg_status };
int r = ECMD_FAILED;
- _get_lv_info_with_segment_status_for_report(cmd, &lvdm);
- if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL, lvdm.info, lvdm.seg_status, NULL))
+ _get_lv_info_with_segment_status_for_report(cmd, seg->lv, &lvinfo, seg, &lv_seg_status);
+ if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL, &lvinfo, &lv_seg_status, NULL))
goto_out;
r = ECMD_PROCESSED;
out:
- if (lvdm.seg_status->status)
- dm_pool_free(lvdm.seg_status->mem, lvdm.seg_status->status);
+ if (lv_seg_status.status)
+ dm_pool_free(lv_seg_status.mem, lv_seg_status.status);
return r;
}
9 years, 6 months
master - pvck: Use non-zero exit status after failure.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=efe5245e47201e...
Commit: efe5245e47201e1947ce0bf60990a7de2151e296
Parent: c3e29903590b596bfead1d84f91a32362d8e640f
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Thu Nov 13 12:26:43 2014 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Thu Nov 13 12:26:43 2014 +0000
pvck: Use non-zero exit status after failure.
---
WHATS_NEW | 1 +
tools/pvck.c | 12 ++++++++----
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 9859939..19f029b 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.113 -
=====================================
+ Exit with non-zero status code when pvck encounters a problem.
Fix clean_tree after activation/resume for cache target (2.02.112).
Version 2.02.112 - 11th November 2014
diff --git a/tools/pvck.c b/tools/pvck.c
index e45e77a..0b868e8 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -18,9 +18,11 @@
int pvck(struct cmd_context *cmd, int argc, char **argv)
{
int i;
+ int ret_max = ECMD_PROCESSED;
/* FIXME: validate cmdline options */
/* FIXME: what does the cmdline look like? */
+
/*
* Use what's on the cmdline directly, and avoid calling into
* some of the other infrastructure functions, so as to avoid
@@ -32,10 +34,12 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Scanning %s", argv[i]);
dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
- pv_analyze(cmd, argv[i],
- arg_uint64_value(cmd, labelsector_ARG,
- UINT64_C(0)));
+ if (!pv_analyze(cmd, argv[i],
+ arg_uint64_value(cmd, labelsector_ARG, UINT64_C(0)))) {
+ stack;
+ ret_max = ECMD_FAILED;
+ }
}
- return ECMD_PROCESSED;
+ return ret_max;
}
9 years, 6 months
master - cleanu: drop duplicate const
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c3e29903590b59...
Commit: c3e29903590b596bfead1d84f91a32362d8e640f
Parent: 8cb79dad0bc8b02ad57a4ffaa137e40c3cb8daaf
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Nov 13 13:15:58 2014 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Nov 13 13:15:58 2014 +0100
cleanu: drop duplicate const
---
lib/activate/dev_manager.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 047e929..32abde7 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -3028,7 +3028,7 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, const
static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
struct lv_activate_opts *laopts, action_t action)
{
- static const char const _action_names[][24] = {
+ static const char _action_names[][24] = {
"PRELOAD", "ACTIVATE", "DEACTIVATE", "SUSPEND", "SUSPEND_WITH_LOCKFS", "CLEAN"
};
const size_t DLID_SIZE = ID_LEN + sizeof(UUID_PREFIX) - 1;
9 years, 6 months
master - pool: fix removal of pool metadata spare
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8cb79dad0bc8b0...
Commit: 8cb79dad0bc8b02ad57a4ffaa137e40c3cb8daaf
Parent: fba86dd42b57626aa276e4f31e56e5d2a4384e48
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Nov 13 13:09:07 2014 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Nov 13 13:09:07 2014 +0100
pool: fix removal of pool metadata spare
Since we support device stack of pools over pool
(thin-pool with cache data volume) the existing code
is no longer able to detect orphan _pmspare.
So instead do a _pmspare check after volume removal,
and remove spare afterwards.
---
lib/metadata/lv_manip.c | 90 ++++++++++++++++++++--------------
test/shell/pvmove-cache-segtypes.sh | 5 ++
2 files changed, 58 insertions(+), 37 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 543f070..ca2a706 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1318,6 +1318,11 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
if (!delete)
return 1;
+ if (lv == lv->vg->pool_metadata_spare_lv) {
+ lv->status &= ~POOL_METADATA_SPARE;
+ lv->vg->pool_metadata_spare_lv = NULL;
+ }
+
/* Remove the LV if it is now empty */
if (!lv->le_count && !unlink_lv_from_vg(lv))
return_0;
@@ -5334,7 +5339,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
int ask_discard;
struct lv_list *lvl;
struct seg_list *sl;
- int is_last_pool;
+ int is_last_pool = lv_is_pool(lv);
vg = lv->vg;
@@ -5428,11 +5433,34 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
log_print_unless_silent("Ignoring uncache failure of %s.",
display_lvname(lv));
}
+ is_last_pool = 1;
+ }
+
+ /* Used cache pool or COW cannot be activated */
+ if ((!lv_is_cache_pool(lv) || dm_list_empty(&lv->segs_using_this_lv)) &&
+ !lv_is_cow(lv) &&
+ !deactivate_lv(cmd, lv)) {
+ /* FIXME Review and fix the snapshot error paths! */
+ log_error("Unable to deactivate logical volume %s.",
+ display_lvname(lv));
+ return 0;
}
if (!archive(vg))
return 0;
+ /* Clear thin pool stacked messages */
+ if (pool_lv && !pool_has_message(first_seg(pool_lv), lv, 0) &&
+ !update_pool_lv(pool_lv, 1)) {
+ if (force < DONT_PROMPT_OVERRIDE) {
+ log_error("Failed to update pool %s.", display_lvname(pool_lv));
+ return 0;
+ }
+ log_print_unless_silent("Ignoring update failure of pool %s.",
+ display_lvname(pool_lv));
+ pool_lv = NULL; /* Do not retry */
+ }
+
/* When referenced by the LV with pending delete flag, remove this deleted LV first */
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
if (lv_is_pending_delete(sl->seg->lv) && !lv_remove(sl->seg->lv)) {
@@ -5450,26 +5478,12 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
/* vg_remove_snapshot() will preload origin/former snapshots */
if (!vg_remove_snapshot(lv))
return_0;
- }
- if (lv_is_pool(lv) && lv->vg->pool_metadata_spare_lv) {
- /* When removing last pool, also remove the spare */
- is_last_pool = 1;
- dm_list_iterate_items(lvl, &lv->vg->lvs)
- if (lv_is_pool(lvl->lv) &&
- lvl->lv != lv) {
- is_last_pool = 0;
- break;
- }
- if (is_last_pool) {
- /* This is purely internal LV volume, no question */
- if (!deactivate_lv(cmd, lv->vg->pool_metadata_spare_lv)) {
- log_error("Unable to deactivate logical volume %s",
- display_lvname(lv->vg->pool_metadata_spare_lv));
- return 0;
- }
- if (!lv_remove(lv->vg->pool_metadata_spare_lv))
- return_0;
+ if (!deactivate_lv(cmd, lv)) {
+ /* FIXME Review and fix the snapshot error paths! */
+ log_error("Unable to deactivate logical volume %s.",
+ display_lvname(lv));
+ return 0;
}
}
@@ -5483,23 +5497,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
if (!lv_cache_remove(cache_seg->lv))
return_0;
}
- } else if (!deactivate_lv(cmd, lv)) {
- /* FIXME Review and fix the snapshot error paths! */
- log_error("Unable to deactivate logical volume \"%s\"",
- lv->name);
- return 0;
- }
-
- /* Clear thin pool stacked messages */
- if (pool_lv && !pool_has_message(first_seg(pool_lv), lv, 0) &&
- !update_pool_lv(pool_lv, 1)) {
- if (force < DONT_PROMPT_OVERRIDE) {
- log_error("Failed to update pool %s.", display_lvname(pool_lv));
- return 0;
- }
- log_print_unless_silent("Ignoring update failure of pool %s.",
- display_lvname(pool_lv));
- pool_lv = NULL; /* Do not retry */
}
visible = lv_is_visible(lv);
@@ -5510,6 +5507,25 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
+ if (is_last_pool && vg->pool_metadata_spare_lv) {
+ /* When removed last pool, also remove the spare */
+ dm_list_iterate_items(lvl, &vg->lvs)
+ if (lv_is_pool_metadata(lvl->lv)) {
+ is_last_pool = 0;
+ break;
+ }
+ if (is_last_pool) {
+ /* This is purely internal LV volume, no question */
+ if (!deactivate_lv(cmd, vg->pool_metadata_spare_lv)) {
+ log_error("Unable to deactivate spare logical volume %s.",
+ display_lvname(vg->pool_metadata_spare_lv));
+ return 0;
+ }
+ if (!lv_remove(vg->pool_metadata_spare_lv))
+ return_0;
+ }
+ }
+
/*
* Old format1 code: If no snapshots left reload without -real.
*/
diff --git a/test/shell/pvmove-cache-segtypes.sh b/test/shell/pvmove-cache-segtypes.sh
index 9eaf186..2f09596 100644
--- a/test/shell/pvmove-cache-segtypes.sh
+++ b/test/shell/pvmove-cache-segtypes.sh
@@ -56,6 +56,7 @@ not check lv_tree_on $vg ${lv1}_pool "$dev5"
#check lv_tree_on $vg ${lv1}_foo "$dev5"
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of origin LV
#############################
@@ -82,6 +83,7 @@ not check lv_tree_on $vg ${lv1} "$dev3"
#check lv_tree_on $vg ${lv1} "$dev1"
#check dev_md5sum $vg $lv1
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of a RAID origin LV
####################################
@@ -106,6 +108,7 @@ not check lv_tree_on $vg ${lv1} "$dev2" "$dev3"
#check lv_tree_on $vg ${lv1}_pool "$dev5"
#check dev_md5sum $vg $lv1
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of a RAID cachepool (metadata and data)
########################################################
@@ -137,6 +140,7 @@ not check lv_tree_on $vg ${lv1}_pool "$dev2" "$dev3"
#check lv_tree_on $vg ${lv1} "$dev5"
#check dev_md5sum $vg $lv1
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of Thin-pool on cache LV on RAID
#################################################
@@ -177,5 +181,6 @@ check lv_tree_on $vg thinpool "$dev3" "$dev4" "$dev5" # Move non-cache tmeta
#check dev_md5sum $vg/thin_lv
lvremove -ff $vg
+dmsetup info -c | not grep $vg
done
9 years, 6 months
master - pool: fix removal of pool metadata spare
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1d39504b6bd904...
Commit: 1d39504b6bd904e7b4812d6226c31a29ad2937e6
Parent: fba86dd42b57626aa276e4f31e56e5d2a4384e48
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Nov 13 11:53:18 2014 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Nov 13 11:55:53 2014 +0100
pool: fix removal of pool metadata spare
Since we support device stack of pools over pool
(thin-pool with cache data volume) the existing code
is no longer able to detect orphan _pmspare.
So instead do a _pmspare check after volume removal,
and remove spare afterwards.
---
lib/metadata/lv_manip.c | 85 +++++++++++++++++++----------------
test/shell/pvmove-cache-segtypes.sh | 5 ++
2 files changed, 51 insertions(+), 39 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 543f070..ab2ffa1 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1318,6 +1318,11 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
if (!delete)
return 1;
+ if (lv == lv->vg->pool_metadata_spare_lv) {
+ lv->status &= ~POOL_METADATA_SPARE;
+ lv->vg->pool_metadata_spare_lv = NULL;
+ }
+
/* Remove the LV if it is now empty */
if (!lv->le_count && !unlink_lv_from_vg(lv))
return_0;
@@ -5334,7 +5339,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
int ask_discard;
struct lv_list *lvl;
struct seg_list *sl;
- int is_last_pool;
+ int is_last_pool = lv_is_pool(lv);
vg = lv->vg;
@@ -5428,11 +5433,32 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
log_print_unless_silent("Ignoring uncache failure of %s.",
display_lvname(lv));
}
+ is_last_pool = 1;
+ }
+
+ if ((!lv_is_cache_pool(lv) || dm_list_empty(&lv->segs_using_this_lv)) &&
+ !deactivate_lv(cmd, lv)) {
+ /* FIXME Review and fix the snapshot error paths! */
+ log_error("Unable to deactivate logical volume %s.",
+ display_lvname(lv));
+ return 0;
}
if (!archive(vg))
return 0;
+ /* Clear thin pool stacked messages */
+ if (pool_lv && !pool_has_message(first_seg(pool_lv), lv, 0) &&
+ !update_pool_lv(pool_lv, 1)) {
+ if (force < DONT_PROMPT_OVERRIDE) {
+ log_error("Failed to update pool %s.", display_lvname(pool_lv));
+ return 0;
+ }
+ log_print_unless_silent("Ignoring update failure of pool %s.",
+ display_lvname(pool_lv));
+ pool_lv = NULL; /* Do not retry */
+ }
+
/* When referenced by the LV with pending delete flag, remove this deleted LV first */
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
if (lv_is_pending_delete(sl->seg->lv) && !lv_remove(sl->seg->lv)) {
@@ -5452,27 +5478,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return_0;
}
- if (lv_is_pool(lv) && lv->vg->pool_metadata_spare_lv) {
- /* When removing last pool, also remove the spare */
- is_last_pool = 1;
- dm_list_iterate_items(lvl, &lv->vg->lvs)
- if (lv_is_pool(lvl->lv) &&
- lvl->lv != lv) {
- is_last_pool = 0;
- break;
- }
- if (is_last_pool) {
- /* This is purely internal LV volume, no question */
- if (!deactivate_lv(cmd, lv->vg->pool_metadata_spare_lv)) {
- log_error("Unable to deactivate logical volume %s",
- display_lvname(lv->vg->pool_metadata_spare_lv));
- return 0;
- }
- if (!lv_remove(lv->vg->pool_metadata_spare_lv))
- return_0;
- }
- }
-
if (lv_is_cache_pool(lv)) {
/* Cache pool removal drops cache layer
* If the cache pool is not linked, we can simply remove it. */
@@ -5483,23 +5488,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
if (!lv_cache_remove(cache_seg->lv))
return_0;
}
- } else if (!deactivate_lv(cmd, lv)) {
- /* FIXME Review and fix the snapshot error paths! */
- log_error("Unable to deactivate logical volume \"%s\"",
- lv->name);
- return 0;
- }
-
- /* Clear thin pool stacked messages */
- if (pool_lv && !pool_has_message(first_seg(pool_lv), lv, 0) &&
- !update_pool_lv(pool_lv, 1)) {
- if (force < DONT_PROMPT_OVERRIDE) {
- log_error("Failed to update pool %s.", display_lvname(pool_lv));
- return 0;
- }
- log_print_unless_silent("Ignoring update failure of pool %s.",
- display_lvname(pool_lv));
- pool_lv = NULL; /* Do not retry */
}
visible = lv_is_visible(lv);
@@ -5510,6 +5498,25 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
+ if (is_last_pool && vg->pool_metadata_spare_lv) {
+ /* When removed last pool, also remove the spare */
+ dm_list_iterate_items(lvl, &vg->lvs)
+ if (lv_is_pool_metadata(lvl->lv)) {
+ is_last_pool = 0;
+ break;
+ }
+ if (is_last_pool) {
+ /* This is purely internal LV volume, no question */
+ if (!deactivate_lv(cmd, vg->pool_metadata_spare_lv)) {
+ log_error("Unable to deactivate spare logical volume %s.",
+ display_lvname(vg->pool_metadata_spare_lv));
+ return 0;
+ }
+ if (!lv_remove(vg->pool_metadata_spare_lv))
+ return_0;
+ }
+ }
+
/*
* Old format1 code: If no snapshots left reload without -real.
*/
diff --git a/test/shell/pvmove-cache-segtypes.sh b/test/shell/pvmove-cache-segtypes.sh
index 9eaf186..2f09596 100644
--- a/test/shell/pvmove-cache-segtypes.sh
+++ b/test/shell/pvmove-cache-segtypes.sh
@@ -56,6 +56,7 @@ not check lv_tree_on $vg ${lv1}_pool "$dev5"
#check lv_tree_on $vg ${lv1}_foo "$dev5"
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of origin LV
#############################
@@ -82,6 +83,7 @@ not check lv_tree_on $vg ${lv1} "$dev3"
#check lv_tree_on $vg ${lv1} "$dev1"
#check dev_md5sum $vg $lv1
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of a RAID origin LV
####################################
@@ -106,6 +108,7 @@ not check lv_tree_on $vg ${lv1} "$dev2" "$dev3"
#check lv_tree_on $vg ${lv1}_pool "$dev5"
#check dev_md5sum $vg $lv1
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of a RAID cachepool (metadata and data)
########################################################
@@ -137,6 +140,7 @@ not check lv_tree_on $vg ${lv1}_pool "$dev2" "$dev3"
#check lv_tree_on $vg ${lv1} "$dev5"
#check dev_md5sum $vg $lv1
lvremove -ff $vg
+dmsetup info -c | not grep $vg
# Testing pvmove of Thin-pool on cache LV on RAID
#################################################
@@ -177,5 +181,6 @@ check lv_tree_on $vg thinpool "$dev3" "$dev4" "$dev5" # Move non-cache tmeta
#check dev_md5sum $vg/thin_lv
lvremove -ff $vg
+dmsetup info -c | not grep $vg
done
9 years, 6 months
master - cache: improve pending_delete
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fba86dd42b5762...
Commit: fba86dd42b57626aa276e4f31e56e5d2a4384e48
Parent: 359dc6fa76f765a5503b3fda7a596984272a4a4e
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Nov 13 10:08:40 2014 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Nov 13 11:54:41 2014 +0100
cache: improve pending_delete
We need to stop guessing deleted names - so rather collect
deleted UUID into a string list - and then remove them properly
in _clean_tree. Restore origin _clean_tree behaviour them for
currently unconverted removal of snapshots.
Pending delete feature now properly tracks whole subtree of cache
(so i.e. data or metadata as raid volumes).
It properly replaces all related volumes with 'errors' in suspend
preload, then resume them as error and remove collected UUIDs
from root - since they are not longer part of any volume deps.
---
lib/activate/dev_manager.c | 121 +++++++++++++++++++++++--------------------
1 files changed, 65 insertions(+), 56 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 6e5b785..047e929 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -25,6 +25,7 @@
#include "config.h"
#include "activate.h"
#include "lvm-exec.h"
+#include "str_list.h"
#include <limits.h>
#include <dirent.h>
@@ -44,6 +45,12 @@ typedef enum {
/* This list must match lib/misc/lvm-string.c:build_dm_uuid(). */
const char *uuid_suffix_list[] = { "pool", "cdata", "cmeta", "tdata", "tmeta", NULL};
+struct dlid_list {
+ struct dm_list list;
+ const char *dlid;
+ const struct logical_volume *lv;
+};
+
struct dev_manager {
struct dm_pool *mem;
@@ -54,6 +61,8 @@ struct dev_manager {
int flush_required;
int activation; /* building activation tree */
int skip_external_lv;
+ struct dm_list pending_delete; /* str_list of dlid(s) with pending delete */
+ unsigned track_pending_delete;
unsigned track_pvmove_deps;
char *vg_name;
@@ -1069,6 +1078,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
dm_udev_set_sync_support(cmd->current_settings.udev_sync);
+ dm_list_init(&dm->pending_delete);
+
return dm;
bad:
@@ -1726,6 +1737,12 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return 0;
}
+ if (info.exists && dm->track_pending_delete) {
+ log_debug_activation("Tracking pending delete for %s (%s).", lv->name, dlid);
+ if (!str_list_add(dm->mem, &dm->pending_delete, dlid))
+ return_0;
+ }
+
return 1;
}
@@ -2044,13 +2061,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
}
if (lv_is_cache(lv)) {
- if (lv_is_pending_delete(lv)) {
- if (!_add_lv_to_dtree(dm, dtree, first_seg(lv)->pool_lv, 1)) /* stack */
- return_0;
- /* Orhan cache LV exits here */
- return 1;
- }
- if (!origin_only && !dm->activation) {
+ if (!origin_only && !dm->activation && !dm->track_pending_delete) {
/* Setup callback for non-activation partial tree */
/* Activation gets own callback when needed */
/* TODO: extend _cached_dm_info() to return dnode */
@@ -2080,13 +2091,16 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dm->track_pvmove_deps = 1;
}
- dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
- if (lv_is_pending_delete(sl->seg->lv) && lv_is_cache(sl->seg->lv)) {
- if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
- return_0;
- break;
+ if (!dm->track_pending_delete)
+ dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
+ if (lv_is_pending_delete(sl->seg->lv)) {
+ /* LV is referenced by 'cache pending delete LV */
+ dm->track_pending_delete = 1;
+ if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
+ return_0;
+ dm->track_pending_delete = 0;
+ }
}
- }
/* Adding LV head of replicator adds all other related devs */
if (lv_is_replicator_dev(lv) &&
@@ -2111,6 +2125,8 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s) &&
+ /* origin only for cache without pending delete */
+ (!dm->track_pending_delete || !lv_is_cache(lv)) &&
!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
return_0;
if (seg_is_raid(seg) &&
@@ -2554,21 +2570,24 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
{
uint32_t s;
struct lv_segment *seg_present;
+ const struct segment_type *segtype;
const char *target_name;
/* Ensure required device-mapper targets are loaded */
seg_present = find_snapshot(seg->lv) ? : seg;
- target_name = (seg_present->segtype->ops->target_name ?
- seg_present->segtype->ops->target_name(seg_present, laopts) :
- seg_present->segtype->name);
+ segtype = seg_present->segtype;
+
+ target_name = (segtype->ops->target_name ?
+ segtype->ops->target_name(seg_present, laopts) :
+ segtype->name);
log_debug_activation("Checking kernel supports %s segment type for %s%s%s",
target_name, seg->lv->name,
layer ? "-" : "", layer ? : "");
- if (seg_present->segtype->ops->target_present &&
- !seg_present->segtype->ops->target_present(seg_present->lv->vg->cmd,
- seg_present, NULL)) {
+ if (segtype->ops->target_present &&
+ !segtype->ops->target_present(seg_present->lv->vg->cmd,
+ seg_present, NULL)) {
log_error("Can't process LV %s: %s target support missing "
"from kernel?", seg->lv->name, target_name);
return 0;
@@ -2603,8 +2622,10 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Add any LVs used by this segment */
for (s = 0; s < seg->area_count; ++s) {
if ((seg_type(seg, s) == AREA_LV) &&
- (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
- laopts, NULL)))
+ /* origin only for cache without pending delete */
+ (!dm->track_pending_delete || !seg_is_cache(seg)) &&
+ !_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
+ laopts, NULL))
return_0;
if (seg_is_raid(seg) &&
!_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
@@ -2612,7 +2633,13 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
return_0;
}
- if (!_add_target_to_dtree(dm, dnode, seg, laopts))
+ if (dm->track_pending_delete) {
+ /* Replace target and all its used devs with error mapping */
+ log_debug_activation("Using error for pending delete %s.",
+ seg->lv->name);
+ if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * seg->len))
+ return_0;
+ } else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
return_0;
return 1;
@@ -2685,6 +2712,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
uint32_t max_stripe_size = UINT32_C(0);
uint32_t read_ahead = lv->read_ahead;
uint32_t read_ahead_flags = UINT32_C(0);
+ int save_pending_delete = dm->track_pending_delete;
/* LV with pending delete is never put new into a table */
if (lv_is_pending_delete(lv) && !_cached_dm_info(dm->mem, dtree, lv, NULL))
@@ -2772,29 +2800,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Create table */
dm->pvmove_mirror_count = 0u;
- if (lv_is_pending_delete(lv)) {
+ if (lv_is_pending_delete(lv))
/* Handle LVs with pending delete */
- if (lv_is_cache(lv)) {
- /* Use 'error' for cache, metadata and data volumes */
- seg = first_seg(lv);
- if (!dm_tree_node_add_error_target(dnode, seg_lv(seg, 0)->size))
- return_0;
- seg = first_seg(seg->pool_lv);
- if (!(dlid = build_dm_uuid(dm->mem, seg->metadata_lv, NULL)))
- return_0;
- if ((dnode = dm_tree_find_node_by_uuid(dtree, dlid)) &&
- !dm_tree_node_get_context(dnode) &&
- !dm_tree_node_add_error_target(dnode, seg->metadata_lv->size))
- return_0;
- if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, 0), NULL)))
- return_0;
- if ((dnode = dm_tree_find_node_by_uuid(dtree, dlid)) &&
- !dm_tree_node_get_context(dnode) &&
- !dm_tree_node_add_error_target(dnode, seg_lv(seg, 0)->size))
- return_0;
- }
- return 1;
- }
+ /* Fow now used only by cache segtype, TODO snapshots */
+ dm->track_pending_delete = 1;
/* This is unused cache-pool - make metadata accessible */
if (lv_is_cache_pool(lv))
@@ -2880,6 +2889,8 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
#endif
+ dm->track_pending_delete = save_pending_delete; /* restore */
+
return 1;
}
@@ -2972,12 +2983,20 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
return r;
}
-static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, char *non_toplevel_tree_dlid)
+static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, const char *non_toplevel_tree_dlid)
{
void *handle = NULL;
struct dm_tree_node *child;
char *vgname, *lvname, *layer;
const char *name, *uuid;
+ struct dm_str_list *dl;
+
+ /* Deactivate any tracked pending delete nodes */
+ dm_list_iterate_items(dl, &dm->pending_delete) {
+ log_debug_activation("Deleting tracked UUID %s.", dl->str);
+ if (!dm_tree_deactivate_children(root, dl->str, strlen(dl->str)))
+ return_0;
+ }
while ((child = dm_tree_next_child(&handle, root, 0))) {
if (!(name = dm_tree_node_get_name(child)))
@@ -2992,23 +3011,13 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, char *
}
/* Not meant to be top level? */
- if (!*layer && (!(layer = strchr(uuid + 4, '-')) || strstr(layer, "-pool") || strstr(layer, "-tpool")))
- continue;
-
- /* FIXME: we still occasionally need to activate these at top-level */
- if (((name = strstr(lvname, "_tmeta")) && !name[6]) ||
- ((name = strstr(lvname, "_tdata")) && !name[6]))
+ if (!*layer)
continue;
/* If operation was performed on a partial tree, don't remove it */
if (non_toplevel_tree_dlid && !strcmp(non_toplevel_tree_dlid, uuid))
continue;
- if ((name = strstr(lvname, "_corig")) && !name[6] &&
- /* FIXME: for now just for _corig deactivate LVM subtree, should be generic */
- !dm_tree_deactivate_children(child, "LVM-", 4))
- return_0;
-
if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
return_0;
}
9 years, 6 months