]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_db: report parent pointers embedded in xattrs
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:22 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:11 +0000 (17:01 -0700)
Decode the parent pointer inode, generation, and name fields if the
parent pointer passes basic validation checks.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
db/attr.c
db/attrshort.c
db/field.c
db/field.h

index 3252f388614e0b95d9d82a1294c47711480273de..3b556c43def5e296362db63fc73a607821dae073 100644 (file)
--- a/db/attr.c
+++ b/db/attr.c
@@ -33,6 +33,8 @@ static int    attr_remote_data_count(void *obj, int startoff);
 static int     attr3_remote_hdr_count(void *obj, int startoff);
 static int     attr3_remote_data_count(void *obj, int startoff);
 
+static int     attr_leaf_value_pptr_count(void *obj, int startoff);
+
 const field_t  attr_hfld[] = {
        { "", FLDT_ATTR, OI(0), C1, 0, TYP_NONE },
        { NULL }
@@ -118,6 +120,8 @@ const field_t       attr_leaf_name_flds[] = {
          attr_leaf_name_local_count, FLD_COUNT, TYP_NONE },
        { "name", FLDT_CHARNS, OI(LNOFF(nameval)),
          attr_leaf_name_local_name_count, FLD_COUNT, TYP_NONE },
+       { "parent_dir", FLDT_PARENT_REC, attr_leaf_name_local_value_offset,
+         attr_leaf_value_pptr_count, FLD_COUNT | FLD_OFFSET, TYP_NONE },
        { "value", FLDT_CHARNS, attr_leaf_name_local_value_offset,
          attr_leaf_name_local_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE },
        { "valueblk", FLDT_UINT32X, OI(LVOFF(valueblk)),
@@ -307,6 +311,8 @@ __attr_leaf_name_local_value_count(
 
        if (!(e->flags & XFS_ATTR_LOCAL))
                return 0;
+       if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT)
+               return 0;
 
        l = xfs_attr3_leaf_name_local(leaf, i);
        return be16_to_cpu(l->valuelen);
@@ -514,6 +520,28 @@ attr3_remote_hdr_count(
        return be32_to_cpu(node->rm_magic) == XFS_ATTR3_RMT_MAGIC;
 }
 
+static int
+__leaf_pptr_count(
+       struct xfs_attr_leafblock       *leaf,
+       struct xfs_attr_leaf_entry      *e,
+       int                             i)
+{
+       if (!(e->flags & XFS_ATTR_LOCAL))
+               return 0;
+       if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) != XFS_ATTR_PARENT)
+               return 0;
+
+       return 1;
+}
+
+static int
+attr_leaf_value_pptr_count(
+       void                            *obj,
+       int                             startoff)
+{
+       return attr_leaf_entry_walk(obj, startoff, __leaf_pptr_count);
+}
+
 int
 attr_size(
        void    *obj,
index 978f58d67a7b02c2f6dbf9b65cdaeaafd17e0ac8..7e5c94ca533d99b3082b69c59728850062b8440f 100644 (file)
@@ -18,6 +18,8 @@ static int    attr_sf_entry_value_offset(void *obj, int startoff, int idx);
 static int     attr_shortform_list_count(void *obj, int startoff);
 static int     attr_shortform_list_offset(void *obj, int startoff, int idx);
 
+static int     attr_sf_entry_pptr_count(void *obj, int startoff);
+
 const field_t  attr_shortform_flds[] = {
        { "hdr", FLDT_ATTR_SF_HDR, OI(0), C1, 0, TYP_NONE },
        { "list", FLDT_ATTR_SF_ENTRY, attr_shortform_list_offset,
@@ -48,6 +50,8 @@ const field_t attr_sf_entry_flds[] = {
          TYP_NONE },
        { "name", FLDT_CHARNS, OI(EOFF(nameval)), attr_sf_entry_name_count,
          FLD_COUNT, TYP_NONE },
+       { "parent_dir", FLDT_PARENT_REC, attr_sf_entry_value_offset,
+         attr_sf_entry_pptr_count, FLD_COUNT | FLD_OFFSET, TYP_NONE },
        { "value", FLDT_CHARNS, attr_sf_entry_value_offset,
          attr_sf_entry_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE },
        { NULL }
@@ -92,6 +96,10 @@ attr_sf_entry_value_count(
 
        ASSERT(bitoffs(startoff) == 0);
        e = (struct xfs_attr_sf_entry *)((char *)obj + byteize(startoff));
+
+       if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT)
+               return 0;
+
        return e->valuelen;
 }
 
@@ -159,3 +167,19 @@ attrshort_size(
                e = xfs_attr_sf_nextentry(e);
        return bitize((int)((char *)e - (char *)hdr));
 }
+
+static int
+attr_sf_entry_pptr_count(
+       void                            *obj,
+       int                             startoff)
+{
+       struct xfs_attr_sf_entry        *e;
+
+       ASSERT(bitoffs(startoff) == 0);
+       e = (struct xfs_attr_sf_entry *)((char *)obj + byteize(startoff));
+
+       if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) != XFS_ATTR_PARENT)
+               return 0;
+
+       return 1;
+}
index a3e47ee81ccf6b65246d556ff7656b0a64e6293f..a61ccc9ef6d072c7350bc536163a645fabfc93d1 100644 (file)
 #include "dir2sf.h"
 #include "symlink.h"
 
+#define        PPOFF(f)        bitize(offsetof(struct xfs_parent_rec, f))
+const field_t          parent_flds[] = {
+       { "inumber", FLDT_INO, OI(PPOFF(p_ino)), C1, 0, TYP_INODE },
+       { "gen", FLDT_UINT32D, OI(PPOFF(p_gen)), C1, 0, TYP_NONE },
+       { NULL }
+};
+#undef PPOFF
+
 const ftattr_t ftattrtab[] = {
        { FLDT_AGBLOCK, "agblock", fp_num, "%u", SI(bitsz(xfs_agblock_t)),
          FTARG_DONULL, fa_agblock, NULL },
@@ -384,6 +392,8 @@ const ftattr_t      ftattrtab[] = {
        { FLDT_UINT8X, "uint8x", fp_num, "%#x", SI(bitsz(uint8_t)), 0, NULL,
          NULL },
        { FLDT_UUID, "uuid", fp_uuid, NULL, SI(bitsz(uuid_t)), 0, NULL, NULL },
+       { FLDT_PARENT_REC, "parent", NULL, (char *)parent_flds,
+         SI(bitsz(struct xfs_parent_rec)), 0, NULL, parent_flds },
        { FLDT_ZZZ, NULL }
 };
 
index 634742a572c8067e032b6853241944f415acfc85..b1bfdbed19cea3ccce033dec4162a510f566c81c 100644 (file)
@@ -187,6 +187,9 @@ typedef enum fldt   {
        FLDT_UINT8O,
        FLDT_UINT8X,
        FLDT_UUID,
+
+       FLDT_PARENT_REC,
+
        FLDT_ZZZ                        /* mark last entry */
 } fldt_t;