]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_db: dump per-AG reservations
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 30 Jan 2020 18:40:46 +0000 (13:40 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Thu, 30 Jan 2020 18:40:46 +0000 (13:40 -0500)
Add a new 'agresv' command to print the size and free blocks count of an
AG along with the size and usage of the per-AG reservation.  This
command can be used to aid in diagnosing why a particular filesystem
fails the mount time per-AG space reservation, and to figure out how
much space needs to be freed from a given AG to fix the problem.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
db/info.c
libxfs/libxfs_api_defs.h
man/man8/xfs_db.8

index e5f1c2dd7051a6ab5155d7acb5c51f47d296cc60..fc5ccfe753e270386e4cb30b5bd9d6f5a2953d39 100644 (file)
--- a/db/info.c
+++ b/db/info.c
@@ -8,6 +8,7 @@
 #include "init.h"
 #include "output.h"
 #include "libfrog/fsgeom.h"
+#include "libfrog/logging.h"
 
 static void
 info_help(void)
@@ -45,8 +46,111 @@ static const struct cmdinfo info_cmd = {
        .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_putbuf(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);
 }
index 33e52926a29ab53e5e6bf0fc6311c38e2030d5d9..c7fa16075456136b6ad642edd7f00b5694854929 100644 (file)
 #define xfs_verify_rtbno               libxfs_verify_rtbno
 #define xfs_zero_extent                        libxfs_zero_extent
 
+#define xfs_refcountbt_calc_reserves   libxfs_refcountbt_calc_reserves
+#define xfs_finobt_calc_reserves       libxfs_finobt_calc_reserves
+#define xfs_rmapbt_calc_reserves       libxfs_rmapbt_calc_reserves
+#define xfs_read_agf                   libxfs_read_agf
+
 #endif /* __LIBXFS_API_DEFS_H__ */
index 9f1ff7619547b0620fc930601ddad02be5f60f88..7f73d458cf76a3ac7de5fd4c5d61897877452751 100644 (file)
@@ -179,6 +179,11 @@ Set current address to the AGI block for allocation group
 .IR agno .
 If no argument is given, use the current allocation group.
 .TP
+.BI "agresv [" agno ]
+Displays the length, free block count, per-AG reservation size, and per-AG
+reservation usage for a given AG.
+If no argument is given, display information for all AGs.
+.TP
 .BI "attr_remove [\-r|\-u|\-s] [\-n] " name
 Remove the specified extended attribute from the current file.
 .RS 1.0i