]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_db: enable conversion of rt space units
authorDarrick J. Wong <djwong@kernel.org>
Tue, 29 Oct 2024 00:03:32 +0000 (17:03 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 31 Oct 2024 22:45:05 +0000 (15:45 -0700)
Teach the xfs_db convert function about rt extents, rt block numbers,
and how to compute offsets within the rt bitmap and summary files.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
db/convert.c
man/man8/xfs_db.8

index e1466057031da6cb859f2ccc1883dd7da3e89abe..4c2ff1c5804c476bf08d1b3549c49c3b43dc2145 100644 (file)
@@ -8,6 +8,7 @@
 #include "command.h"
 #include "output.h"
 #include "init.h"
+#include "block.h"
 
 #define        M(A)    (1 << CT_ ## A)
 #define        agblock_to_bytes(x)     \
         agino_to_bytes(XFS_INO_TO_AGINO(mp, (x))))
 #define        inoidx_to_bytes(x)      \
        ((uint64_t)(x) << mp->m_sb.sb_inodelog)
+#define rtblock_to_bytes(x)    \
+       ((uint64_t)(x) << mp->m_sb.sb_blocklog)
+#define rtx_to_rtblock(x)      \
+       ((uint64_t)(x) * mp->m_sb.sb_rextsize)
 
 typedef enum {
        CT_NONE = -1,
@@ -40,11 +45,12 @@ typedef enum {
        CT_INO,                 /* xfs_ino_t */
        CT_INOIDX,              /* index of inode in fsblock */
        CT_INOOFF,              /* byte offset in inode */
+       CT_RTBLOCK,             /* realtime block */
+       CT_RTX,                 /* realtime extent */
        NCTS
 } ctype_t;
 
 typedef struct ctydesc {
-       ctype_t         ctype;
        int             allowed;
        const char      **names;
 } ctydesc_t;
@@ -61,12 +67,16 @@ typedef union {
        xfs_ino_t       ino;
        int             inoidx;
        int             inooff;
+       xfs_rtblock_t   rtblock;
+       xfs_rtblock_t   rtx;
 } cval_t;
 
 static uint64_t                bytevalue(ctype_t ctype, cval_t *val);
+static int             rtconvert_f(int argc, char **argv);
 static int             convert_f(int argc, char **argv);
 static int             getvalue(char *s, ctype_t ctype, cval_t *val);
-static ctype_t         lookupcty(char *ctyname);
+static ctype_t         lookupcty(const struct ctydesc *descs,
+                                 const char *ctyname);
 
 static const char      *agblock_names[] = { "agblock", "agbno", NULL };
 static const char      *agino_names[] = { "agino", "aginode", NULL };
@@ -74,6 +84,8 @@ static const char     *agnumber_names[] = { "agnumber", "agno", NULL };
 static const char      *bboff_names[] = { "bboff", "daddroff", NULL };
 static const char      *blkoff_names[] = { "blkoff", "fsboff", "agboff",
                                            NULL };
+static const char      *rtblkoff_names[] = { "blkoff", "rtboff",
+                                           NULL };
 static const char      *byte_names[] = { "byte", "fsbyte", NULL };
 static const char      *daddr_names[] = { "daddr", "bb", NULL };
 static const char      *fsblock_names[] = { "fsblock", "fsb", "fsbno", NULL };
@@ -81,30 +93,119 @@ static const char  *ino_names[] = { "ino", "inode", NULL };
 static const char      *inoidx_names[] = { "inoidx", "offset", NULL };
 static const char      *inooff_names[] = { "inooff", "inodeoff", NULL };
 
+static const char      *rtblock_names[] = { "rtblock", "rtb", "rtbno", NULL };
+static const char      *rtx_names[] = { "rtx", "rtextent", NULL };
+
 static const ctydesc_t ctydescs[NCTS] = {
-       { CT_AGBLOCK, M(AGNUMBER)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF),
-         agblock_names },
-       { CT_AGINO, M(AGNUMBER)|M(INOOFF), agino_names },
-       { CT_AGNUMBER,
-         M(AGBLOCK)|M(AGINO)|M(BBOFF)|M(BLKOFF)|M(INOIDX)|M(INOOFF),
-         agnumber_names },
-       { CT_BBOFF, M(AGBLOCK)|M(AGNUMBER)|M(DADDR)|M(FSBLOCK), bboff_names },
-       { CT_BLKOFF, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK), blkoff_names },
-       { CT_BYTE, 0, byte_names },
-       { CT_DADDR, M(BBOFF), daddr_names },
-       { CT_FSBLOCK, M(BBOFF)|M(BLKOFF)|M(INOIDX), fsblock_names },
-       { CT_INO, M(INOOFF), ino_names },
-       { CT_INOIDX, M(AGBLOCK)|M(AGNUMBER)|M(FSBLOCK)|M(INOOFF),
-         inoidx_names },
-       { CT_INOOFF,
-         M(AGBLOCK)|M(AGINO)|M(AGNUMBER)|M(FSBLOCK)|M(INO)|M(INOIDX),
-         inooff_names },
+       [CT_AGBLOCK] = {
+               .allowed = M(AGNUMBER) |
+                          M(BBOFF) |
+                          M(BLKOFF) |
+                          M(INOIDX) |
+                          M(INOOFF),
+               .names   = agblock_names,
+       },
+       [CT_AGINO] = {
+               .allowed = M(AGNUMBER) |
+                          M(INOOFF),
+               .names   = agino_names,
+       },
+       [CT_AGNUMBER] = {
+               .allowed = M(AGBLOCK) |
+                          M(AGINO) |
+                          M(BBOFF) |
+                          M(BLKOFF) |
+                          M(INOIDX) |
+                          M(INOOFF),
+               .names   = agnumber_names,
+       },
+       [CT_BBOFF] = {
+               .allowed = M(AGBLOCK) |
+                          M(AGNUMBER) |
+                          M(DADDR) |
+                          M(FSBLOCK),
+               .names   = bboff_names,
+       },
+       [CT_BLKOFF] = {
+               .allowed = M(AGBLOCK) |
+                          M(AGNUMBER) |
+                          M(FSBLOCK),
+               .names   = blkoff_names,
+       },
+       [CT_BYTE] = {
+               .allowed = 0,
+               .names   = byte_names,
+       },
+       [CT_DADDR] = {
+               .allowed = M(BBOFF),
+               .names   = daddr_names,
+       },
+       [CT_FSBLOCK] = {
+               .allowed = M(BBOFF) |
+                          M(BLKOFF) |
+                          M(INOIDX),
+               .names   = fsblock_names,
+       },
+       [CT_INO] = {
+               .allowed = M(INOOFF),
+               .names   = ino_names,
+       },
+       [CT_INOIDX] = {
+               .allowed = M(AGBLOCK) |
+                          M(AGNUMBER) |
+                          M(FSBLOCK) |
+                          M(INOOFF),
+               .names   = inoidx_names,
+       },
+       [CT_INOOFF] = {
+               .allowed = M(AGBLOCK) |
+                          M(AGINO) |
+                          M(AGNUMBER) |
+                          M(FSBLOCK) |
+                          M(INO) |
+                          M(INOIDX),
+               .names   = inooff_names,
+       },
+};
+
+static const ctydesc_t ctydescs_rt[NCTS] = {
+       [CT_BBOFF] = {
+               .allowed = M(DADDR) |
+                          M(RTBLOCK),
+               .names   = bboff_names,
+       },
+       [CT_BLKOFF] = {
+               .allowed = M(RTBLOCK),
+               .names   = rtblkoff_names,
+       },
+       [CT_BYTE] = {
+               .allowed = 0,
+               .names   = byte_names,
+       },
+       [CT_DADDR] = {
+               .allowed = M(BBOFF),
+               .names   = daddr_names,
+       },
+       [CT_RTBLOCK] = {
+               .allowed = M(BBOFF) |
+                          M(BLKOFF),
+               .names   = rtblock_names,
+       },
+       [CT_RTX] = {
+               .allowed = M(BBOFF) |
+                          M(BLKOFF),
+               .names   = rtx_names,
+       },
 };
 
 static const cmdinfo_t convert_cmd =
        { "convert", NULL, convert_f, 3, 9, 0, "type num [type num]... type",
          "convert from one address form to another", NULL };
 
