diff --git a/WHATS_NEW b/WHATS_NEW index e1eaade9d..e8dfbced8 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.44 - ==================================== + Use displayable_lvs_in_vg and lv_is_displayable for consistency throughout. Fix race in vgcreate that would result in second caller overwriting first. Fix uninitialised lv_count in vgdisplay -c. Don't skip updating pvid hash when lvmcache_info struct got swapped. diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 95b812a8a..c970da40b 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -666,7 +666,7 @@ int lvs_in_vg_opened(const struct volume_group *vg) return 0; dm_list_iterate_items(lvl, &vg->lvs) { - if (lvl->lv->status & VISIBLE_LV) + if (lv_is_displayable(lvl->lv)) count += (_lv_open_count(vg->cmd, lvl->lv) > 0); } diff --git a/lib/display/display.c b/lib/display/display.c index 8a672f386..c1ae8dbab 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -574,8 +574,6 @@ void vgdisplay_full(const struct volume_group *vg) { uint32_t access_str; uint32_t active_pvs; - uint32_t lv_count = 0; - struct lv_list *lvl; char uuid[64] __attribute((aligned(8))); active_pvs = vg->pv_count - vg_missing_pv_count(vg); @@ -607,12 +605,8 @@ void vgdisplay_full(const struct volume_group *vg) vg->status & SHARED ? "yes" : "no"); } - dm_list_iterate_items(lvl, &vg->lvs) - if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT)) - lv_count++; - log_print("MAX LV %u", vg->max_lv); - log_print("Cur LV %u", lv_count); + log_print("Cur LV %u", displayable_lvs_in_vg(vg)); log_print("Open LV %u", lvs_in_vg_opened(vg)); /****** FIXME Max LV Size log_print ( "MAX LV Size %s", @@ -656,17 +650,11 @@ void vgdisplay_full(const struct volume_group *vg) void vgdisplay_colons(const struct volume_group *vg) { uint32_t active_pvs; - uint32_t lv_count = 0; - struct lv_list *lvl; const char *access_str; char uuid[64] __attribute((aligned(8))); active_pvs = vg->pv_count - vg_missing_pv_count(vg); - dm_list_iterate_items(lvl, &vg->lvs) - if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT)) - lv_count++; - switch (vg->status & (LVM_READ | LVM_WRITE)) { case LVM_READ | LVM_WRITE: access_str = "r/w"; @@ -693,7 +681,7 @@ void vgdisplay_colons(const struct volume_group *vg) vg->status, /* internal volume group number; obsolete */ vg->max_lv, - vg->lv_count, + displayable_lvs_in_vg(vg), lvs_in_vg_opened(vg), /* FIXME: maximum logical volume size */ vg->max_pv, diff --git a/lib/format_text/export.c b/lib/format_text/export.c index 16279ef7d..6f16143d7 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -592,14 +592,14 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg) * Write visible LVs first */ dm_list_iterate_items(lvl, &vg->lvs) { - if (!(lvl->lv->status & VISIBLE_LV)) + if (!(lv_is_displayable(lvl->lv))) continue; if (!_print_lv(f, lvl->lv)) return_0; } dm_list_iterate_items(lvl, &vg->lvs) { - if ((lvl->lv->status & VISIBLE_LV)) + if ((lv_is_displayable(lvl->lv))) continue; if (!_print_lv(f, lvl->lv)) return_0; diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index e5302f9b6..0e40756b9 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -1715,7 +1715,7 @@ int lv_rename(struct cmd_context *cmd, struct logical_volume *lv, struct lv_names lv_names; /* rename is not allowed on sub LVs */ - if (!lv_is_visible(lv)) { + if (!lv_is_displayable(lv)) { log_error("Cannot rename internal LV \"%s\".", lv->name); return 0; } diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index d49eaba01..40ece6f3e 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -483,6 +483,9 @@ int lv_is_origin(const struct logical_volume *lv); int lv_is_cow(const struct logical_volume *lv); int lv_is_visible(const struct logical_volume *lv); +/* Test if given LV is visible from user's perspective */ +int lv_is_displayable(const struct logical_volume *lv); + int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv); /* Given a cow LV, return return the snapshot lv_segment that uses it */ diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index e5a13e64b..a49c4d89e 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -337,6 +337,7 @@ int vg_remove_single(struct cmd_context *cmd, const char *vg_name, { struct physical_volume *pv; struct pv_list *pvl; + unsigned lv_count; int ret = 1; if (!vg || !consistent || vg_missing_pv_count(vg)) { @@ -350,22 +351,26 @@ int vg_remove_single(struct cmd_context *cmd, const char *vg_name, if (!vg_check_status(vg, EXPORTED_VG)) return 0; - if (vg->lv_count) { + lv_count = displayable_lvs_in_vg(vg); + + if (lv_count) { if ((force == PROMPT) && (yes_no_prompt("Do you really want to remove volume " - "group \"%s\" containing %d " + "group \"%s\" containing %u " "logical volumes? [y/n]: ", - vg_name, vg->lv_count) == 'n')) { + vg_name, lv_count) == 'n')) { log_print("Volume group \"%s\" not removed", vg_name); return 0; } if (!remove_lvs_in_vg(cmd, vg, force)) return 0; } + + lv_count = displayable_lvs_in_vg(vg); - if (vg->lv_count) { - log_error("Volume group \"%s\" still contains %d " - "logical volume(s)", vg_name, vg->lv_count); + if (lv_count) { + log_error("Volume group \"%s\" still contains %u " + "logical volume(s)", vg_name, lv_count); return 0; } @@ -1098,6 +1103,18 @@ int vg_remove(struct volume_group *vg) return 1; } +unsigned displayable_lvs_in_vg(const struct volume_group *vg) +{ + struct lv_list *lvl; + unsigned lv_count = 0; + + dm_list_iterate_items(lvl, &vg->lvs) + if (lv_is_displayable(lvl->lv)) + lv_count++; + + return lv_count; +} + /* * Determine whether two vgs are compatible for merging. */ diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 3d9fd8dac..02d47377c 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -320,6 +320,11 @@ int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment * int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg); struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv); +/* + * Count LVs that are visible from user's perspective. + */ +unsigned displayable_lvs_in_vg(const struct volume_group *vg); + /* * For internal metadata caching. */ diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c index a3c7fb89c..9531c921d 100644 --- a/lib/metadata/snapshot_manip.c +++ b/lib/metadata/snapshot_manip.c @@ -36,6 +36,14 @@ int lv_is_visible(const struct logical_volume *lv) return lv->status & VISIBLE_LV ? 1 : 0; } +int lv_is_displayable(const struct logical_volume *lv) +{ + if (lv->status & SNAPSHOT) + return 0; + + return (lv->status & VISIBLE_LV) || lv_is_cow(lv) ? 1 : 0; +} + /* Given a cow LV, return the snapshot lv_segment that uses it */ struct lv_segment *find_cow(const struct logical_volume *lv) { diff --git a/lib/report/report.c b/lib/report/report.c index 437bfd8b6..4c164c9b4 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -511,7 +511,7 @@ static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem, char *repstr, *lvname; size_t len; - if (lv_is_visible(lv)) { + if (lv_is_displayable(lv)) { repstr = lv->name; return dm_report_field_string(rh, field, (const char **) &repstr); } @@ -911,12 +911,9 @@ static int _lvcount_disp(struct dm_report *rh, struct dm_pool *mem, const void *data, void *private) { const struct volume_group *vg = (const struct volume_group *) data; - struct lv_list *lvl; - uint32_t count = 0; + uint32_t count; - dm_list_iterate_items(lvl, &vg->lvs) - if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT)) - count++; + count = displayable_lvs_in_vg(vg); return _uint32_disp(rh, mem, field, &count, private); } diff --git a/tools/lvchange.c b/tools/lvchange.c index 4016c8f57..3c2fa19a2 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -590,7 +590,7 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv, return ECMD_FAILED; } - if (!(lv->status & VISIBLE_LV)) { + if (!(lv_is_displayable(lv))) { log_error("Unable to change internal LV %s directly", lv->name); return ECMD_FAILED; diff --git a/tools/lvdisplay.c b/tools/lvdisplay.c index 16e7052f2..5263e0d12 100644 --- a/tools/lvdisplay.c +++ b/tools/lvdisplay.c @@ -18,7 +18,7 @@ static int _lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { - if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) + if (!arg_count(cmd, all_ARG) && !lv_is_displayable(lv)) return ECMD_PROCESSED; if (arg_count(cmd, colon_ARG)) diff --git a/tools/lvscan.c b/tools/lvscan.c index a286fe17f..1186b3bce 100644 --- a/tools/lvscan.c +++ b/tools/lvscan.c @@ -27,7 +27,7 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv, const char *active_str, *snapshot_str; - if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) + if (!arg_count(cmd, all_ARG) && !lv_is_displayable(lv)) return ECMD_PROCESSED; inkernel = lv_info(cmd, lv, &info, 1, 0) && info.exists; diff --git a/tools/reporter.c b/tools/reporter.c index e95ed5e80..d1907438f 100644 --- a/tools/reporter.c +++ b/tools/reporter.c @@ -36,7 +36,7 @@ static int _vgs_single(struct cmd_context *cmd __attribute((unused)), static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { - if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) + if (!arg_count(cmd, all_ARG) && !lv_is_displayable(lv)) return ECMD_PROCESSED; if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL)) @@ -102,7 +102,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd __attribute((unused)), static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { - if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv)) + if (!arg_count(cmd, all_ARG) && !lv_is_displayable(lv)) return ECMD_PROCESSED; return process_each_segment_in_lv(cmd, lv, handle, _segs_single);