btrfs-progs: list-chunks: port to sorting API

Use the sorting API. This is 1:1 transformation of previous single key
sorting and needs to be updated so there are multiple accepted instead.

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2023-07-17 17:41:01 +02:00
parent 7f9bcab309
commit 00e401752f
1 changed files with 51 additions and 41 deletions

View File

@ -43,6 +43,7 @@
#include "common/units.h" #include "common/units.h"
#include "common/string-utils.h" #include "common/string-utils.h"
#include "common/string-table.h" #include "common/string-table.h"
#include "common/sort-utils.h"
#include "cmds/commands.h" #include "cmds/commands.h"
static const char * const inspect_cmd_group_usage[] = { static const char * const inspect_cmd_group_usage[] = {
@ -714,17 +715,6 @@ static const char * const cmd_inspect_list_chunks_usage[] = {
NULL NULL
}; };
enum {
CHUNK_SORT_PSTART,
CHUNK_SORT_LSTART,
CHUNK_SORT_USAGE,
/* Length, secondary physical start */
CHUNK_SORT_LENGTH_P,
/* Length, secondary logical start */
CHUNK_SORT_LENGTH_L,
CHUNK_SORT_DEFAULT = CHUNK_SORT_PSTART
};
struct list_chunks_entry { struct list_chunks_entry {
u64 devid; u64 devid;
u64 start; u64 start;
@ -834,7 +824,7 @@ static int cmp_cse_length_logical(const void *va, const void *vb)
return 0; return 0;
} }
static int print_list_chunks(struct list_chunks_ctx *ctx, unsigned sort_mode, static int print_list_chunks(struct list_chunks_ctx *ctx, const char* sortmode,
unsigned unit_mode, bool with_usage, bool with_empty) unsigned unit_mode, bool with_usage, bool with_empty)
{ {
u64 devid; u64 devid;
@ -846,6 +836,47 @@ static int print_list_chunks(struct list_chunks_ctx *ctx, unsigned sort_mode,
u64 number; u64 number;
u32 gaps; u32 gaps;
u32 tabidx; u32 tabidx;
static const struct sortdef sortit[] = {
{ .name = "pstart", .comp = (sort_cmp_t)cmp_cse_devid_start,
.desc = "sort by physical srart offset, group by device" },
{ .name = "lstart", .comp = (sort_cmp_t)cmp_cse_devid_lstart,
.desc = "sort by logical offset" },
{ .name = "usage", .comp = (sort_cmp_t)cmp_cse_devid_usage,
.desc = "sort by chunk usage" },
{ .name = "length_p", .comp = (sort_cmp_t)cmp_cse_length_physical,
.desc = "sort by lentgh, secondary by physical offset" },
{ .name = "length_l", .comp = (sort_cmp_t)cmp_cse_length_logical,
.desc = "sort by lentgh, secondary by logical offset" },
};
enum {
CHUNK_SORT_PSTART,
CHUNK_SORT_LSTART,
CHUNK_SORT_USAGE,
CHUNK_SORT_LENGTH_P,
CHUNK_SORT_LENGTH_L,
CHUNK_SORT_DEFAULT = CHUNK_SORT_PSTART
};
unsigned int sort_mode;
struct compare comp;
if (!sortmode) {
sort_mode = CHUNK_SORT_DEFAULT;
sortmode = "pstart";
} else if (strcmp(sortmode, "pstart") == 0) {
sort_mode = CHUNK_SORT_PSTART;
} else if (strcmp(sortmode, "lstart") == 0) {
sort_mode = CHUNK_SORT_LSTART;
} else if (strcmp(sortmode, "usage") == 0) {
sort_mode = CHUNK_SORT_USAGE;
with_usage = true;
} else if (strcmp(sortmode, "length_p") == 0) {
sort_mode = CHUNK_SORT_LENGTH_P;
} else if (strcmp(sortmode, "length_l") == 0) {
sort_mode = CHUNK_SORT_LENGTH_L;
} else {
error("unknown sort mode: %s", sortmode);
exit(1);
}
/* /*
* Chunks are sorted logically as found by the ioctl, we need to sort * Chunks are sorted logically as found by the ioctl, we need to sort
@ -869,18 +900,10 @@ static int print_list_chunks(struct list_chunks_ctx *ctx, unsigned sort_mode,
lastend = e.start + e.length; lastend = e.start + e.length;
} }
if (sort_mode == CHUNK_SORT_LSTART) compare_init(&comp, sortit);
qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), compare_add_sort_key(&comp, sortmode);
cmp_cse_devid_lstart); qsort_r(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_r_cmp_t)compare_cmp_multi,
else if (sort_mode == CHUNK_SORT_USAGE) &comp);
qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]),
cmp_cse_devid_usage);
else if (sort_mode == CHUNK_SORT_LENGTH_P)
qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]),
cmp_cse_length_physical);
else if (sort_mode == CHUNK_SORT_LENGTH_L)
qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]),
cmp_cse_length_logical);
/* Optional usage, two rows for header and separator, gaps */ /* Optional usage, two rows for header and separator, gaps */
table = table_create(7 + (int)with_usage, 2 + ctx->length + gaps); table = table_create(7 + (int)with_usage, 2 + ctx->length + gaps);
@ -1003,7 +1026,7 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
int e; int e;
DIR *dirstream = NULL; DIR *dirstream = NULL;
unsigned unit_mode; unsigned unit_mode;
unsigned sort_mode = 0; char *sortmode = NULL;
bool with_usage = true; bool with_usage = true;
bool with_empty = true; bool with_empty = true;
const char *path; const char *path;
@ -1036,21 +1059,8 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
switch (c) { switch (c) {
case GETOPT_VAL_SORT: case GETOPT_VAL_SORT:
if (strcmp(optarg, "pstart") == 0) { free(sortmode);
sort_mode = CHUNK_SORT_PSTART; sortmode = strdup(optarg);
} else if (strcmp(optarg, "lstart") == 0) {
sort_mode = CHUNK_SORT_LSTART;
} else if (strcmp(optarg, "usage") == 0) {
sort_mode = CHUNK_SORT_USAGE;
with_usage = true;
} else if (strcmp(optarg, "length_p") == 0) {
sort_mode = CHUNK_SORT_LENGTH_P;
} else if (strcmp(optarg, "length_l") == 0) {
sort_mode = CHUNK_SORT_LENGTH_L;
} else {
error("unknown sort mode: %s", optarg);
exit(1);
}
break; break;
case GETOPT_VAL_USAGE: case GETOPT_VAL_USAGE:
case GETOPT_VAL_NO_USAGE: case GETOPT_VAL_NO_USAGE:
@ -1181,7 +1191,7 @@ static int cmd_inspect_list_chunks(const struct cmd_struct *cmd,
break; break;
} }
ret = print_list_chunks(&ctx, sort_mode, unit_mode, with_usage, with_empty); ret = print_list_chunks(&ctx, sortmode, unit_mode, with_usage, with_empty);
close_file_or_dir(fd, dirstream); close_file_or_dir(fd, dirstream);
out_nomem: out_nomem: