blob: 5c941dc462081be9210742b7d4dc4f8980aedbfa [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
* Author: Darrick J. Wong <darrick.wong@oracle.com>
*/
#include "libxfs.h"
#include "command.h"
#include "init.h"
#include "output.h"
#include "libfrog/fsgeom.h"
#include "libfrog/logging.h"
static void
info_help(void)
{
dbprintf(_(
"\n"
" Pretty-prints the filesystem geometry as derived from the superblock.\n"
" The output has the same format as mkfs.xfs, xfs_info, and other utilities.\n"
"\n"
));
}
static int
info_f(
int argc,
char **argv)
{
struct xfs_fsop_geom geo;
libxfs_fs_geometry(&mp->m_sb, &geo, XFS_FS_GEOM_MAX_STRUCT_VER);
xfs_report_geom(&geo, fsdevice, x.logname, x.rtname);
return 0;
}
static const struct cmdinfo info_cmd = {
.name = "info",
.altname = "i",
.cfunc = info_f,
.argmin = 0,
.argmax = 0,
.canpush = 0,
.args = NULL,
.oneline = N_("pretty-print superblock info"),
.help = info_help,
};
static void
agresv_help(void)
{
dbprintf(_(
"\n"
" Print the size and per-AG reservation information some allocation groups.\n"
"\n"
" Specific allocation group numbers can be provided as command line arguments.\n"
" If no arguments are provided, all allocation groups are iterated.\n"
"\n"
));
}
static void
print_agresv_info(
xfs_agnumber_t agno)
{
struct xfs_buf *bp;
struct xfs_agf *agf;
xfs_extlen_t ask = 0;
xfs_extlen_t used = 0;
xfs_extlen_t free = 0;
xfs_extlen_t length = 0;
int error;
error = -libxfs_refcountbt_calc_reserves(mp, NULL, agno, &ask, &used);
if (error)
xfrog_perror(error, "refcountbt");
error = -libxfs_finobt_calc_reserves(mp, NULL, agno, &ask, &used);
if (error)
xfrog_perror(error, "finobt");
error = -libxfs_rmapbt_calc_reserves(mp, NULL, agno, &ask, &used);
if (error)
xfrog_perror(error, "rmapbt");
error = -libxfs_read_agf(mp, NULL, agno, 0, &bp);
if (error)
xfrog_perror(error, "AGF");
agf = XFS_BUF_TO_AGF(bp);
length = be32_to_cpu(agf->agf_length);
free = be32_to_cpu(agf->agf_freeblks) +
be32_to_cpu(agf->agf_flcount);
libxfs_buf_relse(bp);
printf("AG %d: length: %u free: %u reserved: %u used: %u",
agno, length, free, ask, used);
if (ask - used > free)
printf(" <not enough space>");
printf("\n");
}
static int
agresv_f(
int argc,
char **argv)
{
xfs_agnumber_t agno;
int i;
if (argc > 1) {
for (i = 1; i < argc; i++) {
long a;
char *p;
errno = 0;
a = strtol(argv[i], &p, 0);
if (p == argv[i])
errno = ERANGE;
if (errno) {
perror(argv[i]);
continue;
}
if (a < 0 || a >= mp->m_sb.sb_agcount) {
fprintf(stderr, "%ld: Not a AG.\n", a);
continue;
}
print_agresv_info(a);
}
return 0;
}
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
print_agresv_info(agno);
return 0;
}
static const struct cmdinfo agresv_cmd = {
.name = "agresv",
.altname = NULL,
.cfunc = agresv_f,
.argmin = 0,
.argmax = -1,
.canpush = 0,
.args = NULL,
.oneline = N_("print AG reservation stats"),
.help = agresv_help,
};
void
info_init(void)
{
add_command(&info_cmd);
add_command(&agresv_cmd);
}