mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
report: select: add support for percent selection
This commit is contained in:
parent
cfed0d09e8
commit
51a86dc2f8
@ -123,7 +123,8 @@ static int _ ## NAME ## _get (const void *obj, struct lvm_property_type *prop) \
|
||||
#define STR 1
|
||||
#define NUM 2
|
||||
#define SIZ 3
|
||||
#define STR_LIST 4
|
||||
#define PCT 4
|
||||
#define STR_LIST 5
|
||||
|
||||
#define FIELD_MODIFIABLE 0x00000001
|
||||
#define FIELD(type, strct, field_type, head, field, width, fn, id, desc, settable) \
|
||||
|
@ -44,11 +44,11 @@ FIELD(LVS, lv, SIZ, "MSize", lvid, 6, lvmetadatasize, lv_metadata_size, "For thi
|
||||
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, seg_count, "Number of segments in LV.", 0)
|
||||
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, origin, "For snapshots, the origin device of this LV.", 0)
|
||||
FIELD(LVS, lv, SIZ, "OSize", lvid, 5, originsize, origin_size, "For snapshots, the size of the origin device of this LV.", 0)
|
||||
FIELD(LVS, lv, NUM, "Data%", lvid, 6, datapercent, data_percent, "For snapshot and thin pools and volumes, the percentage full if LV is active.", 0)
|
||||
FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, snap_percent, "For snapshots, the percentage full if LV is active.", 0)
|
||||
FIELD(LVS, lv, NUM, "Meta%", lvid, 6, metadatapercent, metadata_percent, "For thin pools, the percentage of metadata full if LV is active.", 0)
|
||||
FIELD(LVS, lv, NUM, "Cpy%Sync", lvid, 8, copypercent, copy_percent, "For RAID, mirrors and pvmove, current percentage in-sync.", 0)
|
||||
FIELD(LVS, lv, NUM, "Cpy%Sync", lvid, 8, copypercent, sync_percent, "For RAID, mirrors and pvmove, current percentage in-sync.", 0)
|
||||
FIELD(LVS, lv, PCT, "Data%", lvid, 6, datapercent, data_percent, "For snapshot and thin pools and volumes, the percentage full if LV is active.", 0)
|
||||
FIELD(LVS, lv, PCT, "Snap%", lvid, 6, snpercent, snap_percent, "For snapshots, the percentage full if LV is active.", 0)
|
||||
FIELD(LVS, lv, PCT, "Meta%", lvid, 6, metadatapercent, metadata_percent, "For thin pools, the percentage of metadata full if LV is active.", 0)
|
||||
FIELD(LVS, lv, PCT, "Cpy%Sync", lvid, 8, copypercent, copy_percent, "For RAID, mirrors and pvmove, current percentage in-sync.", 0)
|
||||
FIELD(LVS, lv, PCT, "Cpy%Sync", lvid, 8, copypercent, sync_percent, "For RAID, mirrors and pvmove, current percentage in-sync.", 0)
|
||||
FIELD(LVS, lv, NUM, "Mismatches", lvid, 10, raidmismatchcount, raid_mismatch_count, "For RAID, number of mismatches found or repaired.", 0)
|
||||
FIELD(LVS, lv, STR, "SyncAction", lvid, 10, raidsyncaction, raid_sync_action, "For RAID, the current synchronization action being performed.", 0)
|
||||
FIELD(LVS, lv, NUM, "WBehind", lvid, 7, raidwritebehind, raid_write_behind, "For RAID1, the number of outstanding writes allowed to writemostly devices.", 0)
|
||||
|
@ -1203,6 +1203,7 @@ static const struct dm_report_object_type _devtypes_report_types[] = {
|
||||
#define STR DM_REPORT_FIELD_TYPE_STRING
|
||||
#define NUM DM_REPORT_FIELD_TYPE_NUMBER
|
||||
#define SIZ DM_REPORT_FIELD_TYPE_SIZE
|
||||
#define PCT DM_REPORT_FIELD_TYPE_PERCENT
|
||||
#define STR_LIST DM_REPORT_FIELD_TYPE_STRING_LIST
|
||||
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc, writeable) \
|
||||
{type, sorttype, offsetof(type_ ## strct, field), width, \
|
||||
|
@ -1628,15 +1628,16 @@ struct dm_report_field;
|
||||
/*
|
||||
* dm_report_field_type flags
|
||||
*/
|
||||
#define DM_REPORT_FIELD_MASK 0x000000FF
|
||||
#define DM_REPORT_FIELD_MASK 0x00000FFF
|
||||
#define DM_REPORT_FIELD_ALIGN_MASK 0x0000000F
|
||||
#define DM_REPORT_FIELD_ALIGN_LEFT 0x00000001
|
||||
#define DM_REPORT_FIELD_ALIGN_RIGHT 0x00000002
|
||||
#define DM_REPORT_FIELD_TYPE_MASK 0x000000F0
|
||||
#define DM_REPORT_FIELD_TYPE_MASK 0x00000FF0
|
||||
#define DM_REPORT_FIELD_TYPE_STRING 0x00000010
|
||||
#define DM_REPORT_FIELD_TYPE_NUMBER 0x00000020
|
||||
#define DM_REPORT_FIELD_TYPE_SIZE 0x00000040
|
||||
#define DM_REPORT_FIELD_TYPE_STRING_LIST 0x00000080
|
||||
#define DM_REPORT_FIELD_TYPE_PERCENT 0x00000080
|
||||
#define DM_REPORT_FIELD_TYPE_STRING_LIST 0x00000100
|
||||
|
||||
#define DM_REPORT_FIELD_TYPE_ID_LEN 32
|
||||
#define DM_REPORT_FIELD_TYPE_HEADING_LEN 32
|
||||
@ -1666,6 +1667,7 @@ struct dm_report_reserved_value {
|
||||
const void const *value; /* reserved value:
|
||||
uint64_t for DM_REPORT_FIELD_TYPE_NUMBER
|
||||
uint64_t for DM_REPORT_FIELD_TYPE_SIZE (number of 512-byte sectors)
|
||||
uint64_t for DM_REPORT_FIELD_TYPE_PERCENT
|
||||
const char * for DM_REPORT_FIELD_TYPE_STRING */
|
||||
const char **names; /* null-terminated array of names for this reserved value */
|
||||
const char *description; /* description of the reserved value */
|
||||
|
@ -59,10 +59,10 @@ struct dm_report {
|
||||
/*
|
||||
* Internal per-field flags
|
||||
*/
|
||||
#define FLD_HIDDEN 0x00000100
|
||||
#define FLD_SORT_KEY 0x00000200
|
||||
#define FLD_ASCENDING 0x00000400
|
||||
#define FLD_DESCENDING 0x00000800
|
||||
#define FLD_HIDDEN 0x00001000
|
||||
#define FLD_SORT_KEY 0x00002000
|
||||
#define FLD_ASCENDING 0x00004000
|
||||
#define FLD_DESCENDING 0x00008000
|
||||
|
||||
struct field_properties {
|
||||
struct dm_list list;
|
||||
@ -82,15 +82,15 @@ struct op_def {
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
#define FLD_CMP_MASK 0x000FF000
|
||||
#define FLD_CMP_EQUAL 0x00001000
|
||||
#define FLD_CMP_NOT 0x00002000
|
||||
#define FLD_CMP_GT 0x00004000
|
||||
#define FLD_CMP_LT 0x00008000
|
||||
#define FLD_CMP_REGEX 0x00010000
|
||||
#define FLD_CMP_NUMBER 0x00020000
|
||||
#define FLD_CMP_MASK 0x00FF0000
|
||||
#define FLD_CMP_EQUAL 0x00010000
|
||||
#define FLD_CMP_NOT 0x00020000
|
||||
#define FLD_CMP_GT 0x00040000
|
||||
#define FLD_CMP_LT 0x00080000
|
||||
#define FLD_CMP_REGEX 0x00100000
|
||||
#define FLD_CMP_NUMBER 0x00200000
|
||||
/*
|
||||
* #define FLD_CMP_STRING 0x00040000
|
||||
* #define FLD_CMP_STRING 0x00400000
|
||||
* We could defined FLD_CMP_STRING here for completeness here,
|
||||
* but it's not needed - we can check operator compatibility with
|
||||
* field type by using FLD_CMP_REGEX and FLD_CMP_NUMBER flags only.
|
||||
@ -515,6 +515,7 @@ static const char *_get_field_type_name(unsigned field_type)
|
||||
case DM_REPORT_FIELD_TYPE_STRING: return "string";
|
||||
case DM_REPORT_FIELD_TYPE_NUMBER: return "number";
|
||||
case DM_REPORT_FIELD_TYPE_SIZE: return "size";
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT: return "percent";
|
||||
case DM_REPORT_FIELD_TYPE_STRING_LIST: return "string list";
|
||||
default: return "unknown";
|
||||
}
|
||||
@ -1150,6 +1151,13 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
r = _cmp_field_regex((const char *) f->sort_value, fs->v.r, fs->flags);
|
||||
else {
|
||||
switch(f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
/*
|
||||
* Check against real percent values only.
|
||||
* That means DM_PERCENT_0 <= percent <= DM_PERCENT_100.
|
||||
*/
|
||||
if (*(const uint64_t *) f->sort_value > DM_PERCENT_100)
|
||||
return 0;
|
||||
case DM_REPORT_FIELD_TYPE_NUMBER:
|
||||
r = _cmp_field_int(field_id, *(const uint64_t *) f->sort_value, fs->v.i, fs->flags);
|
||||
break;
|
||||
@ -1553,6 +1561,7 @@ static int _check_reserved_values_supported(const struct dm_report_reserved_valu
|
||||
const struct dm_report_reserved_value *iter;
|
||||
static uint32_t supported_reserved_types = DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
DM_REPORT_FIELD_TYPE_STRING;
|
||||
|
||||
if (!reserved_values)
|
||||
@ -1835,33 +1844,46 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
case DM_REPORT_FIELD_TYPE_NUMBER:
|
||||
case DM_REPORT_FIELD_TYPE_SIZE:
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
if (!(s = _tok_value_number(s, begin, end))) {
|
||||
log_error("Failed to parse numeric value "
|
||||
"for selection field %s.", ft->id);
|
||||
return NULL;
|
||||
}
|
||||
factor = (uint64_t *) custom;
|
||||
*factor = dm_units_to_factor(s, &c, 0, &tmp);
|
||||
|
||||
if (expected_type == DM_REPORT_FIELD_TYPE_NUMBER) {
|
||||
if (*factor) {
|
||||
log_error("Found size unit specifier but "
|
||||
"only numeric value expected for "
|
||||
"selection field %s.",ft->id);
|
||||
factor = (uint64_t *) custom;
|
||||
|
||||
if (*s == DM_PERCENT_CHAR) {
|
||||
s++;
|
||||
c = DM_PERCENT_CHAR;
|
||||
if (expected_type != DM_REPORT_FIELD_TYPE_PERCENT) {
|
||||
log_error("Found percent value but %s value "
|
||||
"expected for selection field %s.",
|
||||
expected_type == DM_REPORT_FIELD_TYPE_NUMBER ?
|
||||
"numeric" : "size", ft->id);
|
||||
return NULL;
|
||||
}
|
||||
*flags |= DM_REPORT_FIELD_TYPE_NUMBER;
|
||||
} else {
|
||||
} else if ((*factor = dm_units_to_factor(s, &c, 0, &tmp))) {
|
||||
s = tmp;
|
||||
if (expected_type != DM_REPORT_FIELD_TYPE_SIZE) {
|
||||
log_error("Found size unit specifier "
|
||||
"but %s value expected for "
|
||||
"selection field %s.",
|
||||
expected_type == DM_REPORT_FIELD_TYPE_NUMBER ?
|
||||
"numeric" : "percent", ft->id);
|
||||
return NULL;
|
||||
}
|
||||
} else if (expected_type == DM_REPORT_FIELD_TYPE_SIZE) {
|
||||
/*
|
||||
* If size unit is not defined in the selection
|
||||
* use use 'm' (1 MiB) by default. This is the
|
||||
* and the type expected is size, use use 'm'
|
||||
* (1 MiB) for the unit by default. This is the
|
||||
* same behaviour as seen in lvcreate -L <size>.
|
||||
*/
|
||||
if (!*factor)
|
||||
*factor = 1024*1024;
|
||||
*flags |= DM_REPORT_FIELD_TYPE_SIZE;
|
||||
*factor = 1024*1024;
|
||||
}
|
||||
|
||||
*flags |= expected_type;
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -2014,6 +2036,24 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
}
|
||||
dm_pool_free(rh->mem, s);
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
if (reserved)
|
||||
fs->v.i = *(uint64_t *) reserved->value;
|
||||
else {
|
||||
fs->v.d = strtod(s, NULL);
|
||||
if ((errno == ERANGE) || (fs->v.d < 0) || (fs->v.d > 100)) {
|
||||
log_error(_out_of_range_msg, s, field_id);
|
||||
goto error;
|
||||
}
|
||||
|
||||
fs->v.i = (dm_percent_t) (DM_PERCENT_1 * fs->v.d);
|
||||
|
||||
if (_check_value_is_reserved(rh, DM_REPORT_FIELD_TYPE_PERCENT, &fs->v.i)) {
|
||||
log_error("Percent value %s found in selection is reserved.", s);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_STRING_LIST:
|
||||
fs->v.l = *(struct selection_str_list **)custom;
|
||||
if (_check_value_is_reserved(rh, DM_REPORT_FIELD_TYPE_STRING_LIST, fs->v.l)) {
|
||||
@ -2065,6 +2105,7 @@ static void _display_selection_help(struct dm_report *rh)
|
||||
log_warn(" field - Reporting field.");
|
||||
log_warn(" number - Non-negative integer value.");
|
||||
log_warn(" size - Floating point value with units, 'm' unit used by default if not specified.");
|
||||
log_warn(" percent - Non-negative integer with or without %% suffix.");
|
||||
log_warn(" string - Characters quoted by \' or \" or unquoted.");
|
||||
log_warn(" string list - Strings enclosed by [ ] and elements delimited by either");
|
||||
log_warn(" \"all items must match\" or \"at least one item must match\" operator.");
|
||||
@ -2191,12 +2232,13 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* some operators can compare only numeric fields */
|
||||
/* some operators can compare only numeric fields (NUMBER, SIZE or PERCENT) */
|
||||
if ((flags & FLD_CMP_NUMBER) &&
|
||||
(ft->flags != DM_REPORT_FIELD_TYPE_NUMBER) &&
|
||||
(ft->flags != DM_REPORT_FIELD_TYPE_SIZE)) {
|
||||
(ft->flags != DM_REPORT_FIELD_TYPE_SIZE) &&
|
||||
(ft->flags != DM_REPORT_FIELD_TYPE_PERCENT)) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with numeric or size fields: %s", ws);
|
||||
log_error("Operator can be used only with number, size or percent fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@ -2206,7 +2248,8 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
goto_bad;
|
||||
} else {
|
||||
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER)
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
|
||||
custom = &factor;
|
||||
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
|
||||
custom = &str_list;
|
||||
|
Loading…
Reference in New Issue
Block a user