btrfs-progs: fi df: implement json output

Print JSON output with example output:

  $ btrfs --format json filesystem df /path
  {
    "__header": {
      "version": "1"
    },
    "filesystem-df": [
      {
	"bg-type": "Data",
	"bg-profile": "single",
	"total": "841813590016",
	"used": "494085484544"
      },
      {
	"bg-type": "System",
	"bg-profile": "single",
	"total": "33554432",
	"used": "114688"
      },
      {
	"bg-type": "Metadata",
	"bg-profile": "single",
	"total": "24696061952",
	"used": "5743165440"
      },
      {
	"bg-type": "GlobalReserve",
	"bg-profile": "single",
	"total": "536870912",
	"used": "0"
      }
    ]
  }

Optionally there's "zone_unusable" key. The rowspec cannot print the
same output as now so the original implementation is preserved.

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2022-12-06 17:12:10 +01:00
parent b16b35e074
commit 0b3df991db

View file

@ -54,6 +54,7 @@
#include "common/parse-utils.h"
#include "common/string-utils.h"
#include "common/filesystem-utils.h"
#include "common/format-output.h"
#include "cmds/commands.h"
#include "cmds/filesystem-usage.h"
#include "ioctl.h"
@ -75,10 +76,12 @@ static const char * const cmd_filesystem_df_usage[] = {
"Show space usage information for a mount point",
"",
HELPINFO_UNITS_SHORT_LONG,
HELPINFO_INSERT_GLOBALS,
HELPINFO_INSERT_FORMAT,
NULL
};
static void print_df(int fd, struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
static void print_df_text(int fd, struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
{
u64 i;
struct btrfs_ioctl_space_info *sp = sargs->spaces;
@ -99,6 +102,44 @@ static void print_df(int fd, struct btrfs_ioctl_space_args *sargs, unsigned unit
}
}
static const struct rowspec filesystem_df_rowspec[] = {
{ .key = "bg-type", .fmt = "%s", .out_json = "bg-type" },
{ .key = "bg-profile", .fmt = "%s", .out_json = "bg-profile" },
{ .key = "total", .fmt = "%llu", .out_json = "total" },
{ .key = "used", .fmt = "%llu", .out_json = "used" },
{ .key = "zone_unusable", .fmt = "%llu", .out_json = "zone_unusable" },
ROWSPEC_END
};
static void print_df_json(int fd, struct btrfs_ioctl_space_args *sargs)
{
struct format_ctx fctx;
u64 i;
struct btrfs_ioctl_space_info *sp = sargs->spaces;
u64 unusable;
bool ok;
fmt_start(&fctx, filesystem_df_rowspec, 1, 0);
fmt_print_start_group(&fctx, "filesystem-df", JSON_TYPE_ARRAY);
for (i = 0; i < sargs->total_spaces; i++, sp++) {
unusable = device_get_zone_unusable(fd, sp->flags);
ok = (unusable != DEVICE_ZONE_UNUSABLE_UNKNOWN);
fmt_print_start_group(&fctx, NULL, JSON_TYPE_MAP);
fmt_print(&fctx, "bg-type", btrfs_group_type_str(sp->flags));
fmt_print(&fctx, "bg-profile", btrfs_group_profile_str(sp->flags));
fmt_print(&fctx, "total", sp->total_bytes);
fmt_print(&fctx, "used", sp->used_bytes);
if (ok)
fmt_print(&fctx, "zone_unusable", unusable);
fmt_print_end_group(&fctx, NULL);
}
fmt_print_end_group(&fctx, "filesystem-df");
fmt_end(&fctx);
}
static int cmd_filesystem_df(const struct cmd_struct *cmd,
int argc, char **argv)
{
@ -125,7 +166,10 @@ static int cmd_filesystem_df(const struct cmd_struct *cmd,
ret = get_df(fd, &sargs);
if (ret == 0) {
print_df(fd, sargs, unit_mode);
if (bconf.output_format == CMD_FORMAT_JSON)
print_df_json(fd, sargs);
else
print_df_text(fd, sargs, unit_mode);
free(sargs);
} else {
errno = -ret;
@ -136,7 +180,7 @@ static int cmd_filesystem_df(const struct cmd_struct *cmd,
close_file_or_dir(fd, dirstream);
return !!ret;
}
static DEFINE_SIMPLE_COMMAND(filesystem_df, "df");
static DEFINE_COMMAND_WITH_FLAGS(filesystem_df, "df", CMD_FORMAT_JSON);
static int match_search_item_kernel(u8 *fsid, char *mnt, char *label,
char *search)