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:
parent
8a7682cbc9
commit
e8bbcda2a3
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
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,
|
||||
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 lv_type_t _get_lv_type(const struct logical_volume *lv)
|
||||
static const char *_lv_type_names[] = {
|
||||
[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",
|
||||
};
|
||||
|
||||
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;
|
||||
dm_list_iterate_items(seg, &lv->segments) {
|
||||
if (!seg_is_linear(seg)) {
|
||||
type = LV_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(*layout = str_list_create(mem))) {
|
||||
log_error("LV layout list allocation failed");
|
||||
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 (!(*type = str_list_create(mem))) {
|
||||
log_error("LV type list allocation failed");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
/* Mirrors and related */
|
||||
if (lv_is_mirror_type(lv) && !lv_is_raid(lv) &&
|
||||
!_lv_type_list_mirror(mem, lv, *layout, *type))
|
||||
goto_bad;
|
||||
|
||||
const char *lv_type_name(const struct logical_volume *lv) {
|
||||
lv_type_t type = _get_lv_type(lv);
|
||||
return _lv_type_names[type];
|
||||
}
|
||||
/* RAIDs and related */
|
||||
if (lv_is_raid_type(lv) &&
|
||||
!_lv_type_list_raid(mem, lv, *layout, *type))
|
||||
goto_bad;
|
||||
|
||||
int lv_is_linear(const struct logical_volume *lv)
|
||||
{
|
||||
lv_type_t type = _get_lv_type(lv);
|
||||
return type == LV_TYPE_LINEAR;
|
||||
}
|
||||
/* Thins and related */
|
||||
if ((lv_is_thin_type(lv) || lv_is_external_origin(lv)) &&
|
||||
!_lv_type_list_thin(mem, lv, *layout, *type))
|
||||
goto_bad;
|
||||
|
||||
int lv_is_striped(const struct logical_volume *lv)
|
||||
{
|
||||
lv_type_t type = _get_lv_type(lv);
|
||||
return type == LV_TYPE_STRIPED;
|
||||
/* 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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user