btrfs-progs: fi usage: fix unallocated and print total and slack

The size reported as Unallocated in the table was different that the one
in the listing, calculated differently. The values should reflect the
unallocated area available for the filesystem - not necessarily the
total size of the device. If there's such slack space it's reported
separately.

The values in the table mean:

- Unallocated: block device size - slack - allocated
- Total:       block device size - slack
- Slack:       block device size - filesystem

The new columns make the table wider but the values are deemed to be
important by users and for filesystems with normal profiles it fits
under reasonable line width. During balance or with multiple profiles it
can get wider but this should not be a serious problem.

Example output:

Overall:
    Device size:                  13.00GiB
    Device allocated:            536.00MiB
    Device unallocated:           12.48GiB
    Device missing:                  0.00B
    Device slack:                  1.00GiB
    Used:                          2.31MiB
    Free (estimated):             12.48GiB      (min: 6.24GiB)
    Free (statfs, df):            12.48GiB
    Data ratio:                       1.00
    Metadata ratio:                   2.00
    Global reserve:                3.50MiB      (used: 0.00B)
    Multiple profiles:                  no

              Data    Metadata  System
Id Path       single  DUP       DUP      Unallocated Total    Slack
-- ---------- ------- --------- -------- ----------- -------- -------
 1 /dev/loop0 8.00MiB 512.00MiB 16.00MiB     2.48GiB  3.00GiB 1.00GiB
 2 /dev/loop1       -         -        -    10.00GiB 10.00GiB       -
-- ---------- ------- --------- -------- ----------- -------- -------
   Total      8.00MiB 256.00MiB  8.00MiB    12.48GiB 13.00GiB 1.00GiB
   Used       2.00MiB 144.00KiB 16.00KiB

Issue: #508
Pull-request: #509 (partial fix)
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2022-09-14 21:20:43 +02:00
parent 1c3ab87c92
commit 7ab0c46a81
2 changed files with 55 additions and 8 deletions

View File

@ -284,6 +284,7 @@ usage [options] <path> [<path>...]
Device allocated: 1.17TiB Device allocated: 1.17TiB
Device unallocated: 669.99GiB Device unallocated: 669.99GiB
Device missing: 0.00B Device missing: 0.00B
Device slack: 1.00GiB
Used: 1.14TiB Used: 1.14TiB
Free (estimated): 692.57GiB (min: 692.57GiB) Free (estimated): 692.57GiB (min: 692.57GiB)
Free (statfs, df) 692.57GiB Free (statfs, df) 692.57GiB
@ -292,13 +293,17 @@ usage [options] <path> [<path>...]
Global reserve: 512.00MiB (used: 0.00B) Global reserve: 512.00MiB (used: 0.00B)
Multiple profiles: no Multiple profiles: no
* *Device size* -- sum of raw device capacity available to the filesystem * *Device size* -- sum of raw device capacity available to the
filesystem, note that this may not be the same as the total device
size (the difference is accounted as slack)
* *Device allocated* -- sum of total space allocated for * *Device allocated* -- sum of total space allocated for
data/metadata/system profiles, this also accounts space reserved but data/metadata/system profiles, this also accounts space reserved but
not yet used for extents not yet used for extents
* *Device unallocated* -- the remaining unallocated space for future * *Device unallocated* -- the remaining unallocated space for future
allocations (difference of the above two numbers) allocations (difference of the above two numbers)
* *Device missing* -- sum of capacity of all missing devices * *Device missing* -- sum of capacity of all missing devices
* *Device slack* -- sum of slack space on all devices (difference
between entire device size and the space occupied by filesystem)
* *Used* -- sum of the used space of data/metadata/system profiles, not * *Used* -- sum of the used space of data/metadata/system profiles, not
including the reserved space including the reserved space
* *Free (estimated)* -- approximate size of the remaining free space * *Free (estimated)* -- approximate size of the remaining free space

View File