+static const cmdinfo_t rtconvert_cmd =
+       { "rtconvert", NULL, rtconvert_f, 3, 9, 0, "type num [type num]... type",
+         "convert from one realtime address form to another", NULL };
+
 static uint64_t
 bytevalue(ctype_t ctype, cval_t *val)
 {
@@ -131,6 +232,10 @@ bytevalue(ctype_t ctype, cval_t *val)
                return inoidx_to_bytes(val->inoidx);
        case CT_INOOFF:
                return (uint64_t)val->inooff;
+       case CT_RTBLOCK:
+               return rtblock_to_bytes(val->rtblock);
+       case CT_RTX:
+               return rtblock_to_bytes(rtx_to_rtblock(val->rtx));
        case CT_NONE:
        case NCTS:
                break;
@@ -159,13 +264,13 @@ convert_f(int argc, char **argv)
                         "arguments\n"), argc);
                return 0;
        }
-       if ((wtype = lookupcty(argv[argc - 1])) == CT_NONE) {
+       if ((wtype = lookupcty(ctydescs, argv[argc - 1])) == CT_NONE) {
                dbprintf(_("unknown conversion type %s\n"), argv[argc - 1]);
                return 0;
        }
 
        for (i = mask = conmask = 0; i < (argc - 1) / 2; i++) {
-               c = lookupcty(argv[i * 2]);
+               c = lookupcty(ctydescs, argv[i * 2]);
                if (c == CT_NONE) {
                        dbprintf(_("unknown conversion type %s\n"), argv[i * 2]);
                        return 0;
@@ -230,6 +335,99 @@ convert_f(int argc, char **argv)
        case CT_INOOFF:
                v &= mp->m_sb.sb_inodesize - 1;
                break;
+       case CT_RTBLOCK:
+       case CT_RTX:
+               /* shouldn't get here */
+               ASSERT(0);
+               break;
+       case CT_NONE:
+       case NCTS:
+               /* NOTREACHED */
+               break;
+       }
+       dbprintf("0x%llx (%llu)\n", v, v);
+       return 0;
+}
+
+static int
+rtconvert_f(int argc, char **argv)
+{
+       ctype_t         c;
+       int             conmask;
+       cval_t          cvals[NCTS] = {};
+       int             i;
+       int             mask;
+       uint64_t        v;
+       ctype_t         wtype;
+
+       /* move past the "rtconvert" command */
+       argc--;
+       argv++;
+
+       if ((argc % 2) != 1) {
+               dbprintf(_("bad argument count %d to rtconvert, expected 3,5,7,9 "
+                        "arguments\n"), argc);
+               return 0;
+       }
+       if ((wtype = lookupcty(ctydescs_rt, argv[argc - 1])) == CT_NONE) {
+               dbprintf(_("unknown conversion type %s\n"), argv[argc - 1]);
+               return 0;
+       }
+
+       for (i = mask = conmask = 0; i < (argc - 1) / 2; i++) {
+               c = lookupcty(ctydescs_rt, argv[i * 2]);
+               if (c == CT_NONE) {
+                       dbprintf(_("unknown conversion type %s\n"), argv[i * 2]);
+                       return 0;
+               }
+               if (c == wtype) {
+                       dbprintf(_("result type same as argument\n"));
+                       return 0;
+               }
+               if (conmask & (1 << c)) {
+                       dbprintf(_("conflicting conversion type %s\n"),
+                               argv[i * 2]);
+                       return 0;
+               }
+               if (!getvalue(argv[i * 2 + 1], c, &cvals[c]))
+                       return 0;
+               mask |= 1 << c;
+               conmask |= ~ctydescs_rt[c].allowed;
+       }
+       v = 0;
+       for (c = (ctype_t)0; c < NCTS; c++) {
+               if (!(mask & (1 << c)))
+                       continue;
+               v += bytevalue(c, &cvals[c]);
+       }
+       switch (wtype) {
+       case CT_BBOFF:
+               v &= BBMASK;
+               break;
+       case CT_BLKOFF:
+               v &= mp->m_blockmask;
+               break;
+       case CT_BYTE:
+               break;
+       case CT_DADDR:
+               v >>= BBSHIFT;
+               break;
+       case CT_RTBLOCK:
+               v = xfs_daddr_to_rtb(mp, v >> BBSHIFT);
+               break;
+       case CT_RTX:
+               v = xfs_daddr_to_rtb(mp, v >> BBSHIFT) / mp->m_sb.sb_rextsize;
+               break;
+       case CT_AGBLOCK:
+       case CT_AGINO:
+       case CT_AGNUMBER:
+       case CT_FSBLOCK:
+       case CT_INO:
+       case CT_INOIDX:
+       case CT_INOOFF:
+               /* shouldn't get here */
+               ASSERT(0);
+               break;
        case CT_NONE:
        case NCTS:
                /* NOTREACHED */
@@ -243,6 +441,7 @@ void
 convert_init(void)
 {
        add_command(&convert_cmd);
+       add_command(&rtconvert_cmd);
 }
 
 static int
@@ -290,6 +489,12 @@ getvalue(char *s, ctype_t ctype, cval_t *val)
        case CT_INOOFF:
                val->inooff = (int)v;
                break;
+       case CT_RTBLOCK:
+               val->rtblock = (xfs_rtblock_t)v;
+               break;
+       case CT_RTX:
+               val->rtx = (xfs_rtblock_t)v;
+               break;
        case CT_NONE:
        case NCTS:
                /* NOTREACHED */
@@ -299,13 +504,15 @@ getvalue(char *s, ctype_t ctype, cval_t *val)
 }
 
 static ctype_t
-lookupcty(char *ctyname)
+lookupcty(
+       const struct ctydesc    *descs,
+       const char              *ctyname)
 {
        ctype_t         cty;
        const char      **name;
 
        for (cty = (ctype_t)0; cty < NCTS; cty++) {
-               for (name = ctydescs[cty].names; *name; name++) {
+               for (name = descs[cty].names; name && *name; name++) {
                        if (strcmp(ctyname, *name) == 0)
                                return cty;
                }
index 48afcb6e81787b44eb31a7da132a4bfbf7c270f3..0bf434299a3fb4084cb71a0ca5607f5aeecd7096 100644 (file)
@@ -1127,6 +1127,57 @@ Show position ring (if no
 argument is given), or move to a specific entry in the position ring given by
 .IR index .
 .TP
+.BI "rtconvert " "type number" " [" "type number" "] ... " type
+Convert from one address form to another for realtime section addresses.
+The known
+.IR type s,
+with alternate names, are:
+.RS 1.0i
+.PD 0
+.HP
+.B bboff
+or
+.B daddroff
+(byte offset in a
+.BR daddr )
+.HP
+.B blkoff
+or
+.B fsboff or
+.B rtboff
+(byte offset in a
+.B rtblock
+or
+.BR rtextent )
+.HP
+.B byte
+or
+.B fsbyte
+(byte address in filesystem)
+.HP
+.B daddr
+or
+.B bb
+(disk address, 512-byte blocks)
+.HP
+.B rtblock
+or
+.B rtb
+or
+.B rtbno
+(realtime filesystem block, see the
+.B fsblock
+command)
+.HP
+.B rtx
+or
+.B rtextent
+(realtime extent)
+.PD
+.RE
+.IP
+Only conversions that "make sense" are allowed.
+.TP
 .BI "sb [" agno ]
 Set current address to SB header in allocation group
 .IR agno .