btrfs-progs/common/sort-utils.h
David Sterba 5cdaf19529 btrfs-progs: inspect list-chunks: better sorting, updated output
Enhance the sorting capabilities of 'inspect list-chunks' to allow
multiple keys. Drop the gaps, this works only for pstart and it's hard
to make it work with arbitrary sort keys.

Usage is printed by default, assuming this is an interesting info and
even if it slows down the output (due to extra lookups) it's more
convenient to print it rather than not.

The options related to usage and empty were removed.

Output changes:

- rename Number to PNumber, meaning physical number on the device
- print Devid, device number, can be also sort key

Examples:

btrfs inspect list-chunks /mnt
btrfs inspect list-chunks --sort length,usage
btrfs inspect list-chunks --sort lstart

Depending on the sort key order, the output can be wild, for that the
PNumber and LNumber give some hint where the chunks lie in their space.

Example output:

$ sudo ./btrfs inspect list-chunks --sort length,usage /
Devid PNumber      Type/profile    PStart    Length      PEnd LNumber    LStart Usage%
----- ------- ----------------- --------- --------- --------- ------- --------- ------
    1       7       Data/single   1.52GiB  16.00MiB   1.54GiB      69 191.68GiB  86.04
    1       3     System/DUP    117.00MiB  32.00MiB 149.00MiB      40 140.17GiB   0.05
    1       2     System/DUP     85.00MiB  32.00MiB 117.00MiB      39 140.17GiB   0.05
    1      15       Data/single   8.04GiB  64.00MiB   8.10GiB      61 188.60GiB  94.46
    1       1       Data/single   1.00MiB  84.00MiB  85.00MiB      68 191.60GiB  74.24
    1       5   Metadata/DUP    341.00MiB 192.00MiB 533.00MiB      60 188.41GiB  82.58
    1       4   Metadata/DUP    149.00MiB 192.00MiB 341.00MiB      59 188.41GiB  82.58
    1      20   Metadata/DUP      9.29GiB 256.00MiB   9.54GiB      38 139.92GiB  57.76
    1      19   Metadata/DUP      9.04GiB 256.00MiB   9.29GiB      37 139.92GiB  57.76
    1      22   Metadata/DUP      9.79GiB 256.00MiB  10.04GiB      25 113.15GiB  57.93
    1      21   Metadata/DUP      9.54GiB 256.00MiB   9.79GiB      24 113.15GiB  57.93
    1      46   Metadata/DUP     29.29GiB 256.00MiB  29.54GiB      43 142.71GiB  62.38

Signed-off-by: David Sterba <dsterba@suse.com>
2024-06-20 10:15:52 +09:30

105 lines
3 KiB
C

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#ifndef __COMMON_SORT_UTILS_H__
#define __COMMON_SORT_UTILS_H__
#include <stdbool.h>
/*
* Example:
struct entry {
int id;
long size;
};
static int cmp_entry_id(const struct entry *a, const struct entry *b)
{
return (a->id < b->id ? -1 :
a->id > b->id ? 1 : 0);
}
static int cmp_entry_size(const struct entry *a, const struct entry *b)
{
return (a->size < b->size ? -1 :
a->size > b->size ? 1 : 0);
}
void test() {
// User data
struct entry entries[SIZE];
// Comparator structure
struct compare comp = { 0 };
// Keys, item comparators, help text defitions
struct sortdef sortit[] = {
{ .name = "id", .comp = (sort_cmp_t)cmp_entry_id,
.desc = "sort by id" },
{ .name = "size", .comp = (sort_cmp_t)cmp_entry_size,
.desc = "sort by entry size" },
SORTDEF_END
};
// List of keys to use for sort (e.g. from command line options)
const char *sortby[] = { "size", "id" };
compare_init(&comp, sortit);
for (i = 0; i < sizeof(sortby) / sizeof(sortby[0]); i++) {
ret = compare_add_sort_key(&comp, sortby[i]);
if (ret < 0) {
printf("ERROR adding sort key %s\n", sortby[i]);
break;
}
}
qsort_r(entries, SIZE, sizeof(struct entry), (sort_r_cmp_t)compare_cmp_multi,
&comp);
}
*/
#define SORTDEF_END { .name = NULL, .comp = NULL }
#define SORT_MAX_KEYS 32
typedef int (*sort_cmp_t)(const void *a, const void *b);
typedef int (*sort_r_cmp_t)(const void *a, const void *b, void *data);
#define SORTDEF_END { .name = NULL, .comp = NULL }
struct sortdef {
const char *name;
const char *desc;
sort_cmp_t comp;
/* User defined identifier of this sort key. */
int id;
};
struct compare {
sort_cmp_t comp[SORT_MAX_KEYS];
unsigned long invert_map;
int count;
const struct sortdef *sortdef;
};
int compare_init(struct compare *comp, const struct sortdef *sortdef);
int compare_cmp_multi(const void *a, const void *b, const struct compare *comp);
int compare_add_sort_key(struct compare *comp, const char *key);
int compare_parse_key_to_id(const struct compare *comp, const char **next);
int compare_add_sort_id(struct compare *comp, int id);
int compare_key_id(const struct compare *comp, const char *key);
const char *compare_id_name(const struct compare *comp, int id);
bool compare_has_id(const struct compare *comp, int id);
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def);
#endif