@ -428,6 +428,13 @@ out:
return ret; return ret;
} }
static u64 calc_slack_size(const struct device_info *devinfo)
{
if (devinfo->device_size > 0)
return devinfo->device_size - devinfo->size;
return 0;
}
#define MIN_UNALOCATED_THRESH SZ_16M #define MIN_UNALOCATED_THRESH SZ_16M
static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo, static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
int chunkcount, struct device_info *devinfo, int devcount, int chunkcount, struct device_info *devinfo, int devcount,
@ -449,6 +456,7 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
u64 r_total_used = 0; u64 r_total_used = 0;
u64 r_total_unused = 0; u64 r_total_unused = 0;
u64 r_total_missing = 0; /* sum of missing devices size */ u64 r_total_missing = 0; /* sum of missing devices size */
u64 r_total_slack = 0;
u64 r_data_used = 0; u64 r_data_used = 0;
u64 r_data_chunks = 0; u64 r_data_chunks = 0;
u64 l_data_chunks = 0; u64 l_data_chunks = 0;
@ -479,6 +487,7 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
r_total_size = 0; r_total_size = 0;
for (i = 0; i < devcount; i++) { for (i = 0; i < devcount; i++) {
r_total_size += devinfo[i].size; r_total_size += devinfo[i].size;
r_total_slack += calc_slack_size(&devinfo[i]);
if (!devinfo[i].device_size) if (!devinfo[i].device_size)
r_total_missing += devinfo[i].size; r_total_missing += devinfo[i].size;
} }
@ -608,6 +617,8 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
pretty_size_mode(r_total_unused, unit_mode | UNITS_NEGATIVE)); pretty_size_mode(r_total_unused, unit_mode | UNITS_NEGATIVE));
printf(" Device missing:\t\t%*s\n", width, printf(" Device missing:\t\t%*s\n", width,
pretty_size_mode(r_total_missing, unit_mode)); pretty_size_mode(r_total_missing, unit_mode));
printf(" Device slack:\t\t%*s\n", width,
pretty_size_mode(r_total_slack, unit_mode));
ret = ioctl(fd, BTRFS_IOC_GET_FEATURES, &feature_flags); ret = ioctl(fd, BTRFS_IOC_GET_FEATURES, &feature_flags);
if (ret == 0 && (feature_flags.incompat_flags & BTRFS_FEATURE_INCOMPAT_ZONED)) { if (ret == 0 && (feature_flags.incompat_flags & BTRFS_FEATURE_INCOMPAT_ZONED)) {
u64 zone_size; u64 zone_size;
@ -834,15 +845,20 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
{ {
int i; int i;
u64 total_unused = 0; u64 total_unused = 0;
u64 total_total = 0;
u64 total_slack = 0;
struct string_table *matrix = NULL; struct string_table *matrix = NULL;
int ncols, nrows; int ncols, nrows;
int col; int col;
int unallocated_col; int unallocated_col;
int spaceinfos_col; int spaceinfos_col;
int total_col;
int slack_col;
u64 slack;
const int vhdr_skip = 3; /* amount of vertical header space */ const int vhdr_skip = 3; /* amount of vertical header space */
/* id, path, unallocated */ /* id, path, unallocated, total, slack */
ncols = 3; ncols = 5;
spaceinfos_col = 2; spaceinfos_col = 2;
/* Properly count the real space infos */ /* Properly count the real space infos */
for (i = 0; i < sargs->total_spaces; i++) { for (i = 0; i < sargs->total_spaces; i++) {
@ -878,11 +894,15 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
btrfs_group_profile_str(flags)); btrfs_group_profile_str(flags));
col++; col++;
} }
unallocated_col = col; unallocated_col = col++;
total_col = col++;
slack_col = col++;
table_printf(matrix, 0, 1, "<Id"); table_printf(matrix, 0, 1, "<Id");
table_printf(matrix, 1, 1, "<Path"); table_printf(matrix, 1, 1, "<Path");
table_printf(matrix, unallocated_col, 1, "<Unallocated"); table_printf(matrix, unallocated_col, 1, "<Unallocated");
table_printf(matrix, total_col, 1, "<Total");
table_printf(matrix, slack_col, 1, "<Slack");
/* body */ /* body */
for (i = 0; i < device_info_count; i++) { for (i = 0; i < device_info_count; i++) {
@ -932,10 +952,24 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
unused = device_get_partition_size(device_info_ptr[i].path) unused = device_get_partition_size(device_info_ptr[i].path)
- total_allocated; - total_allocated;
unused = device_info_ptr[i].size - total_allocated;
table_printf(matrix, unallocated_col, vhdr_skip + i, ">%s", table_printf(matrix, unallocated_col, vhdr_skip + i, ">%s",
pretty_size_mode(unused, unit_mode | UNITS_NEGATIVE)); pretty_size_mode(unused, unit_mode | UNITS_NEGATIVE));
table_printf(matrix, total_col, vhdr_skip + i, ">%s",
pretty_size_mode(device_info_ptr[i].size,
unit_mode | UNITS_NEGATIVE));
slack = calc_slack_size(&device_info_ptr[i]);
if (slack > 0) {
table_printf(matrix, slack_col, vhdr_skip + i, ">%s",
pretty_size_mode(slack,
unit_mode | UNITS_NEGATIVE));
} else {
table_printf(matrix, slack_col, vhdr_skip + i, ">-");
}
total_unused += unused; total_unused += unused;
total_slack += slack;
total_total += device_info_ptr[i].size;
} }
@ -952,9 +986,13 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
table_printf(matrix, col, vhdr_skip + device_info_count, "*-"); table_printf(matrix, col, vhdr_skip + device_info_count, "*-");
col++; col++;
} }
/* One for Unallocated */ /* Line under Unallocated, Total, Slack */
table_printf(matrix, col, vhdr_skip - 1, "*-"); table_printf(matrix, col, vhdr_skip - 1, "*-");
table_printf(matrix, col, vhdr_skip + device_info_count, "*-"); table_printf(matrix, col, vhdr_skip + device_info_count, "*-");
table_printf(matrix, col + 1, vhdr_skip - 1, "*-");
table_printf(matrix, col + 1, vhdr_skip + device_info_count, "*-");
table_printf(matrix, col + 2, vhdr_skip - 1, "*-");
table_printf(matrix, col + 2, vhdr_skip + device_info_count, "*-");
/* footer */ /* footer */
table_printf(matrix, 1, vhdr_skip + device_info_count + 1, "<Total"); table_printf(matrix, 1, vhdr_skip + device_info_count + 1, "<Total");
@ -970,6 +1008,12 @@ static void _cmd_filesystem_usage_tabular(unsigned unit_mode,
table_printf(matrix, unallocated_col, vhdr_skip + device_info_count + 1, table_printf(matrix, unallocated_col, vhdr_skip + device_info_count + 1,
">%s", ">%s",
pretty_size_mode(total_unused, unit_mode | UNITS_NEGATIVE)); pretty_size_mode(total_unused, unit_mode | UNITS_NEGATIVE));
table_printf(matrix, total_col, vhdr_skip + device_info_count + 1,
">%s",
pretty_size_mode(total_total, unit_mode | UNITS_NEGATIVE));
table_printf(matrix, slack_col, vhdr_skip + device_info_count + 1,
">%s",
pretty_size_mode(total_slack, unit_mode | UNITS_NEGATIVE));
table_printf(matrix, 1, vhdr_skip + device_info_count + 2, "<Used"); table_printf(matrix, 1, vhdr_skip + device_info_count + 2, "<Used");
for (i = 0, col = spaceinfos_col; i < sargs->total_spaces; i++) { for (i = 0, col = spaceinfos_col; i < sargs->total_spaces; i++) {
@ -1256,7 +1300,5 @@ void print_device_sizes(struct device_info *devinfo, unsigned unit_mode)
pretty_size_mode(devinfo->device_size, unit_mode)); pretty_size_mode(devinfo->device_size, unit_mode));
printf(" Device slack: %*s%10s\n", printf(" Device slack: %*s%10s\n",
(int)(20 - strlen("Device slack")), "", (int)(20 - strlen("Device slack")), "",
pretty_size_mode(devinfo->device_size > 0 ? pretty_size_mode(calc_slack_size(devinfo), unit_mode));
devinfo->device_size - devinfo->size : 0,
unit_mode));
} }