Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 42 additions & 8 deletions cmds/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,19 +999,34 @@ static int cmd_device_stats(const struct cmd_struct *cmd, int argc, char **argv)
}
static DEFINE_COMMAND_WITH_FLAGS(device_stats, "stats", CMD_FORMAT_JSON);

static const struct rowspec device_usage_rowspec[] = {
{ .key = "device", .fmt = "str", .out_json = "device" },
{ .key = "devid", .fmt = "%llu", .out_json = "devid" },
{ .key = "device_size", .fmt = "%llu", .out_json = "device_size" },
{ .key = "device_slack", .fmt = "%llu", .out_json = "device_slack" },
{ .key = "type", .fmt = "str", .out_json = "type" },
{ .key = "profile", .fmt = "str", .out_json = "profile" },
{ .key = "num_stripes", .fmt = "%llu", .out_json = "num_stripes" },
{ .key = "size", .fmt = "%llu", .out_json = "size" },
{ .key = "unallocated", .fmt = "%llu", .out_json = "unallocated" },
ROWSPEC_END
};

static const char * const cmd_device_usage_usage[] = {
"btrfs device usage [options] <path> [<path>..]",
"Show detailed information about internal allocations in devices.",
"",
HELPINFO_UNITS_SHORT_LONG,
HELPINFO_INSERT_FORMAT,
NULL
};

static int _cmd_device_usage(int fd, const char *path, unsigned unit_mode)
static int _cmd_device_usage(int fd, const char *path, unsigned unit_mode, struct format_ctx *fctx)
{
int ret = 0;
struct array chunkinfos = { 0 };
struct array devinfos = { 0 };
const bool json = (bconf.output_format == CMD_FORMAT_JSON);

ret = load_chunk_and_device_info(fd, &chunkinfos, &devinfos);
if (ret)
Expand All @@ -1020,10 +1035,22 @@ static int _cmd_device_usage(int fd, const char *path, unsigned unit_mode)
for (int i = 0; i < devinfos.length; i++) {
const struct device_info *devinfo = devinfos.data[i];

pr_default("%s, ID: %llu\n", devinfo->path, devinfo->devid);
print_device_sizes(devinfo, unit_mode);
print_device_chunks(devinfo, &chunkinfos, unit_mode);
pr_default("\n");
if (json) {
fmt_print_start_group(fctx, NULL, JSON_TYPE_MAP);
fmt_print(fctx, "device", devinfo->path);
fmt_print(fctx, "devid", devinfo->devid);
} else {
pr_default("%s, ID: %llu\n", devinfo->path, devinfo->devid);
}

print_device_sizes(devinfo, unit_mode, fctx);
print_device_chunks(devinfo, &chunkinfos, unit_mode, fctx);

if (json) {
fmt_print_end_group(fctx, NULL);
} else {
pr_default("\n");
}
}

out:
Expand All @@ -1040,6 +1067,7 @@ static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
unsigned unit_mode;
int ret = 0;
int i;
struct format_ctx fctx;

unit_mode = get_unit_mode_from_arg(&argc, argv, 1);

Expand All @@ -1048,10 +1076,13 @@ static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
if (check_argc_min(argc - optind, 1))
return 1;

fmt_start(&fctx, device_usage_rowspec, 24, 0);
fmt_print_start_group(&fctx, "device-usage", JSON_TYPE_ARRAY);

for (i = optind; i < argc; i++) {
int fd;

if (i > 1)
if (i > 1 && bconf.output_format != CMD_FORMAT_JSON)
pr_default("\n");

fd = btrfs_open_dir(argv[i]);
Expand All @@ -1060,17 +1091,20 @@ static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
break;
}

ret = _cmd_device_usage(fd, argv[i], unit_mode);
ret = _cmd_device_usage(fd, argv[i], unit_mode, &fctx);
btrfs_warn_multiple_profiles(fd);
close(fd);

if (ret)
break;
}

fmt_print_end_group(&fctx, "device-usage");
fmt_end(&fctx);

return !!ret;
}
static DEFINE_SIMPLE_COMMAND(device_usage, "usage");
static DEFINE_COMMAND_WITH_FLAGS(device_usage, "usage", CMD_FORMAT_JSON);

