1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

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...
This commit is contained in:
Peter Rajnoha 2014-08-13 10:03:45 +02:00
parent 8a7682cbc9
commit e8bbcda2a3
9 changed files with 441 additions and 182 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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_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_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_STRIPED,
LV_TYPE_MIRROR,
LV_TYPE_RAID,
LV_TYPE_THIN,
LV_TYPE_CACHE,
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_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_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;
return " ";
}
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 (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 1;
bad:
return 0;
}
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;
}
static int _lv_type_list_thin(struct dm_pool *mem,
const struct logical_volume *lv,
struct dm_list *layout,
struct dm_list *type)
{
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;
}
static int _lv_type_list_cache(struct dm_pool *mem,
const struct logical_volume *lv,
struct dm_list *layout,
struct dm_list *type)
{
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;
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;
*layout = *type = NULL;
/* none of the above, check linear... */
if (type == LV_TYPE_UNKNOWN) {
type = LV_TYPE_LINEAR;
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)) {
type = LV_TYPE_UNKNOWN;
break;
}
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 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 (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;
}
return type;
}
/*
* 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);
const char *lv_type_name(const struct logical_volume *lv) {
lv_type_t type = _get_lv_type(lv);
return _lv_type_names[type];
}
int lv_is_linear(const struct logical_volume *lv)
{
lv_type_t type = _get_lv_type(lv);
return type == LV_TYPE_LINEAR;
}
int lv_is_striped(const struct logical_volume *lv)
{
lv_type_t type = _get_lv_type(lv);
return type == LV_TYPE_STRIPED;
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)

View File

@ -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,
@ -910,18 +913,12 @@ struct lv_segment *last_seg(const struct logical_volume *lv);
/* Human-readable LV type name. */
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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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 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 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 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)