master - lvconvert: show name of activated volume
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=10e3715564e80e...
Commit: 10e3715564e80e08daf04f0ae51067a04dfaa7b8
Parent: e8bbcda2a3a6799ff4e967276f9284c8b808584c
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Aug 14 11:12:02 2014 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Aug 15 15:06:44 2014 +0200
lvconvert: show name of activated volume
Display the name of volume that needs to be activated for merging.
---
WHATS_NEW | 1 +
tools/lvconvert.c | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index e5d4d6d..a5daf80 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.110 -
==================================
+ Print name of LV which on activation triggers delayed snapshot merge.
Add lv_layout and lv_type LV reporting fields.
Properly display lvs lv_attr volume type and target type bit for cache origin.
Fix pvcreate_check() to update cache correctly after signature wiping.
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 333459d..e369def 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2216,7 +2216,8 @@ static int _lvconvert_merge_old_snapshot(struct cmd_context *cmd,
return_0;
r = 1;
log_print_unless_silent("Merging of snapshot %s will start "
- "next activation.", lv->name);
+ "next activation of %s.",
+ display_lvname(lv), display_lvname(origin));
goto out;
}
@@ -2323,7 +2324,8 @@ static int _lvconvert_merge_thin_snapshot(struct cmd_context *cmd,
return_0;
log_print_unless_silent("Merging of thin snapshot %s will occur on "
- "next activation.", lv->name);
+ "next activation of %s.",
+ display_lvname(lv), display_lvname(origin));
r = 1;
out:
backup(lv->vg);
9 years, 8 months
master - Add lv_layout_and_type fn, lv_layout and lv_type reporting fields.
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e8bbcda2a3a679...
Commit: e8bbcda2a3a6799ff4e967276f9284c8b808584c
Parent: 8a7682cbc982004e880a740d61ca5d12f0caf769
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Aug 13 10:03:45 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Aug 15 14:50:38 2014 +0200
Add lv_layout_and_type fn, lv_layout and lv_type reporting fields.
The lv_layout and lv_type fields together help with LV identification.
We can do basic identification using the lv_attr field which provides
very condensed view. In contrast to that, the new lv_layout and lv_type
fields provide more detialed information on exact layout and type used
for LVs.
For top-level LVs which are pure types not combined with any
other LV types, the lv_layout value is equal to lv_type value.
For non-top-level LVs which may be combined with other types,
the lv_layout describes the underlying layout used, while the
lv_type describes the use/type/usage of the LV.
These two new fields are both string lists so selection (-S/--select)
criteria can be defined using the list operators easily:
[] for strict matching
{} for subset matching.
For example, let's consider this:
$ lvs -a -o name,vg_name,lv_attr,layout,type
LV VG Attr Layout Type
[lvol1_pmspare] vg ewi------- linear metadata,pool,spare
pool vg twi-a-tz-- pool,thin pool,thin
[pool_tdata] vg rwi-aor--- level10,raid data,pool,thin
[pool_tdata_rimage_0] vg iwi-aor--- linear image,raid
[pool_tdata_rimage_1] vg iwi-aor--- linear image,raid
[pool_tdata_rimage_2] vg iwi-aor--- linear image,raid
[pool_tdata_rimage_3] vg iwi-aor--- linear image,raid
[pool_tdata_rmeta_0] vg ewi-aor--- linear metadata,raid
[pool_tdata_rmeta_1] vg ewi-aor--- linear metadata,raid
[pool_tdata_rmeta_2] vg ewi-aor--- linear metadata,raid
[pool_tdata_rmeta_3] vg ewi-aor--- linear metadata,raid
[pool_tmeta] vg ewi-aor--- level1,raid metadata,pool,thin
[pool_tmeta_rimage_0] vg iwi-aor--- linear image,raid
[pool_tmeta_rimage_1] vg iwi-aor--- linear image,raid
[pool_tmeta_rmeta_0] vg ewi-aor--- linear metadata,raid
[pool_tmeta_rmeta_1] vg ewi-aor--- linear metadata,raid
thin_snap1 vg Vwi---tz-k thin snapshot,thin
thin_snap2 vg Vwi---tz-k thin snapshot,thin
thin_vol1 vg Vwi-a-tz-- thin thin
thin_vol2 vg Vwi-a-tz-- thin multiple,origin,thin
Which is a situation with thin pool, thin volumes and thin snapshots.
We can see internal 'pool_tdata' volume that makes up thin pool has
actually a level10 raid layout and the internal 'pool_tmeta' has
level1 raid layout. Also, we can see that 'thin_snap1' and 'thin_snap2'
are both thin snapshots while 'thin_vol1' is thin origin (having
multiple snapshots).
Such reporting scheme provides much better base for selection criteria
in addition to providing more detailed information, for example:
$ lvs -a -o name,vg_name,lv_attr,layout,type -S 'type=metadata'
LV VG Attr Layout Type
[lvol1_pmspare] vg ewi------- linear metadata,pool,spare
[pool_tdata_rmeta_0] vg ewi-aor--- linear metadata,raid
[pool_tdata_rmeta_1] vg ewi-aor--- linear metadata,raid
[pool_tdata_rmeta_2] vg ewi-aor--- linear metadata,raid
[pool_tdata_rmeta_3] vg ewi-aor--- linear metadata,raid
[pool_tmeta] vg ewi-aor--- level1,raid metadata,pool,thin
[pool_tmeta_rmeta_0] vg ewi-aor--- linear metadata,raid
[pool_tmeta_rmeta_1] vg ewi-aor--- linear metadata,raid
(selected all LVs which are related to metadata of any type)
lvs -a -o name,vg_name,lv_attr,layout,type -S 'type={metadata,thin}'
LV VG Attr Layout Type
[pool_tmeta] vg ewi-aor--- level1,raid metadata,pool,thin
(selected all LVs which hold metadata related to thin)
lvs -a -o name,vg_name,lv_attr,layout,type -S 'type={thin,snapshot}'
LV VG Attr Layout Type
thin_snap1 vg Vwi---tz-k thin snapshot,thin
thin_snap2 vg Vwi---tz-k thin snapshot,thin
(selected all LVs which are thin snapshots)
lvs -a -o name,vg_name,lv_attr,layout,type -S 'layout=raid'
LV VG Attr Layout Type
[pool_tdata] vg rwi-aor--- level10,raid data,pool,thin
[pool_tmeta] vg ewi-aor--- level1,raid metadata,pool,thin
(selected all LVs with raid layout, any raid layout)
lvs -a -o name,vg_name,lv_attr,layout,type -S 'layout={raid,level1}'
LV VG Attr Layout Type
[pool_tmeta] vg ewi-aor--- level1,raid metadata,pool,thin
(selected all LVs with raid level1 layout exactly)
And so on...
---
WHATS_NEW | 1 +
lib/datastruct/str_list.c | 18 +-
lib/datastruct/str_list.h | 1 +
lib/metadata/lv_manip.c | 485 ++++++++++++++++++++++++++++---------
lib/metadata/metadata-exported.h | 11 +-
lib/metadata/thin_manip.c | 18 +-
lib/report/columns.h | 6 +-
lib/report/properties.c | 8 +-
lib/report/report.c | 61 ++---
9 files changed, 434 insertions(+), 175 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index f6a877d..e5d4d6d 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.110 -
==================================
+ Add lv_layout and lv_type LV reporting fields.
Properly display lvs lv_attr volume type and target type bit for cache origin.
Fix pvcreate_check() to update cache correctly after signature wiping.
Fix primary device lookup failure for partition when processing mpath filter.
diff --git a/lib/datastruct/str_list.c b/lib/datastruct/str_list.c
index f519679..3e429ab 100644
--- a/lib/datastruct/str_list.c
+++ b/lib/datastruct/str_list.c
@@ -30,17 +30,13 @@ struct dm_list *str_list_create(struct dm_pool *mem)
return sl;
}
-int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
+int str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str)
{
struct dm_str_list *sln;
if (!str)
return_0;
- /* Already in list? */
- if (str_list_match_item(sll, str))
- return 1;
-
if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
return_0;
@@ -50,6 +46,18 @@ int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
return 1;
}
+int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
+{
+ if (!str)
+ return_0;
+
+ /* Already in list? */
+ if (str_list_match_item(sll, str))
+ return 1;
+
+ return str_list_add_no_dup_check(mem, sll, str);
+}
+
void str_list_del(struct dm_list *sll, const char *str)
{
struct dm_list *slh, *slht;
diff --git a/lib/datastruct/str_list.h b/lib/datastruct/str_list.h
index 82141e1..a052df6 100644
--- a/lib/datastruct/str_list.h
+++ b/lib/datastruct/str_list.h
@@ -21,6 +21,7 @@ struct dm_pool;
struct dm_list *str_list_create(struct dm_pool *mem);
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
+int str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str);
void str_list_del(struct dm_list *sll, const char *str);
int str_list_match_item(const struct dm_list *sll, const char *str);
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, const char **tag_matched);
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 3e1f9e9..35b898f 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -83,146 +83,395 @@ struct pv_and_int {
int *i;
};
-typedef enum {
+enum {
LV_TYPE_UNKNOWN,
- LV_TYPE_PVMOVE,
- LV_TYPE_ORIGIN,
- LV_TYPE_EXTERNAL_ORIGIN,
- LV_TYPE_SNAPSHOT,
+ LV_TYPE_LINEAR,
+ LV_TYPE_STRIPED,
+ LV_TYPE_MIRROR,
+ LV_TYPE_RAID,
LV_TYPE_THIN,
- LV_TYPE_THIN_SNAPSHOT,
- LV_TYPE_THIN_POOL,
- LV_TYPE_THIN_POOL_DATA,
- LV_TYPE_THIN_POOL_METADATA,
LV_TYPE_CACHE,
- LV_TYPE_CACHE_POOL,
- LV_TYPE_CACHE_POOL_DATA,
- LV_TYPE_CACHE_POOL_METADATA,
- LV_TYPE_POOL_METADATA_SPARE,
+ LV_TYPE_ORIGIN,
+ LV_TYPE_MULTIPLE,
+ LV_TYPE_SNAPSHOT,
+ LV_TYPE_PVMOVE,
+ LV_TYPE_IMAGE,
+ LV_TYPE_LOG,
+ LV_TYPE_METADATA,
+ LV_TYPE_POOL,
+ LV_TYPE_DATA,
+ LV_TYPE_EXTERNAL,
+ LV_TYPE_SPARE,
LV_TYPE_VIRTUAL,
- LV_TYPE_RAID,
- LV_TYPE_RAID_IMAGE,
- LV_TYPE_RAID_METADATA,
- LV_TYPE_MIRROR,
- LV_TYPE_MIRROR_IMAGE,
- LV_TYPE_MIRROR_LOG,
- LV_TYPE_LINEAR,
- LV_TYPE_STRIPED
-} lv_type_t;
+ LV_TYPE_RAID_LEVEL1,
+ LV_TYPE_RAID_LEVEL10,
+ LV_TYPE_RAID_LEVEL4,
+ LV_TYPE_RAID_LEVEL5,
+ LV_TYPE_RAID_LEVEL6,
+ LV_TYPE_RAID_LEFT_ASYMMETRIC,
+ LV_TYPE_RAID_RIGHT_ASYMMETRIC,
+ LV_TYPE_RAID_LEFT_SYMMETRIC,
+ LV_TYPE_RAID_RIGHT_SYMMETRIC,
+ LV_TYPE_RAID_ZERO_RESTART,
+ LV_TYPE_RAID_N_RESTART,
+ LV_TYPE_RAID_N_CONTINUE,
+};
static const char *_lv_type_names[] = {
- [LV_TYPE_UNKNOWN] = "unknown",
- [LV_TYPE_PVMOVE] = "pvmove",
- [LV_TYPE_ORIGIN] = "origin",
- [LV_TYPE_EXTERNAL_ORIGIN] = "external-origin",
- [LV_TYPE_SNAPSHOT] = "snapshot",
- [LV_TYPE_THIN] = "thin",
- [LV_TYPE_THIN_SNAPSHOT] = "thin-snapshot",
- [LV_TYPE_THIN_POOL] = "thin-pool",
- [LV_TYPE_THIN_POOL_DATA] = "thin-pool-data",
- [LV_TYPE_THIN_POOL_METADATA] = "thin-pool-metadata",
- [LV_TYPE_CACHE] = "cache",
- [LV_TYPE_CACHE_POOL] = "cache-pool",
- [LV_TYPE_CACHE_POOL_DATA] = "cache-pool-data",
- [LV_TYPE_CACHE_POOL_METADATA] = "cache-pool-metadata",
- [LV_TYPE_POOL_METADATA_SPARE] = "pool-metadata-spare",
- [LV_TYPE_VIRTUAL] = "virtual",
- [LV_TYPE_RAID] = "raid",
- [LV_TYPE_RAID_IMAGE] = "raid-image",
- [LV_TYPE_RAID_METADATA] = "raid-metadata",
- [LV_TYPE_MIRROR] = "mirror",
- [LV_TYPE_MIRROR_IMAGE] = "mirror-image",
- [LV_TYPE_MIRROR_LOG] = "mirror-log",
- [LV_TYPE_LINEAR] = "linear",
- [LV_TYPE_STRIPED] = "striped"
+ [LV_TYPE_UNKNOWN] = "unknown",
+ [LV_TYPE_LINEAR] = "linear",
+ [LV_TYPE_STRIPED] = "striped",
+ [LV_TYPE_MIRROR] = "mirror",
+ [LV_TYPE_RAID] = "raid",
+ [LV_TYPE_THIN] = "thin",
+ [LV_TYPE_CACHE] = "cache",
+ [LV_TYPE_ORIGIN] = "origin",
+ [LV_TYPE_MULTIPLE] = "multiple",
+ [LV_TYPE_SNAPSHOT] = "snapshot",
+ [LV_TYPE_PVMOVE] = "pvmove",
+ [LV_TYPE_IMAGE] = "image",
+ [LV_TYPE_LOG] = "log",
+ [LV_TYPE_METADATA] = "metadata",
+ [LV_TYPE_POOL] = "pool",
+ [LV_TYPE_DATA] = "data",
+ [LV_TYPE_EXTERNAL] = "external",
+ [LV_TYPE_SPARE] = "spare",
+ [LV_TYPE_VIRTUAL] = "virtual",
+ [LV_TYPE_RAID_LEVEL1] = "level1",
+ [LV_TYPE_RAID_LEVEL10] = "level10",
+ [LV_TYPE_RAID_LEVEL4] = "level4",
+ [LV_TYPE_RAID_LEVEL5] = "level5",
+ [LV_TYPE_RAID_LEVEL6] = "level6",
+ [LV_TYPE_RAID_LEFT_ASYMMETRIC] = "left-asymmetric",
+ [LV_TYPE_RAID_RIGHT_ASYMMETRIC] = "right-asymmetric",
+ [LV_TYPE_RAID_LEFT_SYMMETRIC] = "left-symmetric",
+ [LV_TYPE_RAID_RIGHT_SYMMETRIC] = "right-symmetric",
+ [LV_TYPE_RAID_ZERO_RESTART] = "zero-restart",
+ [LV_TYPE_RAID_N_RESTART] = "n-restart",
+ [LV_TYPE_RAID_N_CONTINUE] = "n-continue",
};
-static lv_type_t _get_lv_type(const struct logical_volume *lv)
+const char *lv_type_name(const struct logical_volume *lv)
{
- lv_type_t type = LV_TYPE_UNKNOWN;
- struct lv_segment *seg;
+ return " ";
+}
- if (lv->status & PVMOVE)
- type = LV_TYPE_PVMOVE;
- else if (lv_is_origin(lv))
- type = LV_TYPE_ORIGIN;
- else if (lv_is_external_origin(lv))
- type = LV_TYPE_EXTERNAL_ORIGIN;
- else if (lv_is_cow(lv))
- type = LV_TYPE_SNAPSHOT;
- else if (lv_is_thin_volume(lv))
- type = first_seg(lv)->origin ? LV_TYPE_THIN_SNAPSHOT : LV_TYPE_THIN;
- else if (lv_is_thin_pool(lv))
- type = LV_TYPE_THIN_POOL;
- else if (lv_is_thin_pool_data(lv))
- type = LV_TYPE_THIN_POOL_DATA;
- else if (lv_is_thin_pool_metadata(lv))
- type = LV_TYPE_THIN_POOL_METADATA;
- else if (lv_is_pool_metadata_spare(lv))
- type = LV_TYPE_POOL_METADATA_SPARE;
- else if (lv_is_cache(lv))
- type = LV_TYPE_CACHE;
- else if (lv_is_cache_pool(lv))
- type = LV_TYPE_CACHE_POOL;
- else if (lv_is_cache_pool_data(lv))
- type = LV_TYPE_CACHE_POOL_DATA;
- else if (lv_is_cache_pool_metadata(lv))
- type = LV_TYPE_CACHE_POOL_METADATA;
- else if (lv_is_virtual(lv))
- type = LV_TYPE_VIRTUAL;
- else if (lv_is_raid(lv))
- type = LV_TYPE_RAID;
- else if (lv_is_raid_image(lv))
- type = LV_TYPE_RAID_IMAGE;
- else if (lv_is_raid_metadata(lv))
- type = LV_TYPE_RAID_METADATA;
- else if (lv_is_mirrored(lv))
- type = LV_TYPE_MIRROR;
- else if (lv_is_mirror_image(lv))
- type = LV_TYPE_MIRROR_IMAGE;
- else if (lv_is_mirror_log(lv))
- type = LV_TYPE_MIRROR_LOG;
-
- /* none of the above, check linear... */
- if (type == LV_TYPE_UNKNOWN) {
- type = LV_TYPE_LINEAR;
- dm_list_iterate_items(seg, &lv->segments) {
- if (!seg_is_linear(seg)) {
- type = LV_TYPE_UNKNOWN;
- break;
- }
- }
+static int _lv_type_list_mirror(struct dm_pool *mem,
+ const struct logical_volume *lv,
+ struct dm_list *layout,
+ struct dm_list *type)
+{
+ int top_level = 1;
+
+ if (lv_is_mirror_image(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_IMAGE]))
+ goto_bad;
+ top_level = 0;
+ } else if (lv_is_mirror_log(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_LOG]))
+ goto_bad;
+ top_level = 0;
+ } else if (lv->status & PVMOVE) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_PVMOVE]))
+ goto_bad;
}
- /* ...if not even linear, check striped... */
- if (type == LV_TYPE_UNKNOWN) {
- type = LV_TYPE_STRIPED;
- dm_list_iterate_items(seg, &lv->segments) {
- if (!seg_is_striped(seg)) {
- type = LV_TYPE_UNKNOWN;
- break;
- }
- }
+ if (top_level) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_MIRROR]))
+ goto_bad;
+ } else {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_MIRROR]))
+ goto_bad;
}
- return type;
+ return 1;
+bad:
+ return 0;
}
-const char *lv_type_name(const struct logical_volume *lv) {
- lv_type_t type = _get_lv_type(lv);
- return _lv_type_names[type];
+static int _lv_type_list_raid(struct dm_pool *mem,
+ const struct logical_volume *lv,
+ struct dm_list *layout,
+ struct dm_list *type)
+{
+ int top_level = 1;
+ const char *seg_name;
+
+ if (lv_is_raid_image(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_IMAGE]))
+ goto_bad;
+ top_level = 0;
+ } else if (lv_is_raid_metadata(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_METADATA]))
+ goto_bad;
+ top_level = 0;
+ } else if (!strcmp(first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID1)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEVEL1]))
+ goto_bad;
+ } else if (!strcmp(first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID10)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEVEL10]))
+ goto_bad;
+ } else if (!strcmp(first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID4)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEVEL4]))
+ goto_bad;
+ } else if (!strncmp(seg_name = first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID5, strlen(SEG_TYPE_NAME_RAID5))) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEVEL5]))
+ goto_bad;
+
+ if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_LA)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEFT_ASYMMETRIC]))
+ goto_bad;
+ } else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_RA)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_RIGHT_ASYMMETRIC]))
+ goto_bad;
+ } else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_LS)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEFT_SYMMETRIC]))
+ goto_bad;
+ } else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_RS)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_RIGHT_SYMMETRIC]))
+ goto_bad;
+ }
+ } else if (!strncmp(seg_name = first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID6, strlen(SEG_TYPE_NAME_RAID6))) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_LEVEL6]))
+ goto_bad;
+
+ if (!strcmp(seg_name, SEG_TYPE_NAME_RAID6_ZR)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_ZERO_RESTART]))
+ goto_bad;
+ } else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID6_NR)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_N_RESTART]))
+ goto_bad;
+ } else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID6_NC)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID_N_CONTINUE]))
+ goto_bad;
+ }
+ }
+
+ if (top_level) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID]))
+ goto_bad;
+ } else {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_RAID]))
+ goto_bad;
+ }
+
+ return 1;
+bad:
+ return 0;
}
-int lv_is_linear(const struct logical_volume *lv)
+static int _lv_type_list_thin(struct dm_pool *mem,
+ const struct logical_volume *lv,
+ struct dm_list *layout,
+ struct dm_list *type)
{
- lv_type_t type = _get_lv_type(lv);
- return type == LV_TYPE_LINEAR;
+ int top_level = 1;
+ unsigned snapshot_count;
+
+ if (lv_is_thin_pool(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_THIN]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_POOL]))
+ goto_bad;
+ } else if (lv_is_thin_pool_metadata(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_METADATA]))
+ goto_bad;
+ top_level = 0;
+ } else if (lv_is_thin_pool_data(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_DATA]))
+ goto_bad;
+ top_level = 0;
+ } else if (lv_is_thin_volume(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_THIN]))
+ goto_bad;
+ if (lv_is_thin_origin(lv, &snapshot_count) &&
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_ORIGIN]))
+ goto_bad;
+ if (snapshot_count > 1 &&
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_MULTIPLE]))
+ goto_bad;
+ if (first_seg(lv)->origin)
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_SNAPSHOT]))
+ goto_bad;
+ }
+
+ if (lv_is_external_origin(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_ORIGIN]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_EXTERNAL]))
+ goto_bad;
+ top_level = 0;
+ }
+
+ if (top_level) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_THIN]))
+ goto_bad;
+ } else {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_THIN]))
+ goto_bad;
+ }
+
+ return 1;
+bad:
+ return 0;
}
-int lv_is_striped(const struct logical_volume *lv)
+static int _lv_type_list_cache(struct dm_pool *mem,
+ const struct logical_volume *lv,
+ struct dm_list *layout,
+ struct dm_list *type)
{
- lv_type_t type = _get_lv_type(lv);
- return type == LV_TYPE_STRIPED;
+ int top_level = 1;
+
+ if (lv_is_cache_pool(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_CACHE]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_POOL]))
+ goto_bad;
+ } else if (lv_is_cache_pool_metadata(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_METADATA]))
+ goto_bad;
+ top_level = 0;
+ } else if (lv_is_cache_pool_data(lv)) {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_DATA]))
+ goto_bad;
+ top_level = 0;
+ }
+
+ if (top_level) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_CACHE]))
+ goto_bad;
+ } else {
+ if (!str_list_add_no_dup_check(mem, type, _lv_type_names[LV_TYPE_CACHE]))
+ goto_bad;
+ }
+
+ return 1;
+bad:
+ return 0;
+}
+
+int lv_layout_and_type(struct dm_pool *mem, const struct logical_volume *lv,
+ struct dm_list **layout, struct dm_list **type) {
+ int linear, striped, unknown;
+ struct lv_segment *seg;
+
+ *layout = *type = NULL;
+
+ if (!(*layout = str_list_create(mem))) {
+ log_error("LV layout list allocation failed");
+ goto bad;
+ }
+
+ if (!(*type = str_list_create(mem))) {
+ log_error("LV type list allocation failed");
+ goto bad;
+ }
+
+ /* Mirrors and related */
+ if (lv_is_mirror_type(lv) && !lv_is_raid(lv) &&
+ !_lv_type_list_mirror(mem, lv, *layout, *type))
+ goto_bad;
+
+ /* RAIDs and related */
+ if (lv_is_raid_type(lv) &&
+ !_lv_type_list_raid(mem, lv, *layout, *type))
+ goto_bad;
+
+ /* Thins and related */
+ if ((lv_is_thin_type(lv) || lv_is_external_origin(lv)) &&
+ !_lv_type_list_thin(mem, lv, *layout, *type))
+ goto_bad;
+
+ /* Caches and related */
+ if (lv_is_cache_type(lv) &&
+ !_lv_type_list_cache(mem, lv, *layout, *type))
+ goto_bad;
+
+ if (lv_is_cache_origin(lv)) {
+ if (!str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_CACHE]) ||
+ !str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_ORIGIN]))
+ goto_bad;
+ }
+
+ /* Pool-specific */
+ if (lv_is_pool_metadata_spare(lv) &&
+ (!str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_POOL]) ||
+ !str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_METADATA]) ||
+ !str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_SPARE])))
+ goto_bad;
+
+ /* Old-style origins/snapshots, virtual origins */
+ if (lv_is_origin(lv)) {
+ str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_ORIGIN]);
+ if (lv_is_virtual(lv) &&
+ !str_list_add_no_dup_check(mem, *layout, _lv_type_names[LV_TYPE_VIRTUAL]))
+ goto_bad;
+ if (lv->origin_count > 1 &&
+ !str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_MULTIPLE]))
+ goto_bad;
+ } else if (lv_is_cow(lv)) {
+ if (!str_list_add_no_dup_check(mem, *type, _lv_type_names[LV_TYPE_SNAPSHOT]))
+ goto_bad;
+ }
+
+ /*
+ * If layout not yet determined, it must be either
+ * linear or striped or mixture of these two.
+ */
+ if (dm_list_empty(*layout)) {
+ linear = striped = unknown = 0;
+ dm_list_iterate_items(seg, &lv->segments) {
+ if (seg_is_linear(seg))
+ linear = 1;
+ else if (seg_is_striped(seg))
+ striped = 1;
+ else {
+ /*
+ * This should not happen but if it does
+ * we'll see that there's "unknown" layout
+ * present. This means we forgot to detect
+ * the type above and we need add proper
+ * detection for such type!
+ */
+ unknown = 1;
+ log_error(INTERNAL_ERROR "Failed to properly detect "
+ "layout and type for for LV %s/%s",
+ lv->vg->name, lv->name);
+ }
+ }
+
+ if (linear &&
+ !str_list_add_no_dup_check(mem, *layout, _lv_type_names[LV_TYPE_LINEAR]))
+ goto_bad;
+
+ if (striped &&
+ !str_list_add_no_dup_check(mem, *layout, _lv_type_names[LV_TYPE_STRIPED]))
+ goto_bad;
+
+ if (!linear && !striped &&
+ !str_list_add_no_dup_check(mem, *layout, _lv_type_names[LV_TYPE_UNKNOWN]))
+ goto_bad;
+ }
+
+ /*
+ * If type is not defined here yet, it means this is a pure top-level
+ * device that is not combined with any other type. So just copy what
+ * we have set for "layout" and use it for "type" too.
+ */
+ if (dm_list_empty(*type))
+ str_list_dup(mem, *type, *layout);
+
+ return 1;
+bad:
+ if (*type)
+ dm_pool_free(mem, *type);
+ if (*layout)
+ dm_pool_free(mem, *layout);
+ return 0;
}
static int _lv_is_on_pv(struct logical_volume *lv, void *data)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 497e59c..59d68d6 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -191,6 +191,9 @@
#define lv_is_pool_metadata(lv) (((lv)->status & (CACHE_POOL_METADATA | THIN_POOL_METADATA)) ? 1 : 0)
#define lv_is_pool_metadata_spare(lv) (((lv)->status & (POOL_METADATA_SPARE)) ? 1 : 0)
+int lv_layout_and_type(struct dm_pool *mem, const struct logical_volume *lv,
+ struct dm_list **layout, struct dm_list **type);
+
/* Ordered list - see lv_manip.c */
typedef enum {
AREA_UNASSIGNED,
@@ -911,17 +914,11 @@ struct lv_segment *last_seg(const struct logical_volume *lv);
const char *lv_type_name(const struct logical_volume *lv);
/*
- * Useful function to determine linear and striped volumes.
- */
-int lv_is_linear(const struct logical_volume *lv);
-int lv_is_striped(const struct logical_volume *lv);
-
-/*
* Useful functions for managing snapshots.
*/
int lv_is_origin(const struct logical_volume *lv);
int lv_is_virtual_origin(const struct logical_volume *lv);
-int lv_is_thin_origin(const struct logical_volume *lv);
+int lv_is_thin_origin(const struct logical_volume *lv, unsigned *snapshot_count);
int lv_is_cache_origin(const struct logical_volume *lv);
int lv_is_cow(const struct logical_volume *lv);
int lv_is_merging_origin(const struct logical_volume *origin);
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 7d86187..b4da500 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -500,18 +500,28 @@ const char *get_pool_discards_name(thin_discards_t discards)
return "unknown";
}
-int lv_is_thin_origin(const struct logical_volume *lv)
+int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snapshot_count)
{
struct seg_list *segl;
+ int r = 0;
+
+ if (snapshot_count)
+ *snapshot_count = 0;
if (!lv_is_thin_volume(lv) ||
dm_list_empty(&lv->segs_using_this_lv))
return 0;
dm_list_iterate_items(segl, &lv->segs_using_this_lv) {
- if (segl->seg->origin == lv)
- return 1;
+ if (segl->seg->origin == lv) {
+ r = 1;
+ if (snapshot_count)
+ (*snapshot_count)++;
+ else
+ /* not interested in number of snapshots */
+ break;
+ }
}
- return 0;
+ return r;
}
diff --git a/lib/report/columns.h b/lib/report/columns.h
index 1761a6d..d203f3d 100644
--- a/lib/report/columns.h
+++ b/lib/report/columns.h
@@ -39,7 +39,8 @@ FIELD(LVS, lv, STR, "Path", lvid, 4, lvpath, lv_path, "Full pathname for LV. Bla
FIELD(LVS, lv, STR, "DMPath", lvid, 6, lvdmpath, lv_dm_path, "Internal device-mapper pathname for LV (in /dev/mapper directory).", 0)
FIELD(LVS, lv, STR, "Parent", lvid, 6, lvparent, lv_parent, "For LVs that are components of another LV, the parent LV.", 0)
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, lv_attr, "Various attributes - see man page.", 0)
-//FIELD(LVS, lv, STR, "Type", lvid, 10, lvvolumetype, lv_volume_type, "LV volume type.", 0)
+FIELD(LVS, lv, STR_LIST, "Layout", lvid, 10, lvlayout, lv_layout, "LV layout.", 0)
+FIELD(LVS, lv, STR_LIST, "Type", lvid, 10, lvtype, lv_type, "LV type.", 0)
FIELD(LVS, lv, BIN, "InitImgSync", lvid, 10, lvinitialimagesync, lv_initial_image_sync, "Set if mirror/RAID images underwent initial resynchronization.", 0)
FIELD(LVS, lv, BIN, "ImgSynced", lvid, 10, lvimagesynced, lv_image_synced, "Set if mirror/RAID image is synchronized.", 0)
FIELD(LVS, lv, BIN, "Merging", lvid, 10, lvmerging, lv_merging, "Set if snapshot LV is being merged to origin.", 0)
@@ -49,7 +50,6 @@ FIELD(LVS, lv, BIN, "AllocLock", lvid, 10, lvallocationlocked, lv_allocation_loc
FIELD(LVS, lv, BIN, "FixMin", lvid, 10, lvfixedminor, lv_fixed_minor, "Set if LV has fixed minor number assigned.", 0)
FIELD(LVS, lv, BIN, "MergeFailed", lvid, 15, lvmergefailed, lv_merge_failed, "Set if snapshot merge failed.", 0)
FIELD(LVS, lv, BIN, "SnapInvalid", lvid, 15, lvsnapshotinvalid, lv_snapshot_invalid, "Set if snapshot LV is invalid.", 0)
-//FIELD(LVS, lv, STR, "TargetType", lvid, 10, lvtargettype, lv_target_type, "Kernel target type the LV is related to.", 0)
FIELD(LVS, lv, STR, "Health", lvid, 15, lvhealthstatus, lv_health_status, "LV health status.", 0)
FIELD(LVS, lv, BIN, "SkipAct", lvid, 15, lvskipactivation, lv_skip_activation, "Set if LV is skipped on activation.", 0)
FIELD(LVS, lv, STR, "Active", lvid, 6, lvactive, lv_active, "Active state of the LV.", 0)
@@ -148,7 +148,7 @@ FIELD(VGS, vg, SIZ, "VMdaFree", cmd, 9, vgmdafree, vg_mda_free, "Free metadata a
FIELD(VGS, vg, SIZ, "VMdaSize", cmd, 9, vgmdasize, vg_mda_size, "Size of smallest metadata area for this VG in current units.", 0)
FIELD(VGS, vg, NUM, "#VMdaCps", cmd, 8, vgmdacopies, vg_mda_copies, "Target number of in use metadata areas in the VG.", 1)
-FIELD(SEGS, seg, STR, "Type", list, 4, segtype, segtype, "Type of LV segment.", 0)
+FIELD(SEGS, seg, STR, "SegType", list, 4, segtype, segtype, "Type of LV segment.", 0)
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, stripes, "Number of stripes or mirror legs.", 0)
FIELD(SEGS, seg, SIZ, "Stripe", stripe_size, 6, size32, stripesize, "For stripes, amount of data placed on one device before switching to the next.", 0)
FIELD(SEGS, seg, SIZ, "Stripe", stripe_size, 6, size32, stripe_size, "For stripes, amount of data placed on one device before switching to the next.", 0)
diff --git a/lib/report/properties.c b/lib/report/properties.c
index 3be44f2..eac8c2c 100644
--- a/lib/report/properties.c
+++ b/lib/report/properties.c
@@ -179,8 +179,10 @@ GET_PV_NUM_PROPERTY_FN(pv_ba_size, SECTOR_SIZE * pv->ba_size)
#define _vg_clustered_set prop_not_implemented_set
#define _vg_clustered_get prop_not_implemented_get
-//#define _lv_volume_type_set prop_not_implemented_set
-//#define _lv_volume_type_get prop_not_implemented_get
+#define _lv_layout_set prop_not_implemented_set
+#define _lv_layout_get prop_not_implemented_get
+#define _lv_type_set prop_not_implemented_set
+#define _lv_type_get prop_not_implemented_get
#define _lv_initial_image_sync_set prop_not_implemented_set
#define _lv_initial_image_sync_get prop_not_implemented_get
#define _lv_image_synced_get prop_not_implemented_get
@@ -216,8 +218,6 @@ GET_PV_NUM_PROPERTY_FN(pv_ba_size, SECTOR_SIZE * pv->ba_size)
#define _lv_inactive_table_get prop_not_implemented_get
#define _lv_device_open_set prop_not_implemented_set
#define _lv_device_open_get prop_not_implemented_get
-//#define _lv_target_type_set prop_not_implemented_set
-//#define _lv_target_type_get prop_not_implemented_get
#define _lv_health_status_set prop_not_implemented_set
#define _lv_health_status_get prop_not_implemented_get
#define _lv_skip_activation_set prop_not_implemented_set
diff --git a/lib/report/report.c b/lib/report/report.c
index 842a1a5..69151e0 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -1318,15 +1318,37 @@ static int _vgclustered_disp(struct dm_report *rh, struct dm_pool *mem,
return _binary_disp(rh, mem, field, clustered, FIRST_NAME(vg_clustered_y), private);
}
-/* FIXME Replace with something that provides a complete unique description for every combination.
-static int _lvvolumetype_disp(struct dm_report *rh, struct dm_pool *mem,
+static int _lvlayout_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
+{
+ const struct logical_volume *lv = (const struct logical_volume *) data;
+ struct dm_list *lv_layout;
+ struct dm_list *lv_type;
+
+ if (!lv_layout_and_type(mem, lv, &lv_layout, &lv_type)) {
+ log_error("Failed to display layout for LV %s/%s.", lv->vg->name, lv->name);
+ return 0;
+ }
+
+ return _field_set_string_list(rh, field, lv_layout, private);
+}
+
+static int _lvtype_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
- const char *type = lv_type_name((const struct logical_volume *) data);
- return _string_disp(rh, mem, field, &type, private);
+ const struct logical_volume *lv = (const struct logical_volume *) data;
+ struct dm_list *lv_layout;
+ struct dm_list *lv_type;
+
+ if (!lv_layout_and_type(mem, lv, &lv_layout, &lv_type)) {
+ log_error("Failed to display type for LV %s/%s.", lv->vg->name, lv->name);
+ return 0;
+ }
+
+ return _field_set_string_list(rh, field, lv_type, private);
}
-*/
static int _lvinitialimagesync_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
@@ -1605,35 +1627,6 @@ static int _lvdeviceopen_disp(struct dm_report *rh, struct dm_pool *mem,
return _binary_undef_disp(rh, mem, field, private);
}
-/* FIXME Replace with something that provides a complete unique description for every combination.
-static int _lvtargettype_disp(struct dm_report *rh, struct dm_pool *mem,
- struct dm_report_field *field,
- const void *data, void *private)
-{
- const struct logical_volume *lv = (const struct logical_volume *) data;
- const char *target_type = "unknown";
-
- if (lv_is_thin_pool(lv) || lv_is_thin_volume(lv))
- target_type = "thin";
- else if (lv_is_cache_type(lv))
- target_type = "cache";
- else if (lv_is_raid_type(lv))
- target_type = "raid";
- else if (lv_is_mirror_type(lv))
- target_type = "mirror";
- else if (lv_is_cow(lv) || lv_is_origin(lv))
- target_type = "snapshot";
- else if (lv_is_virtual(lv))
- target_type = "virtual";
- else if (lv_is_linear(lv))
- target_type = "linear";
- else if (lv_is_striped(lv))
- target_type = "striped";
-
- return _string_disp(rh, mem, field, &target_type, private);
-}
-*/
-
static int _thinzero_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
9 years, 8 months
master - libdm: Add DM_DEFERRED_REMOVE to dm-ioctl.h.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8a7682cbc98200...
Commit: 8a7682cbc982004e880a740d61ca5d12f0caf769
Parent: 8740ecfa6492d149637a2f23d3bd7328863f0a78
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Fri Aug 15 13:45:55 2014 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Fri Aug 15 13:45:55 2014 +0100
libdm: Add DM_DEFERRED_REMOVE to dm-ioctl.h.
---
WHATS_NEW_DM | 1 +
libdm/misc/dm-ioctl.h | 17 ++++++++++++++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index cf74aca..41aa89d 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.89 -
=================================
+ Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
Add support for selection to match string list subset, recognize { } operator.
Fix string list selection with '[value]' to not match list that's superset.
Fix string list selection to match whole words only, not prefixes.
diff --git a/libdm/misc/dm-ioctl.h b/libdm/misc/dm-ioctl.h
index 76316b0..01a2b9e 100644
--- a/libdm/misc/dm-ioctl.h
+++ b/libdm/misc/dm-ioctl.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
- * Copyright (C) 2004 - 2013 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004 - 2014 Red Hat, Inc. All rights reserved.
*
* This file is released under the LGPL.
*/
@@ -269,9 +269,9 @@ enum {
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 24
+#define DM_VERSION_MINOR 27
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2013-01-15)"
+#define DM_VERSION_EXTRA "-ioctl (2013-10-30)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -343,4 +343,15 @@ enum {
*/
#define DM_DATA_OUT_FLAG (1 << 16) /* Out */
+/*
+ * If set with DM_DEV_REMOVE or DM_REMOVE_ALL this indicates that if
+ * the device cannot be removed immediately because it is still in use
+ * it should instead be scheduled for removal when it gets closed.
+ *
+ * On return from DM_DEV_REMOVE, DM_DEV_STATUS or other ioctls, this
+ * flag indicates that the device is scheduled to be removed when it
+ * gets closed.
+ */
+#define DM_DEFERRED_REMOVE (1 << 17) /* In/Out */
+
#endif /* _LINUX_DM_IOCTL_H */
9 years, 8 months
master - WHATS_NEW: previous commit
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8740ecfa6492d1...
Commit: 8740ecfa6492d149637a2f23d3bd7328863f0a78
Parent: 1cd622d98ba837886fb70d33b1eda920b14ae405
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Aug 15 13:31:11 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Aug 15 13:31:21 2014 +0200
WHATS_NEW: previous commit
---
WHATS_NEW | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 0ca0485..f6a877d 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.110 -
==================================
+ Properly display lvs lv_attr volume type and target type bit for cache origin.
Fix pvcreate_check() to update cache correctly after signature wiping.
Fix primary device lookup failure for partition when processing mpath filter.
If LV inactive and non-clustered, do not issue "Cannot deactivate" on -aln.
9 years, 8 months
master - report: lvs: properly display 'o' for volume type bit and 'C' for target type bit in lv_attr field for cache origin LVs
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1cd622d98ba837...
Commit: 1cd622d98ba837886fb70d33b1eda920b14ae405
Parent: 8eba33510f95572316a743d6b68d5c7c31743672
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Aug 15 13:21:29 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Aug 15 13:28:43 2014 +0200
report: lvs: properly display 'o' for volume type bit and 'C' for target type bit in lv_attr field for cache origin LVs
Before this patch:
LV VG Attr
[cache_orig_corig] vg -wi-ao----
With this patch applied:
LV VG Attr
[cache_orig_corig] vg owi-aoC---
---
lib/metadata/lv.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 9539369..0fbdfff 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -673,6 +673,8 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[0] = 'l';
else if (lv_is_cow(lv))
repstr[0] = (lv_is_merging_cow(lv)) ? 'S' : 's';
+ else if (lv_is_cache_origin(lv))
+ repstr[0] = 'o';
else
repstr[0] = '-';
@@ -737,7 +739,7 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (lv_is_thin_pool(lv) || lv_is_thin_volume(lv))
repstr[6] = 't';
- else if (lv_is_cache_pool(lv) || lv_is_cache(lv))
+ else if (lv_is_cache_pool(lv) || lv_is_cache(lv) || lv_is_cache_origin(lv))
repstr[6] = 'C';
else if (lv_is_raid_type(lv))
repstr[6] = 'r';
9 years, 8 months
master - cache+thin: add lv_is_{cache, thin}_origin fn to identify origin LVs
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8eba33510f9557...
Commit: 8eba33510f95572316a743d6b68d5c7c31743672
Parent: ec0d2f7aa4da4e433e26bc252626eae6febbe4d6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Aug 15 13:08:30 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Aug 15 13:28:43 2014 +0200
cache+thin: add lv_is_{cache,thin}_origin fn to identify origin LVs
---
lib/metadata/cache_manip.c | 13 +++++++++++++
lib/metadata/metadata-exported.h | 2 ++
lib/metadata/thin_manip.c | 16 ++++++++++++++++
3 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 184df79..f617f4e 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -314,3 +314,16 @@ int get_cache_mode(const char *str, uint32_t *flags)
return 1;
}
+
+int lv_is_cache_origin(const struct logical_volume *lv)
+{
+ struct lv_segment *seg;
+
+ /* Make sure there's exactly one segment in segs_using_this_lv! */
+ if (dm_list_empty(&lv->segs_using_this_lv) ||
+ (dm_list_size(&lv->segs_using_this_lv) > 1))
+ return 0;
+
+ seg = get_only_segment_using_this_lv(lv);
+ return seg && lv_is_cache(seg->lv) && (seg_lv(seg, 0) == lv);
+}
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index fa96a1a..497e59c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -921,6 +921,8 @@ int lv_is_striped(const struct logical_volume *lv);
*/
int lv_is_origin(const struct logical_volume *lv);
int lv_is_virtual_origin(const struct logical_volume *lv);
+int lv_is_thin_origin(const struct logical_volume *lv);
+int lv_is_cache_origin(const struct logical_volume *lv);
int lv_is_cow(const struct logical_volume *lv);
int lv_is_merging_origin(const struct logical_volume *origin);
int lv_is_merging_cow(const struct logical_volume *snapshot);
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 07246f7..7d86187 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -499,3 +499,19 @@ const char *get_pool_discards_name(thin_discards_t discards)
return "unknown";
}
+
+int lv_is_thin_origin(const struct logical_volume *lv)
+{
+ struct seg_list *segl;
+
+ if (!lv_is_thin_volume(lv) ||
+ dm_list_empty(&lv->segs_using_this_lv))
+ return 0;
+
+ dm_list_iterate_items(segl, &lv->segs_using_this_lv) {
+ if (segl->seg->origin == lv)
+ return 1;
+ }
+
+ return 0;
+}
9 years, 8 months
master - refactor: add defines for raid segtypes
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ec0d2f7aa4da4e...
Commit: ec0d2f7aa4da4e433e26bc252626eae6febbe4d6
Parent: bf78e55ef311b0bea7993c5405d637e46a1b8394
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Aug 15 13:03:21 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Aug 15 13:28:43 2014 +0200
refactor: add defines for raid segtypes
This will be reused later on in upcoming code...
---
lib/metadata/segtype.h | 13 +++++++++++++
lib/raid/raid.c | 24 ++++++++++++------------
2 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 891c378..080cf4e 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -150,6 +150,19 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
#endif
+#define SEG_TYPE_NAME_RAID1 "raid1"
+#define SEG_TYPE_NAME_RAID10 "raid10"
+#define SEG_TYPE_NAME_RAID4 "raid4"
+#define SEG_TYPE_NAME_RAID5 "raid5"
+#define SEG_TYPE_NAME_RAID5_LA "raid5_la"
+#define SEG_TYPE_NAME_RAID5_LS "raid5_ls"
+#define SEG_TYPE_NAME_RAID5_RA "raid5_ra"
+#define SEG_TYPE_NAME_RAID5_RS "raid5_rs"
+#define SEG_TYPE_NAME_RAID6 "raid6"
+#define SEG_TYPE_NAME_RAID6_NC "raid6_nc"
+#define SEG_TYPE_NAME_RAID6_NR "raid6_nr"
+#define SEG_TYPE_NAME_RAID6_ZR "raid6_zr"
+
#ifdef REPLICATOR_INTERNAL
int init_replicator_segtype(struct cmd_context *cmd, struct segtype_library *seglib);
#endif
diff --git a/lib/raid/raid.c b/lib/raid/raid.c
index c3f5c3f..5aad447 100644
--- a/lib/raid/raid.c
+++ b/lib/raid/raid.c
@@ -443,18 +443,18 @@ static const struct raid_type {
unsigned parity;
int extra_flags;
} _raid_types[] = {
- { "raid1", 0, SEG_AREAS_MIRRORED },
- { "raid10", 0, SEG_AREAS_MIRRORED },
- { "raid4", 1 },
- { "raid5", 1 },
- { "raid5_la", 1 },
- { "raid5_ls", 1 },
- { "raid5_ra", 1 },
- { "raid5_rs", 1 },
- { "raid6", 2 },
- { "raid6_nc", 2 },
- { "raid6_nr", 2 },
- { "raid6_zr", 2 }
+ { SEG_TYPE_NAME_RAID1, 0, SEG_AREAS_MIRRORED },
+ { SEG_TYPE_NAME_RAID10, 0, SEG_AREAS_MIRRORED },
+ { SEG_TYPE_NAME_RAID4, 1 },
+ { SEG_TYPE_NAME_RAID5, 1 },
+ { SEG_TYPE_NAME_RAID5_LA, 1 },
+ { SEG_TYPE_NAME_RAID5_LS, 1 },
+ { SEG_TYPE_NAME_RAID5_RA, 1 },
+ { SEG_TYPE_NAME_RAID5_RS, 1 },
+ { SEG_TYPE_NAME_RAID6, 2 },
+ { SEG_TYPE_NAME_RAID6_NC, 2 },
+ { SEG_TYPE_NAME_RAID6_NR, 2 },
+ { SEG_TYPE_NAME_RAID6_ZR, 2 }
};
static struct segment_type *_init_raid_segtype(struct cmd_context *cmd,
9 years, 8 months
master - pvcreate: Fix cache state with filters/sig wiping.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=bf78e55ef311b0...
Commit: bf78e55ef311b0bea7993c5405d637e46a1b8394
Parent: 20503ff0675616823bcc9aa67f3e6d14a4172277
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Thu Aug 14 01:30:01 2014 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Thu Aug 14 01:30:01 2014 +0100
pvcreate: Fix cache state with filters/sig wiping.
_pvcreate_check() has two missing requirements:
After refreshing filters there must be a rescan.
(Otherwise the persistent filter may remain empty.)
After wiping a signature, the filters must be refreshed.
(A device that was previously excluded by the filter due to
its signature might now need to be included.)
If several devices are added at once, the repeated scanning isn't
strictly needed, but we can address that later as part of the command
processing restructuring (by grouping the devices).
Replace the new pvcreate code added by commit
54685c20fc9dfb155a2e5bc9d8cf5f0aad944305 "filters: fix regression caused
by commit e80884cd080cad7e10be4588e3493b9000649426"
with this change to _pvcreate_check().
The filter refresh problem dates back to commit
acb4b5e4de3c49d36fe756f6fb9997ec179b89c2 "Fix pvcreate device check."
---
WHATS_NEW | 1 +
lib/metadata/metadata.c | 48 ++++++++++++++++++++++++++++------------------
tools/pvcreate.c | 9 --------
3 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 28f7e36..0ca0485 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.110 -
==================================
+ Fix pvcreate_check() to update cache correctly after signature wiping.
Fix primary device lookup failure for partition when processing mpath filter.
If LV inactive and non-clustered, do not issue "Cannot deactivate" on -aln.
Remove spurious "Skipping mirror LV" message on pvmove of clustered mirror.
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 6f88fd8..d483225 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1329,11 +1329,14 @@ int vg_split_mdas(struct cmd_context *cmd __attribute__((unused)),
* See if we may pvcreate on this device.
* 0 indicates we may not.
*/
-static int pvcreate_check(struct cmd_context *cmd, const char *name,
- struct pvcreate_params *pp)
+static int _pvcreate_check(struct cmd_context *cmd, const char *name,
+ struct pvcreate_params *pp)
{
struct physical_volume *pv;
struct device *dev;
+ int r = 0;
+ int scan_needed = 0;
+ int filter_refresh_needed = 0;
/* FIXME Check partition type is LVM unless --force is given */
@@ -1345,7 +1348,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
if (pv && !is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) {
log_error("Can't initialize physical volume \"%s\" of "
"volume group \"%s\" without -ff", name, pv_vg_name(pv));
- goto bad;
+ goto out;
}
/* prompt */
@@ -1353,28 +1356,29 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
yes_no_prompt("Really INITIALIZE physical volume \"%s\" of volume group \"%s\" [y/n]? ",
name, pv_vg_name(pv)) == 'n') {
log_error("%s: physical volume not initialized", name);
- goto bad;
+ goto out;
}
if (sigint_caught())
- goto_bad;
+ goto_out;
dev = dev_cache_get(name, cmd->filter);
/* Is there an md superblock here? */
- /* FIXME: still possible issues here - rescan cache? */
if (!dev && md_filtering()) {
if (!refresh_filters(cmd))
- goto_bad;
+ goto_out;
init_md_filtering(0);
dev = dev_cache_get(name, cmd->filter);
init_md_filtering(1);
+
+ scan_needed = 1;
}
if (!dev) {
log_error("Device %s not found (or ignored by filtering).", name);
- goto bad;
+ goto out;
}
/*
@@ -1384,33 +1388,39 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name,
/* FIXME Detect whether device-mapper itself is still using it */
log_error("Can't open %s exclusively. Mounted filesystem?",
name);
- goto bad;
+ goto out;
}
if (!wipe_known_signatures(cmd, dev, name,
TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
0, pp->yes, pp->force)) {
log_error("Aborting pvcreate on %s.", name);
- goto bad;
- }
+ goto out;
+ } else
+ filter_refresh_needed = scan_needed = 1;
+
if (sigint_caught())
- goto_bad;
+ goto_out;
- if (pv && !is_orphan(pv) && pp->force) {
+ if (pv && !is_orphan(pv) && pp->force)
log_warn("WARNING: Forcing physical volume creation on "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
pv_vg_name(pv),
!is_orphan(pv) ? "\"" : "");
- }
- free_pv_fid(pv);
- return 1;
+ r = 1;
+
+out:
+ if (filter_refresh_needed)
+ refresh_filters(cmd);
+
+ if (scan_needed)
+ lvmcache_label_scan(cmd, 2);
-bad:
free_pv_fid(pv);
- return 0;
+ return r;
}
void pvcreate_params_set_defaults(struct pvcreate_params *pp)
@@ -1542,7 +1552,7 @@ struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_nam
}
}
- if (!pvcreate_check(cmd, pv_name, pp))
+ if (!_pvcreate_check(cmd, pv_name, pp))
goto_bad;
if (sigint_caught())
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index 67ecd41..958e353 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -105,15 +105,6 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- /*
- * Make sure we don't overwrite any existing signature
- * that may have been created after last time we did filtering.
- */
- if (!(refresh_filters(cmd))) {
- log_error("Failed to refresh filters before pvcreate.");
- return ECMD_FAILED;
- }
-
for (i = 0; i < argc; i++) {
if (sigint_caught())
return_ECMD_FAILED;
9 years, 8 months
master - tests: update report-select test for latest changes
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=20503ff0675616...
Commit: 20503ff0675616823bcc9aa67f3e6d14a4172277
Parent: fa793bed64a728185a9f8aa6196f0d411f89daf5
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Aug 13 17:19:58 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Aug 13 17:20:09 2014 +0200
tests: update report-select test for latest changes
---
test/shell/report-select.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/shell/report-select.sh b/test/shell/report-select.sh
index cdd45ed..fb12bd6 100644
--- a/test/shell/report-select.sh
+++ b/test/shell/report-select.sh
@@ -106,7 +106,7 @@ lvs_sel "lv_name='vol1'" "vol1"
###############################
# STRING LIST FIELD SELECTION #
###############################
-pvs_sel 'tags=["pv_tag1"]' "$dev1 $dev2"
+pvs_sel 'tags=["pv_tag1"]' ""
# for one item, no need to use []
pvs_sel 'tags="pv_tag1"' "$dev1 $dev2"
# no match
@@ -115,7 +115,7 @@ pvs_sel 'tags=["pv_tag1" && "pv_tag2" && "pv_tag3"]' "$dev1"
# check the order has no effect on selection result
pvs_sel 'tags=["pv_tag3" && "pv_tag2" && "pv_tag1"]' "$dev1"
pvs_sel 'tags=["pv_tag4" || "pv_tag3"]' "$dev1 $dev6"
-pvs_sel 'tags!=["pv_tag1"]' "$dev2 $dev3 $dev4 $dev5"
+pvs_sel 'tags!=["pv_tag1"]' "$dev1 $dev2 $dev3 $dev4 $dev5 $dev6"
# check mixture of && and || - this is not allowed
not pvs_sel 'tags=["pv_tag1" && "pv_tag2" || "pv_tag3"]'
9 years, 8 months
master - select: add support for selection to match string list subset, recognize { } operator
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fa793bed64a728...
Commit: fa793bed64a728185a9f8aa6196f0d411f89daf5
Parent: 6dd98c1fa89abb8ee9b91504a73d3a1c3f10e6d4
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Aug 13 15:39:03 2014 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Aug 13 16:10:12 2014 +0200
select: add support for selection to match string list subset, recognize { } operator
Using "[ ]" operator together with "&&" (or ",") inside causes the
string list to be matched if and only if all the items given match
the value reported and the number of items also match. This is
strict list matching and the original behaviour we already have.
In contrast to that, the new "{ }" operator together with "&&" inside
causes the string list to be matched if and only if all the items given
match the value reported but the number of items don't need to match.
So we can provide a subset in selection criteria and if the subset
is found, it matches.
For example:
$ lvs -o name,tags
LV LV Tags
lvol0 a
lvol1 a,b
lvol2 b,c,x
lvol3 a,b,y
$ lvs -o name,tags -S 'tags=[a,b]'
LV LV Tags
lvol1 a,b
$ lvs -o name,tags -S 'tags={a,b}'
LV LV Tags
lvol1 a,b
lvol3 a,b,y
So in the example above the a,b is subset of a,b,y and therefore
it also matches.
Clearly, when using "||" (or "#") inside, the { } and [ ] is the
same:
$ lvs -o name,tags -S 'tags=[a#b]'
LV LV Tags
lvol0 a
lvol1 a,b
lvol2 b,c,x
lvol3 a,b,y
$ lvs -o name,tags -S 'tags={a#b}'
LV LV Tags
lvol0 a
lvol1 a,b
lvol2 b,c,x
lvol3 a,b,y
Also in addition to the above feature, fix list with single value
matching when using [ ]:
Before this patch:
$ lvs -o name,tags -S 'tags=[a]'
LV LV Tags
lvol0 a
lvol1 a,b
lvol3 a,b,y
With this patch applied:
$ lvs -o name,tags -S 'tags=[a]'
LV LV Tags
lvol0 a
In case neither [] or {} is used, assume {} (the behaviour is not
changed here):
$ lvs -o name,tags -S 'tags=a'
LV LV Tags
lvol0 a
lvol1 a,b
lvol3 a,b,y
So in new terms 'tags=a' is equal to 'tags={a}'.
---
WHATS_NEW_DM | 2 +
libdm/libdm-report.c | 109 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 92 insertions(+), 19 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 7bb3f4c..cf74aca 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,7 @@
Version 1.02.89 -
=================================
+ Add support for selection to match string list subset, recognize { } operator.
+ Fix string list selection with '[value]' to not match list that's superset.
Fix string list selection to match whole words only, not prefixes.
Version 1.02.88 - 5th August 2014
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 620283c..9363a92 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -131,6 +131,8 @@ static struct op_def _op_cmp[] = {
#define SEL_LIST_MASK 0x000F0000
#define SEL_LIST_LS 0x00010000
#define SEL_LIST_LE 0x00020000
+#define SEL_LIST_SUBSET_LS 0x00040000
+#define SEL_LIST_SUBSET_LE 0x00080000
static struct op_def _op_log[] = {
{ "&&", SEL_AND, "All fields must match" },
@@ -142,6 +144,8 @@ static struct op_def _op_log[] = {
{ ")", SEL_PRECEDENCE_PE, "Right parenthesis" },
{ "[", SEL_LIST_LS, "List start" },
{ "]", SEL_LIST_LE, "List end"},
+ { "{", SEL_LIST_SUBSET_LS, "List subset start"},
+ { "}", SEL_LIST_SUBSET_LE, "List subset end"},
{ NULL, 0, NULL},
};
@@ -1247,9 +1251,9 @@ static int _cmp_field_string(const char *field_id, const char *a, const char *b,
return 0;
}
-/* Matches if all items from selection string list match. */
-static int _cmp_field_string_list_all(const struct str_list_sort_value *val,
- const struct selection_str_list *sel)
+/* Matches if all items from selection string list match list value strictly 1:1. */
+static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *val,
+ const struct selection_str_list *sel)
{
struct dm_str_list *sel_item;
unsigned int i = 1;
@@ -1269,7 +1273,36 @@ static int _cmp_field_string_list_all(const struct str_list_sort_value *val,
return 1;
}
-/* Matches if any item from selection string list matches. */
+/* Matches if all items from selection string list match a subset of list value. */
+static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *val,
+ const struct selection_str_list *sel)
+{
+ struct dm_str_list *sel_item;
+ unsigned int i = 1, 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))
+ return 0;
+
+ /* 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++) {
+ if ((strlen(sel_item->str) == val->items[i].len) &&
+ !strncmp(sel_item->str, val->value + val->items[i].pos, val->items[i].len)) {
+ last_found = i;
+ r = 1;
+ }
+ }
+ if (!r)
+ break;
+ }
+
+ return r;
+}
+
+/* Matches if any item from selection string list matches list value. */
static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
@@ -1299,11 +1332,24 @@ static int _cmp_field_string_list(const char *field_id,
const struct str_list_sort_value *value,
const struct selection_str_list *selection, uint32_t flags)
{
- int r;
+ int subset, r;
+
+ switch (selection->type & SEL_LIST_MASK) {
+ case SEL_LIST_LS:
+ subset = 0;
+ break;
+ case SEL_LIST_SUBSET_LS:
+ subset = 1;
+ break;
+ default:
+ log_error(INTERNAL_ERROR "_cmp_field_string_list: unknown list type");
+ return 0;
+ }
switch (selection->type & SEL_MASK) {
case SEL_AND:
- r = _cmp_field_string_list_all(value, selection);
+ r = subset ? _cmp_field_string_list_subset_all(value, selection)
+ : _cmp_field_string_list_strict_all(value, selection);
break;
case SEL_OR:
r = _cmp_field_string_list_any(value, selection);
@@ -1932,11 +1978,11 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
struct selection_str_list *ssl = NULL;
struct dm_str_list *item;
const char *begin_item, *end_item, *tmp;
- uint32_t end_op_flags, end_op_flag_hit = 0;
+ uint32_t op_flags, end_op_flag_expected, end_op_flag_hit = 0;
struct dm_str_list **arr;
size_t list_size;
unsigned int i;
- int list_end;
+ int list_end = 0;
char c;
if (!(ssl = dm_pool_alloc(mem, sizeof(*ssl))) ||
@@ -1948,8 +1994,8 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
ssl->type = 0;
*begin = s;
- if (!_tok_op_log(s, &tmp, SEL_LIST_LS)) {
- /* Only one item - SEL_LIST_LS and SEL_LIST_LE not used */
+ if (!(op_flags = _tok_op_log(s, &tmp, SEL_LIST_LS | SEL_LIST_SUBSET_LS))) {
+ /* Only one item - SEL_LIST_{SUBSET_}LS and SEL_LIST_{SUBSET_}LE not used */
c = _get_and_skip_quote_char(&s);
if (!(s = _tok_value_string(s, &begin_item, &end_item, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
log_error(_str_list_item_parsing_failed, ft->id);
@@ -1957,32 +2003,47 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
}
if (!_add_item_to_string_list(mem, begin_item, end_item, ssl->list))
goto_bad;
- ssl->type = SEL_OR;
+ ssl->type = SEL_OR | SEL_LIST_LS;
goto out;
}
- /* More than one item - items enclosed in SEL_LIST_LS and SEL_LIST_LE.
+ /* More than one item - items enclosed in SEL_LIST_LS and SEL_LIST_LE
+ * or SEL_LIST_SUBSET_LS and SEL_LIST_SUBSET_LE.
* Each element is terminated by AND or OR operator or 'list end'.
* The first operator hit is then the one allowed for the whole list,
* no mixing allowed!
*/
- end_op_flags = SEL_LIST_LE | SEL_AND | SEL_OR;
+
+ /* Are we using [] or {} for the list? */
+ end_op_flag_expected = (op_flags == SEL_LIST_LS) ? SEL_LIST_LE : SEL_LIST_SUBSET_LE;
+
+ op_flags = SEL_LIST_LE | SEL_LIST_SUBSET_LE | SEL_AND | SEL_OR;
s++;
while (*s) {
s = _skip_space(s);
c = _get_and_skip_quote_char(&s);
- if (!(s = _tok_value_string(s, &begin_item, &end_item, c, end_op_flags, NULL))) {
+ if (!(s = _tok_value_string(s, &begin_item, &end_item, c, op_flags, NULL))) {
log_error(_str_list_item_parsing_failed, ft->id);
goto bad;
}
s = _skip_space(s);
- if (!(end_op_flag_hit = _tok_op_log(s, &tmp, end_op_flags))) {
+ if (!(end_op_flag_hit = _tok_op_log(s, &tmp, op_flags))) {
log_error("Invalid operator in selection list.");
goto bad;
}
- list_end = end_op_flag_hit == SEL_LIST_LE;
+ if (end_op_flag_hit & (SEL_LIST_LE | SEL_LIST_SUBSET_LE)) {
+ list_end = 1;
+ if (end_op_flag_hit != end_op_flag_expected) {
+ for (i = 0; _op_log[i].string; i++)
+ if (_op_log[i].flags == end_op_flag_expected)
+ break;
+ log_error("List ended with incorrect character, "
+ "expecting \'%s\'.", _op_log[i].string);
+ goto bad;
+ }
+ }
if (ssl->type) {
if (!list_end && !(ssl->type & end_op_flag_hit)) {
@@ -1990,8 +2051,12 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
"in selection list at a time.");
goto bad;
}
- } else
- ssl->type = list_end ? SEL_OR : end_op_flag_hit;
+ } else {
+ if (list_end)
+ ssl->type = end_op_flag_expected == SEL_LIST_LE ? SEL_AND : SEL_OR;
+ else
+ ssl->type = end_op_flag_hit;
+ }
if (!_add_item_to_string_list(mem, begin_item, end_item, ssl->list))
goto_bad;
@@ -2002,11 +2067,17 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
break;
}
- if (end_op_flag_hit != SEL_LIST_LE) {
+ if (!(end_op_flag_hit & (SEL_LIST_LE | SEL_LIST_SUBSET_LE))) {
log_error("Missing list end for selection field %s", ft->id);
goto bad;
}
+ /* Store information whether [] or {} was used. */
+ if ((end_op_flag_expected == SEL_LIST_LE))
+ ssl->type |= SEL_LIST_LS;
+ else
+ ssl->type |= SEL_LIST_SUBSET_LS;
+
/* Sort the list. */
if (!(list_size = dm_list_size(ssl->list))) {
log_error(INTERNAL_ERROR "_tok_value_string_list: list has no items");
9 years, 8 months