| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* |
| * Copyright (c) 2021-2024 Oracle. All rights reserved. |
| * Author: Darrick J. Wong <djwong@kernel.org> |
| */ |
| #include "platform_defs.h" |
| #include "libxfs.h" |
| #include "command.h" |
| #include "input.h" |
| #include "init.h" |
| #include "io.h" |
| #include "libfrog/logging.h" |
| #include "libfrog/paths.h" |
| #include "libfrog/fsgeom.h" |
| |
| static cmdinfo_t aginfo_cmd; |
| static cmdinfo_t rginfo_cmd; |
| |
| static int |
| report_aginfo( |
| struct xfs_fd *xfd, |
| xfs_agnumber_t agno) |
| { |
| struct xfs_ag_geometry ageo = { 0 }; |
| int ret; |
| |
| ret = -xfrog_ag_geometry(xfd->fd, agno, &ageo); |
| if (ret) { |
| xfrog_perror(ret, "aginfo"); |
| return 1; |
| } |
| |
| printf(_("AG: %u\n"), ageo.ag_number); |
| printf(_("Blocks: %u\n"), ageo.ag_length); |
| printf(_("Free Blocks: %u\n"), ageo.ag_freeblks); |
| printf(_("Inodes: %u\n"), ageo.ag_icount); |
| printf(_("Free Inodes: %u\n"), ageo.ag_ifree); |
| printf(_("Sick: 0x%x\n"), ageo.ag_sick); |
| printf(_("Checked: 0x%x\n"), ageo.ag_checked); |
| printf(_("Flags: 0x%x\n"), ageo.ag_flags); |
| |
| return 0; |
| } |
| |
| /* Display AG status. */ |
| static int |
| aginfo_f( |
| int argc, |
| char **argv) |
| { |
| struct xfs_fd xfd = XFS_FD_INIT(file->fd); |
| unsigned long long x; |
| xfs_agnumber_t agno = NULLAGNUMBER; |
| int c; |
| int ret = 0; |
| |
| ret = -xfd_prepare_geometry(&xfd); |
| if (ret) { |
| xfrog_perror(ret, "xfd_prepare_geometry"); |
| exitcode = 1; |
| return 1; |
| } |
| |
| while ((c = getopt(argc, argv, "a:")) != EOF) { |
| switch (c) { |
| case 'a': |
| errno = 0; |
| x = strtoll(optarg, NULL, 10); |
| if (!errno && x >= NULLAGNUMBER) |
| errno = ERANGE; |
| if (errno) { |
| perror("aginfo"); |
| return 1; |
| } |
| agno = x; |
| break; |
| default: |
| return command_usage(&aginfo_cmd); |
| } |
| } |
| |
| if (agno != NULLAGNUMBER) { |
| ret = report_aginfo(&xfd, agno); |
| } else { |
| for (agno = 0; !ret && agno < xfd.fsgeom.agcount; agno++) { |
| ret = report_aginfo(&xfd, agno); |
| } |
| } |
| |
| return ret; |
| } |
| |
| static void |
| aginfo_help(void) |
| { |
| printf(_( |
| "\n" |
| "Report allocation group geometry.\n" |
| "\n" |
| " -a agno -- Report on the given allocation group.\n" |
| "\n")); |
| |
| } |
| |
| static cmdinfo_t aginfo_cmd = { |
| .name = "aginfo", |
| .cfunc = aginfo_f, |
| .argmin = 0, |
| .argmax = -1, |
| .args = "[-a agno]", |
| .flags = CMD_NOMAP_OK, |
| .help = aginfo_help, |
| }; |
| |
| static int |
| report_rginfo( |
| struct xfs_fd *xfd, |
| xfs_rgnumber_t rgno) |
| { |
| struct xfs_rtgroup_geometry rgeo = { 0 }; |
| int ret; |
| |
| ret = -xfrog_rtgroup_geometry(xfd->fd, rgno, &rgeo); |
| if (ret) { |
| xfrog_perror(ret, "rginfo"); |
| return 1; |
| } |
| |
| printf(_("RTG: %u\n"), rgeo.rg_number); |
| printf(_("Length: %u\n"), rgeo.rg_length); |
| printf(_("Sick: 0x%x\n"), rgeo.rg_sick); |
| printf(_("Checked: 0x%x\n"), rgeo.rg_checked); |
| printf(_("Flags: 0x%x\n"), rgeo.rg_flags); |
| |
| return 0; |
| } |
| |
| /* Display rtgroup status. */ |
| static int |
| rginfo_f( |
| int argc, |
| char **argv) |
| { |
| struct xfs_fd xfd = XFS_FD_INIT(file->fd); |
| unsigned long long x; |
| xfs_rgnumber_t rgno = NULLRGNUMBER; |
| int c; |
| int ret = 0; |
| |
| ret = -xfd_prepare_geometry(&xfd); |
| if (ret) { |
| xfrog_perror(ret, "xfd_prepare_geometry"); |
| exitcode = 1; |
| return 1; |
| } |
| |
| while ((c = getopt(argc, argv, "r:")) != EOF) { |
| switch (c) { |
| case 'r': |
| errno = 0; |
| x = strtoll(optarg, NULL, 10); |
| if (!errno && x >= NULLRGNUMBER) |
| errno = ERANGE; |
| if (errno) { |
| perror("rginfo"); |
| return 1; |
| } |
| rgno = x; |
| break; |
| default: |
| return command_usage(&rginfo_cmd); |
| } |
| } |
| |
| if (rgno != NULLRGNUMBER) { |
| ret = report_rginfo(&xfd, rgno); |
| } else { |
| for (rgno = 0; !ret && rgno < xfd.fsgeom.rgcount; rgno++) { |
| ret = report_rginfo(&xfd, rgno); |
| } |
| } |
| |
| return ret; |
| } |
| |
| static void |
| rginfo_help(void) |
| { |
| printf(_( |
| "\n" |
| "Report realtime group geometry.\n" |
| "\n" |
| " -r rgno -- Report on the given realtime group.\n" |
| "\n")); |
| |
| } |
| |
| static cmdinfo_t rginfo_cmd = { |
| .name = "rginfo", |
| .cfunc = rginfo_f, |
| .argmin = 0, |
| .argmax = -1, |
| .args = "[-r rgno]", |
| .flags = CMD_NOMAP_OK, |
| .help = rginfo_help, |
| }; |
| |
| void |
| aginfo_init(void) |
| { |
| aginfo_cmd.oneline = _("Get XFS allocation group state."); |
| add_command(&aginfo_cmd); |
| rginfo_cmd.oneline = _("Get XFS realtime group state."); |
| add_command(&rginfo_cmd); |
| } |