static const char * const cmd_device_replace_usage[] = {
"btrfs device replace <command> [...]\n"
Expand Down
84 changes: 55 additions & 29 deletions cmds/filesystem-usage.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,10 +1278,15 @@ static int cmd_filesystem_usage(const struct cmd_struct *cmd,
DEFINE_SIMPLE_COMMAND(filesystem_usage, "usage");

void print_device_chunks(const struct device_info *devinfo,
const struct array *chunkinfos, unsigned unit_mode)
const struct array *chunkinfos, unsigned unit_mode,
struct format_ctx *fctx)
{
int i;
u64 allocated = 0;
const bool json = (bconf.output_format == CMD_FORMAT_JSON);

if (json)
fmt_print_start_group(fctx, "chunks", JSON_TYPE_ARRAY);

for (i = 0; i < chunkinfos->length; i++) {
const char *description;
Expand All @@ -1304,20 +1309,29 @@ void print_device_chunks(const struct device_info *devinfo,
size = calc_chunk_size(chunk_info);
num_stripes = chunk_info->num_stripes;

if (btrfs_bg_type_is_stripey(profile)) {
pr_default(" %s,%s/%llu:%*s%10s\n",
description,
r_mode,
num_stripes,
(int)(20 - strlen(description) - strlen(r_mode)
- count_digits(num_stripes) - 1), "",
pretty_size_mode(size, unit_mode));
if (json) {
fmt_print_start_group(fctx, NULL, JSON_TYPE_MAP);
fmt_print(fctx, "type", description);
fmt_print(fctx, "profile", r_mode);
fmt_print(fctx, "num_stripes", num_stripes);
fmt_print(fctx, "size", size);
fmt_print_end_group(fctx, NULL);
} else {
pr_default(" %s,%s:%*s%10s\n",
description,
r_mode,
(int)(20 - strlen(description) - strlen(r_mode)), "",
pretty_size_mode(size, unit_mode));
if (btrfs_bg_type_is_stripey(profile)) {
pr_default(" %s,%s/%llu:%*s%10s\n",
description,
r_mode,
num_stripes,
(int)(20 - strlen(description) - strlen(r_mode)
- count_digits(num_stripes) - 1), "",
pretty_size_mode(size, unit_mode));
} else {
pr_default(" %s,%s:%*s%10s\n",
description,
r_mode,
(int)(20 - strlen(description) - strlen(r_mode)), "",
pretty_size_mode(size, unit_mode));
}
}

allocated += size;
Expand All @@ -1328,22 +1342,34 @@ void print_device_chunks(const struct device_info *devinfo,
* If chunkinfos is empty, we cannot compute the unallocated size, so
* don't print incorrect data.
*/
if (chunkinfos->length == 0)
pr_default(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "", "N/A");
else
pr_default(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "",
pretty_size_mode(devinfo->size - allocated,
unit_mode | UNITS_NEGATIVE));
if (json) {
fmt_print_end_group(fctx, "chunks");
if (chunkinfos->length > 0)
fmt_print(fctx, "unallocated", devinfo->size - allocated);

} else {
if (chunkinfos->length == 0)
pr_default(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "", "N/A");
else
pr_default(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "",
pretty_size_mode(devinfo->size - allocated,
unit_mode | UNITS_NEGATIVE));
}
}

void print_device_sizes(const struct device_info *devinfo, unsigned unit_mode)
void print_device_sizes(const struct device_info *devinfo, unsigned unit_mode, struct format_ctx *fctx)
{
pr_default(" Device size: %*s%10s\n",
(int)(20 - strlen("Device size")), "",
pretty_size_mode(devinfo->device_size, unit_mode));
pr_default(" Device slack: %*s%10s\n",
(int)(20 - strlen("Device slack")), "",
pretty_size_mode(calc_slack_size(devinfo), unit_mode));
if (bconf.output_format == CMD_FORMAT_JSON) {
fmt_print(fctx, "device_size", devinfo->device_size);
fmt_print(fctx, "device_slack", calc_slack_size(devinfo));
} else {
pr_default(" Device size: %*s%10s\n",
(int)(20 - strlen("Device size")), "",
pretty_size_mode(devinfo->device_size, unit_mode));
pr_default(" Device slack: %*s%10s\n",
(int)(20 - strlen("Device slack")), "",
pretty_size_mode(calc_slack_size(devinfo), unit_mode));
}
}
7 changes: 5 additions & 2 deletions cmds/filesystem-usage.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "kerncompat.h"
#include "kernel-shared/uapi/btrfs.h"
#include "common/array.h"
#include "common/format-output.h"

struct device_info {
u64 devid;
Expand All @@ -47,8 +48,10 @@ struct chunk_info {

int load_chunk_and_device_info(int fd, struct array *chunkinfos, struct array *devinfos);
void print_device_chunks(const struct device_info *devinfo,
const struct array *chunkinfos, unsigned unit_mode);
void print_device_sizes(const struct device_info *devinfo, unsigned unit_mode);
const struct array *chunkinfos, unsigned unit_mode,
struct format_ctx *fctx);
void print_device_sizes(const struct device_info *devinfo, unsigned unit_mode,
struct format_ctx *fctx);
int dev_to_fsid(const char *dev, u8 *fsid);

#endif