@@ -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,
@@ -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;
+}
@@ -24,6 +24,14 @@
#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 }
};
@@ -187,6 +187,9 @@ typedef enum fldt {
FLDT_UINT8O,
FLDT_UINT8X,
FLDT_UUID,
+
+ FLDT_PARENT_REC,
+
FLDT_ZZZ /* mark last entry */
} fldt_t;