blob: f81986f0df4df303ac08645e7916e1bfdce3dedd [file] [log] [blame]
// 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);
}