zmemtopo: Add case-insensitive partition name filtering

Introduce the -p/--partition-filter option to display only partitions
whose names contain a specified substring. The filter performs
case-insensitive matching and applies consistently across all output
formats (table, tree, and reverse tree views).

Example:

$ zmemtopo -p "part74"
LPAR/LEVEL      SIZE
PARTITION74      12G
└LEVEL4_1        12G
  ├LEVEL3_0       3G
  ├LEVEL3_1       3G
  ├LEVEL3_2       3G
  └LEVEL3_3       3G

Suggested-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
Mete Durlu
2026-07-21 10:10:46 +02:00
committed by Steffen Eiden
parent 29a1ef0023
commit 1aa1558f91
3 changed files with 57 additions and 3 deletions

View File

@@ -56,6 +56,11 @@ Sort and display the data according to given FIELD value. Valid values for
FIELD are "nr" for partition number, "lpar" for partition name, and "sum" for
total partition increments.
.TP
.BR "\-p <SUBSTRING>" " or " "\-\-partition-filter=<SUBSTRING>"
Display only the partitions with names that contain SUBSTRING.
Matching is case-insensitive.
.TP
.BR "\-i" " or " "\-\-ascii"
Use only ASCII characters to render views.

View File

@@ -46,6 +46,7 @@ static struct zmemtopo_globals {
unsigned int sort_field;
unsigned int ascii;
unsigned int fmt_specified;
char *partition_filter;
enum util_fmt_t format;
enum util_fmt_flags_t fmt_flags;
} g;
@@ -116,6 +117,9 @@ static void parse_args(int argc, char *argv[])
case 's':
parse_sort_field(optarg);
break;
case 'p':
g.partition_filter = optarg;
break;
case 'i':
g.ascii = 1;
break;
@@ -483,6 +487,22 @@ static void partition_list_sort(struct partitions *parts)
}
}
static int partition_filter_matches(struct partition *part)
{
int result;
if (!part)
return 0;
if (!g.partition_filter)
return 1;
if (!strlen(g.partition_filter))
return 1;
result = 0;
if (strcasestr(part->part_name, g.partition_filter))
result = 1;
return result;
}
static unsigned int find_entry_cell_size(struct partitions *parts)
{
unsigned int max_digit, max_increment;
@@ -597,8 +617,11 @@ static void table_print(struct partitions *parts)
vdata->entry_len = find_entry_cell_size(parts);
partition_list_calculate_level_lengths(parts, vdata);
table_print_header(table, vdata);
util_list_iterate(parts->list, cur)
util_list_iterate(parts->list, cur) {
if (!partition_filter_matches(cur))
continue;
table_print_row(table, cur, vdata);
}
printf("%s\n", *table);
printf("Increment size: %lu%s\n", unit.size / unit.scale, unit.suffix);
free(vdata);
@@ -716,6 +739,8 @@ static void tree_create(char **tree, struct partitions *parts,
unit = vdata->unit;
tree_create_header(tree, vdata);
util_list_iterate(parts->list, cur) {
if (!partition_filter_matches(cur))
continue;
util_concatf(tree, "%-*s", vdata->cell_len, cur->part_name);
part_size = cur->increment_total * unit.size / unit.scale;
concat_w_padding(tree, vdata->entry_len, 0, "%u%s", part_size,
@@ -737,7 +762,9 @@ static unsigned int is_increment_at(struct partitions *parts,
else
next = util_list_next(parts->list, cur);
for (; next; next = util_list_next(parts->list, next)) {
if (next->entries[level - 1].increments[idx])
if (!next->entries[level - 1].increments[idx])
continue;
if (partition_filter_matches(next))
return 1;
}
return 0;
@@ -772,6 +799,8 @@ static void rtree_print_parts(char **buf, struct partitions *parts,
unit = vdata->unit;
flag_idx = (g.max_level - level) + 1;
util_list_iterate(parts->list, cur) {
if (!partition_filter_matches(cur))
continue;
entries = &cur->entries[level - 1];
if (!entries->increments[idx])
continue;
@@ -789,6 +818,21 @@ static void rtree_print_parts(char **buf, struct partitions *parts,
}
}
static unsigned int rtree_is_last_entry(struct partitions *parts, unsigned int idx,
unsigned int level, unsigned int end)
{
unsigned int tidx;
if (g.partition_filter && !g.tree_full) {
for (tidx = idx + 1; tidx < end; tidx++) {
if (is_increment_at(parts, NULL, level, tidx))
return 0;
}
return 1;
}
return (idx + 1) == end;
}
static void rtree_level_to_part(char **buf, struct partitions *parts,
unsigned int step, unsigned int level,
struct view_data *vdata)
@@ -807,7 +851,8 @@ static void rtree_level_to_part(char **buf, struct partitions *parts,
if (!is_increment_at(parts, NULL, level, idx) && !g.tree_full)
continue;
indent = 0;
vdata->end_flag[flag_idx] = (idx + 1) == end;
vdata->end_flag[flag_idx] = rtree_is_last_entry(parts, idx,
level, end);
if (level != g.max_level)
indent = tree_add_indent(buf, level, vdata->end_flag);
concat_w_padding(buf, vdata->cell_len - indent, 1, "LEVEL%u_%u",

View File

@@ -36,6 +36,10 @@ static struct util_opt opt_vec[] = {
.option = { "sort", required_argument, NULL, 's' },
.argument = "FIELD",
.desc = "Sort view by FIELD (nr, lpar, size)"
}, {
.option = { "partition-filter", required_argument, NULL, 'p' },
.argument = "SUBSTRING",
.desc = "Filter partitions by name substring (case-insensitive)"
}, {
.option = { "ascii", no_argument, NULL, 'i' },
.desc = "Use only ASCII characters",