[PATCH 2/6] xfs: replace parent pointer diroffset with sha512 hash of name

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Replace the diroffset with the sha512 hash of the dirent name, thereby
eliminating the need for directory repair to update all the parent
pointers after rebuilding the directory.

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
---
 db/attr.c                |   25 +++++-
 db/attrshort.c           |   19 ++++-
 db/field.c               |    2 
 db/field.h               |    1 
 db/fprint.c              |   31 +++++++
 db/fprint.h              |    2 
 db/metadump.c            |   39 ++++-----
 libxfs/libxfs_api_defs.h |    2 
 libxfs/libxfs_priv.h     |    1 
 libxfs/xfs_da_format.h   |   15 ++--
 libxfs/xfs_fs.h          |    4 -
 libxfs/xfs_parent.c      |  124 +++++++++++++++++++++++-------
 libxfs/xfs_parent.h      |   21 +++--
 logprint/log_redo.c      |   15 +---
 man/man3/xfsctl.3        |    1 
 mkfs/proto.c             |    7 +-
 repair/phase6.c          |   13 +--
 repair/pptr.c            |  193 +++++++++++++++++++++++++++++++---------------
 repair/pptr.h            |    2 
 19 files changed, 358 insertions(+), 159 deletions(-)


diff --git a/db/attr.c b/db/attr.c
index 8ea7b36e..bacdc6d9 100644
--- a/db/attr.c
+++ b/db/attr.c
@@ -20,6 +20,7 @@ static int	attr_leaf_hdr_count(void *obj, int startoff);
 static int	attr_leaf_name_local_count(void *obj, int startoff);
 static int	attr_leaf_name_local_name_count(void *obj, int startoff);
 static int	attr_leaf_name_pptr_count(void *obj, int startoff);
+static int	attr_leaf_name_pptr_namehashlen(void *obj, int startoff);
 static int	attr_leaf_name_local_value_count(void *obj, int startoff);
 static int	attr_leaf_name_local_value_offset(void *obj, int startoff,
 						  int idx);
@@ -125,8 +126,8 @@ const field_t	attr_leaf_name_flds[] = {
 	  attr_leaf_name_pptr_count, FLD_COUNT, TYP_INODE },
 	{ "parent_gen", FLDT_UINT32D, OI(PPOFF(p_gen)),
 	  attr_leaf_name_pptr_count, FLD_COUNT, TYP_NONE },
-	{ "parent_diroffset", FLDT_UINT32D, OI(PPOFF(p_diroffset)),
-	  attr_leaf_name_pptr_count, FLD_COUNT, TYP_NONE },
+	{ "parent_namehash", FLDT_HEXSTRING, OI(PPOFF(p_namehash)),
+	  attr_leaf_name_pptr_namehashlen, FLD_COUNT, 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)),
@@ -302,6 +303,26 @@ attr_leaf_name_pptr_count(
 			__attr_leaf_name_pptr_count);
 }
 
+static int
+__attr_leaf_name_pptr_namehashlen(
+	struct xfs_attr_leafblock	*leaf,
+	struct xfs_attr_leaf_entry      *e,
+	int				i)
+{
+	if (e->flags & XFS_ATTR_PARENT)
+		return XFS_PARENT_NAME_HASH_SIZE;
+	return 0;
+}
+
+static int
+attr_leaf_name_pptr_namehashlen(
+	void				*obj,
+	int				startoff)
+{
+	return attr_leaf_entry_walk(obj, startoff,
+			__attr_leaf_name_pptr_namehashlen);
+}
+
 static int
 __attr_leaf_name_local_name_count(
 	struct xfs_attr_leafblock	*leaf,
diff --git a/db/attrshort.c b/db/attrshort.c
index 7c8ac485..be15f4ee 100644
--- a/db/attrshort.c
+++ b/db/attrshort.c
@@ -14,6 +14,7 @@
 
 static int	attr_sf_entry_name_count(void *obj, int startoff);
 static int	attr_sf_entry_pptr_count(void *obj, int startoff);
+static int	attr_sf_entry_pptr_namehashlen(void *obj, int startoff);
 static int	attr_sf_entry_value_count(void *obj, int startoff);
 static int	attr_sf_entry_value_offset(void *obj, int startoff, int idx);
 static int	attr_shortform_list_count(void *obj, int startoff);
@@ -56,8 +57,8 @@ const field_t	attr_sf_entry_flds[] = {
 	  FLD_COUNT, TYP_INODE },
 	{ "parent_gen", FLDT_UINT32D, OI(PPOFF(p_gen)), attr_sf_entry_pptr_count,
 	  FLD_COUNT, TYP_NONE },
-	{ "parent_diroffset", FLDT_UINT32D, OI(PPOFF(p_diroffset)),
-	   attr_sf_entry_pptr_count, FLD_COUNT, TYP_NONE },
+	{ "parent_namehash", FLDT_HEXSTRING, OI(PPOFF(p_namehash)),
+	   attr_sf_entry_pptr_namehashlen, FLD_COUNT, TYP_NONE },
 	{ "value", FLDT_CHARNS, attr_sf_entry_value_offset,
 	  attr_sf_entry_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE },
 	{ NULL }
@@ -77,6 +78,20 @@ attr_sf_entry_pptr_count(
 	return 0;
 }
 
+static int
+attr_sf_entry_pptr_namehashlen(
+	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_PARENT)
+		return XFS_PARENT_NAME_HASH_SIZE;
+	return 0;
+}
+
 static int
 attr_sf_entry_name_count(
 	void				*obj,
diff --git a/db/field.c b/db/field.c
index a3e47ee8..afadfdb4 100644
--- a/db/field.c
+++ b/db/field.c
@@ -144,6 +144,8 @@ const ftattr_t	ftattrtab[] = {
 	{ FLDT_CHARNS, "charns", fp_charns, NULL, SI(bitsz(char)), 0, NULL,
 	  NULL },
 	{ FLDT_CHARS, "chars", fp_num, "%c", SI(bitsz(char)), 0, NULL, NULL },
+	{ FLDT_HEXSTRING, "hexstring", fp_hexstring, NULL, SI(bitsz(char)), 0, NULL,
+	  NULL },
 	{ FLDT_REXTLEN, "rextlen", fp_num, "%u", SI(RMAPBT_BLOCKCOUNT_BITLEN),
 	  0, NULL, NULL },
 	{ FLDT_RFILEOFFD, "rfileoffd", fp_num, "%llu", SI(RMAPBT_OFFSET_BITLEN),
diff --git a/db/field.h b/db/field.h
index 634742a5..d756e04a 100644
--- a/db/field.h
+++ b/db/field.h
@@ -64,6 +64,7 @@ typedef enum fldt	{
 	FLDT_CFSBLOCK,
 	FLDT_CHARNS,
 	FLDT_CHARS,
+	FLDT_HEXSTRING,
 	FLDT_REXTLEN,
 	FLDT_RFILEOFFD,
 	FLDT_REXTFLG,
diff --git a/db/fprint.c b/db/fprint.c
index 65accfda..c4462fb6 100644
--- a/db/fprint.c
+++ b/db/fprint.c
@@ -54,6 +54,37 @@ fp_charns(
 	return 1;
 }
 
+int
+fp_hexstring(
+	void	*obj,
+	int	bit,
+	int	count,
+	char	*fmtstr,
+	int	size,
+	int	arg,
+	int	base,
+	int	array)
+{
+	int	i;
+	char	*p;
+
+	ASSERT(bitoffs(bit) == 0);
+	ASSERT(size == bitsz(char));
+	dbprintf("\"");
+	for (i = 0, p = (char *)obj + byteize(bit);
+	     i < count && !seenint();
+	     i++, p++) {
+		char c = *p & 0xff;
+
+		if (isalnum(c))
+			dbprintf("%c", c);
+		else
+			dbprintf("\\x%02x", c);
+	}
+	dbprintf("\"");
+	return 1;
+}
+
 int
 fp_num(
 	void		*obj,
diff --git a/db/fprint.h b/db/fprint.h
index a1ea935c..c07240c6 100644
--- a/db/fprint.h
+++ b/db/fprint.h
@@ -9,6 +9,8 @@ typedef int (*prfnc_t)(void *obj, int bit, int count, char *fmtstr, int size,
 
 extern int	fp_charns(void *obj, int bit, int count, char *fmtstr, int size,
 			  int arg, int base, int array);
+extern int	fp_hexstring(void *obj, int bit, int count, char *fmtstr,
+			  int size, int arg, int base, int array);
 extern int	fp_num(void *obj, int bit, int count, char *fmtstr, int size,
 		       int arg, int base, int array);
 extern int	fp_sarray(void *obj, int bit, int count, char *fmtstr, int size,
diff --git a/db/metadump.c b/db/metadump.c
index 4be23993..e56acdcc 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -740,14 +740,12 @@ nametable_add(xfs_dahash_t hash, int namelen, unsigned char *name)
 #define rol32(x,y)		(((x) << (y)) | ((x) >> (32 - (y))))
 
 static inline unsigned char
-random_filename_char(xfs_ino_t	ino)
+random_filename_char(void)
 {
 	static unsigned char filename_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 						"abcdefghijklmnopqrstuvwxyz"
 						"0123456789-_";
 
-	if (ino)
-		return filename_alphabet[ino % (sizeof filename_alphabet - 1)];
 	return filename_alphabet[random() % (sizeof filename_alphabet - 1)];
 }
 
@@ -817,7 +815,6 @@ in_lost_found(
  */
 static void
 obfuscate_name(
-	xfs_ino_t	ino,
 	xfs_dahash_t	hash,
 	size_t		name_len,
 	unsigned char	*name)
@@ -845,7 +842,7 @@ obfuscate_name(
 	 * Accumulate its new hash value as we go.
 	 */
 	for (i = 0; i < name_len - 5; i++) {
-		*newp = random_filename_char(ino);
+		*newp = random_filename_char();
 		new_hash = *newp ^ rol32(new_hash, 7);
 		newp++;
 	}
@@ -1210,10 +1207,14 @@ generate_obfuscated_name(
 	/* Obfuscate the name (if possible) */
 
 	hash = libxfs_da_hashname(name, namelen);
-	if (xfs_has_parent(mp))
-		obfuscate_name(ino, hash, namelen, name);
+	if (xfs_has_parent(mp) && ino)
+		/*
+		 * XXX: no good way to obfuscate dirent names now that we
+		 * hash them into the pptr key
+		 * obfuscate_name(ino, hash, namelen, name)
+		 */ ;
 	else
-		obfuscate_name(0, hash, namelen, name);
+		obfuscate_name(hash, namelen, name);
 
 	/*
 	 * Make sure the name is not something already seen.  If we
@@ -1326,7 +1327,7 @@ obfuscate_path_components(
 			/* last (or single) component */
 			namelen = strnlen((char *)comp, len);
 			hash = libxfs_da_hashname(comp, namelen);
-			obfuscate_name(0, hash, namelen, comp);
+			obfuscate_name(hash, namelen, comp);
 			break;
 		}
 		namelen = slash - (char *)comp;
@@ -1337,7 +1338,7 @@ obfuscate_path_components(
 			continue;
 		}
 		hash = libxfs_da_hashname(comp, namelen);
-		obfuscate_name(0, hash, namelen, comp);
+		obfuscate_name(hash, namelen, comp);
 		comp += namelen + 1;
 		len -= namelen + 1;
 	}
@@ -1412,16 +1413,11 @@ process_sf_attr(
 			break;
 		}
 
-		if (obfuscate) {
-			if (asfep->flags & XFS_ATTR_PARENT) {
-				generate_obfuscated_name(cur_ino, asfep->valuelen,
-					 &asfep->nameval[asfep->namelen]);
-			} else {
-				generate_obfuscated_name(0, asfep->namelen,
-							 &asfep->nameval[0]);
-				memset(&asfep->nameval[asfep->namelen], 'v',
-				       asfep->valuelen);
-			}
+		if (obfuscate && !(asfep->flags & XFS_ATTR_PARENT)) {
+			generate_obfuscated_name(0, asfep->namelen,
+					&asfep->nameval[0]);
+			memset(&asfep->nameval[asfep->namelen], 'v',
+					asfep->valuelen);
 		}
 
 		asfep = (struct xfs_attr_sf_entry *)((char *)asfep +
@@ -1808,9 +1804,6 @@ process_attr_block(
 			zlen = xfs_attr_leaf_entsize_local(nlen, vlen) -
 				(sizeof(xfs_attr_leaf_name_local_t) - 1 +
 				 nlen + vlen);
-			if (obfuscate && (entry->flags & XFS_ATTR_PARENT))
-				generate_obfuscated_name(cur_ino, vlen,
-						&local->nameval[nlen]);
 			if (zero_stale_data)
 				memset(&local->nameval[nlen + vlen], 0, zlen);
 		} else {
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index ab8bdc1c..a28e604d 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -147,6 +147,8 @@
 #define xfs_parent_add			libxfs_parent_add
 #define xfs_parent_finish		libxfs_parent_finish
 #define xfs_parent_irec_from_disk	libxfs_parent_irec_from_disk
+#define xfs_parent_irec_hash		libxfs_parent_irec_hash
+#define xfs_parent_namehash		libxfs_parent_namehash
 #define xfs_parent_set			libxfs_parent_set
 #define xfs_parent_start		libxfs_parent_start
 #define xfs_parent_unset		libxfs_parent_unset
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index ad21a25d..d5a9fec2 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -56,6 +56,7 @@
 
 #include "xfs_fs.h"
 #include "libfrog/crc32c.h"
+#include "libfrog/sha512.h"
 
 #include <sys/xattr.h>
 
diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h
index c07b8166..386f63b2 100644
--- a/libxfs/xfs_da_format.h
+++ b/libxfs/xfs_da_format.h
@@ -824,17 +824,22 @@ static inline unsigned int xfs_dir2_dirblock_bytes(struct xfs_sb *sbp)
 xfs_failaddr_t xfs_da3_blkinfo_verify(struct xfs_buf *bp,
 				      struct xfs_da3_blkinfo *hdr3);
 
+/* We use sha512 for the parent pointer name hash. */
+#define XFS_PARENT_NAME_HASH_SIZE	(64)
+
 /*
  * Parent pointer attribute format definition
  *
- * EA name encodes the parent inode number, generation and the offset of
- * the dirent that points to the child inode. The EA value contains the
- * same name as the dirent in the parent directory.
+ * The EA name encodes the parent inode number, generation and a collision
+ * resistant hash computed from the dirent name.  The hash is defined to be the
+ * sha512 of the child inode generation and the dirent name.
+ *
+ * The EA value contains the same name as the dirent in the parent directory.
  */
 struct xfs_parent_name_rec {
 	__be64  p_ino;
 	__be32  p_gen;
-	__be32  p_diroffset;
-};
+	__u8	p_namehash[XFS_PARENT_NAME_HASH_SIZE];
+} __attribute__((packed));
 
 #endif /* __XFS_DA_FORMAT_H__ */
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 9e59a1fd..c65345d2 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -770,8 +770,8 @@ struct xfs_scrub_metadata {
 struct xfs_parent_ptr {
 	__u64		xpp_ino;			/* Inode */
 	__u32		xpp_gen;			/* Inode generation */
-	__u32		xpp_diroffset;			/* Directory offset */
-	__u64		xpp_rsvd;			/* Reserved */
+	__u32		xpp_rsvd;			/* Reserved */
+	__u64		xpp_rsvd2;			/* Reserved */
 	__u8		xpp_name[XFS_PPTR_MAXNAMELEN];	/* File name */
 };
 
diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c
index a7c5974c..05c1e032 100644
--- a/libxfs/xfs_parent.c
+++ b/libxfs/xfs_parent.c
@@ -55,7 +55,6 @@ xfs_parent_namecheck(
 	unsigned int				attr_flags)
 {
 	xfs_ino_t				p_ino;
-	xfs_dir2_dataptr_t			p_diroffset;
 
 	if (reclen != sizeof(struct xfs_parent_name_rec))
 		return false;
@@ -68,10 +67,6 @@ xfs_parent_namecheck(
 	if (!xfs_verify_ino(mp, p_ino))
 		return false;
 
-	p_diroffset = be32_to_cpu(rec->p_diroffset);
-	if (p_diroffset > XFS_DIR2_MAX_DATAPTR)
-		return false;
-
 	return true;
 }
 
@@ -92,18 +87,17 @@ xfs_parent_valuecheck(
 }
 
 /* Initializes a xfs_parent_name_rec to be stored as an attribute name */
-static inline void
+static inline int
 xfs_init_parent_name_rec(
 	struct xfs_parent_name_rec	*rec,
-	const struct xfs_inode		*ip,
-	uint32_t			p_diroffset)
+	const struct xfs_inode		*dp,
+	const struct xfs_name		*name,
+	struct xfs_inode		*ip)
 {
-	xfs_ino_t			p_ino = ip->i_ino;
-	uint32_t			p_gen = VFS_IC(ip)->i_generation;
-
-	rec->p_ino = cpu_to_be64(p_ino);
-	rec->p_gen = cpu_to_be32(p_gen);
-	rec->p_diroffset = cpu_to_be32(p_diroffset);
+	rec->p_ino = cpu_to_be64(dp->i_ino);
+	rec->p_gen = cpu_to_be32(VFS_IC(dp)->i_generation);
+	return xfs_parent_namehash(ip, name, rec->p_namehash,
+			sizeof(rec->p_namehash));
 }
 
 /*
@@ -119,7 +113,7 @@ xfs_parent_irec_from_disk(
 {
 	irec->p_ino = be64_to_cpu(rec->p_ino);
 	irec->p_gen = be32_to_cpu(rec->p_gen);
-	irec->p_diroffset = be32_to_cpu(rec->p_diroffset);
+	memcpy(irec->p_namehash, rec->p_namehash, sizeof(irec->p_namehash));
 
 	if (!value) {
 		irec->p_namelen = 0;
@@ -149,7 +143,7 @@ xfs_parent_irec_to_disk(
 {
 	rec->p_ino = cpu_to_be64(irec->p_ino);
 	rec->p_gen = cpu_to_be32(irec->p_gen);
-	rec->p_diroffset = cpu_to_be32(irec->p_diroffset);
+	memcpy(rec->p_namehash, irec->p_namehash, sizeof(rec->p_namehash));
 
 	if (valuelen) {
 		ASSERT(*valuelen > 0);
@@ -209,12 +203,15 @@ xfs_parent_add(
 	struct xfs_parent_defer	*parent,
 	struct xfs_inode	*dp,
 	const struct xfs_name	*parent_name,
-	xfs_dir2_dataptr_t	diroffset,
 	struct xfs_inode	*child)
 {
 	struct xfs_da_args	*args = &parent->args;
+	int			error;
+
+	error = xfs_init_parent_name_rec(&parent->rec, dp, parent_name, child);
+	if (error)
+		return error;
 
-	xfs_init_parent_name_rec(&parent->rec, dp, diroffset);
 	args->hashval = xfs_da_hashname(args->name, args->namelen);
 
 	args->trans = tp;
@@ -231,14 +228,18 @@ xfs_parent_add(
 int
 xfs_parent_remove(
 	struct xfs_trans	*tp,
-	struct xfs_inode	*dp,
 	struct xfs_parent_defer	*parent,
-	xfs_dir2_dataptr_t	diroffset,
+	struct xfs_inode	*dp,
+	const struct xfs_name	*name,
 	struct xfs_inode	*child)
 {
 	struct xfs_da_args	*args = &parent->args;
+	int			error;
+
+	error = xfs_init_parent_name_rec(&parent->rec, dp, name, child);
+	if (error)
+		return error;
 
-	xfs_init_parent_name_rec(&parent->rec, dp, diroffset);
 	args->trans = tp;
 	args->dp = child;
 	args->hashval = xfs_da_hashname(args->name, args->namelen);
@@ -251,16 +252,23 @@ xfs_parent_replace(
 	struct xfs_trans	*tp,
 	struct xfs_parent_defer	*new_parent,
 	struct xfs_inode	*old_dp,
-	xfs_dir2_dataptr_t	old_diroffset,
-	const struct xfs_name	*parent_name,
+	const struct xfs_name	*old_name,
 	struct xfs_inode	*new_dp,
-	xfs_dir2_dataptr_t	new_diroffset,
+	const struct xfs_name	*new_name,
 	struct xfs_inode	*child)
 {
 	struct xfs_da_args	*args = &new_parent->args;
+	int			error;
+
+	error = xfs_init_parent_name_rec(&new_parent->old_rec, old_dp,
+			old_name, child);
+	if (error)
+		return error;
+	error = xfs_init_parent_name_rec(&new_parent->rec, new_dp, new_name,
+			child);
+	if (error)
+		return error;
 
-	xfs_init_parent_name_rec(&new_parent->old_rec, old_dp, old_diroffset);
-	xfs_init_parent_name_rec(&new_parent->rec, new_dp, new_diroffset);
 	new_parent->args.name = (const uint8_t *)&new_parent->old_rec;
 	new_parent->args.namelen = sizeof(struct xfs_parent_name_rec);
 	new_parent->args.new_name = (const uint8_t *)&new_parent->rec;
@@ -268,9 +276,8 @@ xfs_parent_replace(
 	args->trans = tp;
 	args->dp = child;
 
-	ASSERT(parent_name != NULL);
-	new_parent->args.value = (void *)parent_name->name;
-	new_parent->args.valuelen = parent_name->len;
+	new_parent->args.value = (void *)new_name->name;
+	new_parent->args.valuelen = new_name->len;
 
 	args->hashval = xfs_da_hashname(args->name, args->namelen);
 	return xfs_attr_defer_replace(args);
@@ -389,3 +396,62 @@ xfs_parent_unset(
 
 	return xfs_attr_set(&scr->args);
 }
+
+/*
+ * Compute the parent pointer namehash for the given child file and dirent
+ * name.
+ */
+int
+xfs_parent_namehash(
+	struct xfs_inode	*ip,
+	const struct xfs_name	*name,
+	void			*namehash,
+	unsigned int		namehash_len)
+{
+	SHA512_DESC_ON_STACK(ip->i_mount, shash);
+	__be32			gen = cpu_to_be32(VFS_I(ip)->i_generation);
+	int			error;
+
+	ASSERT(SHA512_DIGEST_SIZE ==
+			crypto_shash_digestsize(ip->i_mount->m_sha512));
+
+	if (namehash_len != SHA512_DIGEST_SIZE) {
+		ASSERT(0);
+		return -EINVAL;
+	}
+
+	error = sha512_init(&shash);
+	if (error)
+		goto out;
+
+	error = sha512_process(&shash, (const u8 *)&gen, sizeof(gen));
+	if (error)
+		goto out;
+
+	error = sha512_process(&shash, name->name, name->len);
+	if (error)
+		goto out;
+
+	error = sha512_done(&shash, namehash);
+	if (error)
+		goto out;
+
+out:
+	sha512_erase(&shash);
+	return error;
+}
+
+/* Recalculate the name hash of this parent pointer. */
+int
+xfs_parent_irec_hash(
+	struct xfs_inode		*ip,
+	struct xfs_parent_name_irec	*pptr)
+{
+	struct xfs_name			xname = {
+		.name			= pptr->p_name,
+		.len			= pptr->p_namelen,
+	};
+
+	return xfs_parent_namehash(ip, &xname, &pptr->p_namehash,
+			sizeof(pptr->p_namehash));
+}
diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h
index a7fc621b..d3f2841e 100644
--- a/libxfs/xfs_parent.h
+++ b/libxfs/xfs_parent.h
@@ -23,7 +23,7 @@ struct xfs_parent_name_irec {
 	/* Key fields for looking up a particular parent pointer. */
 	xfs_ino_t		p_ino;
 	uint32_t		p_gen;
-	xfs_dir2_dataptr_t	p_diroffset;
+	uint8_t			p_namehash[XFS_PARENT_NAME_HASH_SIZE];
 
 	/* Attributes of a parent pointer. */
 	uint8_t			p_namelen;
@@ -79,15 +79,14 @@ xfs_parent_start_locked(
 
 int xfs_parent_add(struct xfs_trans *tp, struct xfs_parent_defer *parent,
 		struct xfs_inode *dp, const struct xfs_name *parent_name,
-		xfs_dir2_dataptr_t diroffset, struct xfs_inode *child);
+		struct xfs_inode *child);
 int xfs_parent_replace(struct xfs_trans *tp,
 		struct xfs_parent_defer *new_parent, struct xfs_inode *old_dp,
-		xfs_dir2_dataptr_t old_diroffset,
-		const struct xfs_name *parent_name, struct xfs_inode *new_ip,
-		xfs_dir2_dataptr_t new_diroffset, struct xfs_inode *child);
-int xfs_parent_remove(struct xfs_trans *tp, struct xfs_inode *dp,
-		struct xfs_parent_defer *parent, xfs_dir2_dataptr_t diroffset,
-		struct xfs_inode *child);
+		const struct xfs_name *old_name, struct xfs_inode *new_ip,
+		const struct xfs_name *new_name, struct xfs_inode *child);
+int xfs_parent_remove(struct xfs_trans *tp,
+		struct xfs_parent_defer *parent, struct xfs_inode *dp,
+		const struct xfs_name *name, struct xfs_inode *child);
 
 void __xfs_parent_cancel(struct xfs_mount *mp, struct xfs_parent_defer *parent);
 
@@ -100,6 +99,12 @@ xfs_parent_finish(
 		__xfs_parent_cancel(mp, p);
 }
 
+int xfs_parent_namehash(struct xfs_inode *ip, const struct xfs_name *name,
+		void *namehash, unsigned int namehash_len);
+
+int xfs_parent_irec_hash(struct xfs_inode *ip,
+		struct xfs_parent_name_irec *pptr);
+
 unsigned int xfs_pptr_calc_space_res(struct xfs_mount *mp,
 				     unsigned int namelen);
 
diff --git a/logprint/log_redo.c b/logprint/log_redo.c
index f7e9c9ad..1ac0536a 100644
--- a/logprint/log_redo.c
+++ b/logprint/log_redo.c
@@ -805,9 +805,8 @@ xlog_print_trans_attri_name(
 	}
 	memmove((char*)src_f, *ptr, src_len);
 
-	printf(_("ATTRI:  #p_ino: %llu	p_gen: %u, p_diroffset: %u\n"),
-		be64_to_cpu(src_f->p_ino), be32_to_cpu(src_f->p_gen),
-				be32_to_cpu(src_f->p_diroffset));
+	printf(_("ATTRI:  #p_ino: %llu	p_gen: %u\n"),
+		be64_to_cpu(src_f->p_ino), be32_to_cpu(src_f->p_gen));
 
 	free(src_f);
 out:
@@ -898,9 +897,8 @@ xlog_recover_print_attri(
 				goto out;
 			}
 
-			printf(_("ATTRI:  #inode: %llu     gen: %u, offset: %u\n"),
-				be64_to_cpu(rec->p_ino), be32_to_cpu(rec->p_gen),
-				be32_to_cpu(rec->p_diroffset));
+			printf(_("ATTRI:  #inode: %llu     gen: %u\n"),
+				be64_to_cpu(rec->p_ino), be32_to_cpu(rec->p_gen));
 
 			free(rec);
 		}
@@ -929,9 +927,8 @@ xlog_recover_print_attri(
 				goto out;
 			}
 
-			printf(_("ATTRI:  new #inode: %llu     gen: %u, offset: %u\n"),
-				be64_to_cpu(rec->p_ino), be32_to_cpu(rec->p_gen),
-				be32_to_cpu(rec->p_diroffset));
+			printf(_("ATTRI:  new #inode: %llu     gen: %u\n"),
+				be64_to_cpu(rec->p_ino), be32_to_cpu(rec->p_gen));
 
 			free(rec);
 		}
diff --git a/man/man3/xfsctl.3 b/man/man3/xfsctl.3
index 7cc97499..42ba3bba 100644
--- a/man/man3/xfsctl.3
+++ b/man/man3/xfsctl.3
@@ -367,7 +367,6 @@ int main() {
 			p = xfs_ppinfo_to_pp(pi, i);
 			printf("inode		= %llu\\n", (unsigned long long)p->xpp_ino);
 			printf("generation	= %u\\n", (unsigned int)p->xpp_gen);
-			printf("diroffset	= %u\\n", (unsigned int)p->xpp_diroffset);
 			printf("name		= \\"%s\\"\\n\\n", (char *)p->xpp_name);
 		}
 	} while (!pi->pi_flags & XFS_PPTR_OFLAG_DONE);
diff --git a/mkfs/proto.c b/mkfs/proto.c
index b8d7ac96..445fbefb 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -509,7 +509,7 @@ parseproto(
 		libxfs_trans_log_inode(tp, ip, flags);
 		if (parent) {
 			error = -libxfs_parent_add(tp, parent, pip, &xname,
-					offset, ip);
+					ip);
 			if (error)
 				fail(_("committing parent pointers failed."),
 						error);
@@ -602,7 +602,7 @@ parseproto(
 		libxfs_trans_log_inode(tp, ip, flags);
 		if (parent) {
 			error = -libxfs_parent_add(tp, parent, pip, &xname,
-					offset, ip);
+					ip);
 			if (error)
 				fail(_("committing parent pointers failed."),
 						error);
@@ -636,8 +636,7 @@ parseproto(
 	}
 	libxfs_trans_log_inode(tp, ip, flags);
 	if (parent) {
-		error = -libxfs_parent_add(tp, parent, pip, &xname, offset,
-				ip);
+		error = -libxfs_parent_add(tp, parent, pip, &xname, ip);
 		if (error)
 			fail(_("committing parent pointers failed."), error);
 	}
diff --git a/repair/phase6.c b/repair/phase6.c
index 1994162a..3fb11df9 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -68,7 +68,6 @@ struct dir_hash_ent {
 	struct dir_hash_ent	*nextbyorder;	/* next in order added */
 	xfs_dahash_t		hashval;	/* hash value of name */
 	uint32_t		address;	/* offset of data entry */
-	uint32_t		new_address;	/* new address, if we rebuild */
 	xfs_ino_t		inum;		/* inode num of entry */
 	short			junkit;		/* name starts with / */
 	short			seen;		/* have seen leaf entry */
@@ -226,7 +225,6 @@ dir_hash_add(
 	p->address = addr;
 	p->inum = inum;
 	p->seen = 0;
-	p->new_address = addr;
 
 	/* Set up the name in the region trailing the hash entry. */
 	memcpy(p->namebuf, name, namelen);
@@ -979,7 +977,7 @@ mk_orphanage(xfs_mount_t *mp)
 		do_error(
 		_("can't make %s, createname error %d\n"),
 			ORPHANAGE, error);
-	add_parent_ptr(ip->i_ino, ORPHANAGE, diroffset, pip);
+	add_parent_ptr(ip->i_ino, ORPHANAGE, pip);
 
 	/*
 	 * bump up the link count in the root directory to account
@@ -1169,8 +1167,7 @@ mv_orphanage(
 	}
 
 	if (xfs_has_parent(mp))
-		add_parent_ptr(ino_p->i_ino, xname.name, diroffset,
-				orphanage_ip);
+		add_parent_ptr(ino_p->i_ino, xname.name, orphanage_ip);
 
 	libxfs_irele(ino_p);
 	libxfs_irele(orphanage_ip);
@@ -1341,8 +1338,8 @@ longform_dir2_rebuild(
 
 		libxfs_trans_ijoin(tp, ip, 0);
 
-		error = -libxfs_dir_createname(tp, ip, &p->name, p->inum,
-						nres, &p->new_address);
+		error = -libxfs_dir_createname(tp, ip, &p->name, p->inum, nres,
+				NULL);
 		if (error) {
 			do_warn(
 _("name create failed in ino %" PRIu64 " (%d)\n"), ino, error);
@@ -2819,7 +2816,7 @@ dir_hash_add_parent_ptrs(
 						p->name.name[1] == '.'))))
 			continue;
 
-		add_parent_ptr(p->inum, p->name.name, p->new_address, dp);
+		add_parent_ptr(p->inum, p->name.name, dp);
 	}
 }
 
diff --git a/repair/pptr.c b/repair/pptr.c
index a5cf89b9..ca5fe7e3 100644
--- a/repair/pptr.c
+++ b/repair/pptr.c
@@ -119,9 +119,6 @@ struct ag_pptr {
 	xfs_ino_t		parent_ino;
 	unsigned int		parent_gen;
 
-	/* dirent offset */
-	xfs_dir2_dataptr_t	diroffset;
-
 	/* dirent name length */
 	unsigned int		namelen;
 
@@ -140,9 +137,6 @@ struct file_pptr {
 	unsigned long long	parent_ino:63;
 	unsigned int		parent_gen;
 
-	/* dirent offset */
-	xfs_dir2_dataptr_t	diroffset;
-
 	/* parent pointer name length */
 	unsigned int		namelen;
 
@@ -220,9 +214,9 @@ cmp_ag_pptr(
 	if (pa->parent_ino > pb->parent_ino)
 		return 1;
 
-	if (pa->diroffset < pb->diroffset)
+	if (pa->name_cookie < pb->name_cookie)
 		return -1;
-	if (pa->diroffset > pb->diroffset)
+	if (pa->name_cookie > pb->name_cookie)
 		return 1;
 
 	return 0;
@@ -241,9 +235,18 @@ cmp_file_pptr(
 	if (pa->parent_ino > pb->parent_ino)
 		return 1;
 
-	if (pa->diroffset < pb->diroffset)
+	/*
+	 * Push the parent pointer names that we didn't find in the dirent scan
+	 * towards the front of the list so that we delete them first.
+	 */
+	if (!pa->name_in_nameblobs && pb->name_in_nameblobs)
 		return -1;
-	if (pa->diroffset > pb->diroffset)
+	if (pa->name_in_nameblobs && !pb->name_in_nameblobs)
+		return 1;
+
+	if (pa->name_cookie < pb->name_cookie)
+		return -1;
+	if (pa->name_cookie > pb->name_cookie)
 		return 1;
 
 	return 0;
@@ -308,12 +311,11 @@ parent_ptr_init(
 	}
 }
 
-/* Remember that @dp has a dirent (@fname, @ino) at @diroffset. */
+/* Remember that @dp has a dirent (@fname, @ino). */
 void
 add_parent_ptr(
 	xfs_ino_t		ino,
 	const unsigned char	*fname,
-	xfs_dir2_dataptr_t	diroffset,
 	struct xfs_inode	*dp)
 {
 	struct xfs_mount	*mp = dp->i_mount;
@@ -321,7 +323,6 @@ add_parent_ptr(
 		.child_agino	= XFS_INO_TO_AGINO(mp, ino),
 		.parent_ino	= dp->i_ino,
 		.parent_gen	= VFS_I(dp)->i_generation,
-		.diroffset	= diroffset,
 		.namelen	= strlen(fname),
 	};
 	struct ag_pptrs		*ag_pptrs;
@@ -348,9 +349,9 @@ add_parent_ptr(
 				fname, strerror(error));
 
 	dbg_printf(
- _("%s: dp %llu fname '%s' diroffset %u ino %llu cookie 0x%llx\n"),
+ _("%s: dp %llu fname '%s' ino %llu cookie 0x%llx\n"),
 			__func__, (unsigned long long)dp->i_ino, fname,
-			diroffset, (unsigned long long)ino,
+			(unsigned long long)ino,
 			(unsigned long long)ag_pptr.name_cookie);
 }
 
@@ -509,6 +510,8 @@ examine_xattr(
 {
 	struct file_pptr	file_pptr = { };
 	struct xfs_parent_name_irec irec;
+	struct xfs_name		xname;
+	uint8_t			namehash[XFS_PARENT_NAME_HASH_SIZE];
 	struct xfs_mount	*mp = ip->i_mount;
 	struct file_scan	*fscan = priv;
 	const struct xfs_parent_name_rec *rec = (const void *)name;
@@ -531,9 +534,23 @@ examine_xattr(
 
 	file_pptr.parent_ino = irec.p_ino;
 	file_pptr.parent_gen = irec.p_gen;
-	file_pptr.diroffset = irec.p_diroffset;
 	file_pptr.namelen = irec.p_namelen;
 
+	xname.name = irec.p_name;
+	xname.len = irec.p_namelen;
+
+	/*
+	 * Does the namehash in the attr key match the name in the attr value?
+	 * If not, there's no point in checking further.
+	 */
+	error = -libxfs_parent_namehash(ip, &xname, namehash,
+			sizeof(namehash));
+	if (error)
+		goto corrupt;
+
+	if (memcmp(irec.p_namehash, namehash, sizeof(irec.p_namehash)))
+		goto corrupt;
+
 	error = store_file_pptr_name(fscan, &file_pptr, &irec);
 	if (error)
 		do_error(
@@ -547,10 +564,10 @@ examine_xattr(
 				(unsigned long long)ip->i_ino, strerror(error));
 
 	dbg_printf(
- _("%s: dp %llu fname '%.*s' namelen %u diroffset %u ino %llu cookie 0x%llx\n"),
+ _("%s: dp %llu fname '%.*s' namelen %u ino %llu cookie 0x%llx\n"),
 			__func__, (unsigned long long)irec.p_ino,
 			irec.p_namelen, (const char *)irec.p_name,
-			irec.p_namelen, irec.p_diroffset,
+			irec.p_namelen,
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)file_pptr.name_cookie);
 	fscan->nr_file_pptrs++;
@@ -570,13 +587,17 @@ add_file_pptr(
 	struct xfs_parent_name_irec	pptr_rec = {
 		.p_ino			= ag_pptr->parent_ino,
 		.p_gen			= ag_pptr->parent_gen,
-		.p_diroffset		= ag_pptr->diroffset,
 		.p_namelen		= ag_pptr->namelen,
 	};
 	struct xfs_parent_scratch	scratch;
+	int				error;
 
 	memcpy(pptr_rec.p_name, name, ag_pptr->namelen);
 
+	error = -libxfs_parent_irec_hash(ip, &pptr_rec);
+	if (error)
+		return error;
+
 	return -libxfs_parent_set(ip, &pptr_rec, &scratch);
 }
 
@@ -584,14 +605,22 @@ add_file_pptr(
 static int
 remove_file_pptr(
 	struct xfs_inode		*ip,
-	const struct file_pptr		*file_pptr)
+	const struct file_pptr		*file_pptr,
+	const unsigned char		*name)
 {
 	struct xfs_parent_name_irec	pptr_rec = {
 		.p_ino			= file_pptr->parent_ino,
 		.p_gen			= file_pptr->parent_gen,
-		.p_diroffset		= file_pptr->diroffset,
+		.p_namelen		= file_pptr->namelen,
 	};
 	struct xfs_parent_scratch	scratch;
+	int				error;
+
+	memcpy(pptr_rec.p_name, name, file_pptr->namelen);
+
+	error = -libxfs_parent_irec_hash(ip, &pptr_rec);
+	if (error)
+		return error;
 
 	return -libxfs_parent_unset(ip, &pptr_rec, &scratch);
 }
@@ -637,13 +666,25 @@ clear_all_pptrs(
 				strerror(error));
 
 	while ((file_pptr = pop_slab_cursor(cur)) != NULL) {
-		error = remove_file_pptr(ip, file_pptr);
+		unsigned char	name[MAXNAMELEN];
+
+		error = load_file_pptr_name(fscan, file_pptr, name);
 		if (error)
 			do_error(
- _("wiping ino %llu pptr (ino %llu gen 0x%x diroffset %u) failed: %s\n"),
+  _("loading incorrect name for ino %llu parent pointer (ino %llu gen 0x%x namecookie 0x%llx) failed: %s\n"),
+					(unsigned long long)ip->i_ino,
+					(unsigned long long)file_pptr->parent_ino,
+					file_pptr->parent_gen,
+					(unsigned long long)file_pptr->name_cookie,
+					strerror(error));
+
+		error = remove_file_pptr(ip, file_pptr, name);
+		if (error)
+			do_error(
+ _("wiping ino %llu pptr (ino %llu gen 0x%x) failed: %s\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)file_pptr->parent_ino,
-				file_pptr->parent_gen, file_pptr->diroffset,
+				file_pptr->parent_gen,
 				strerror(error));
 	}
 
@@ -664,37 +705,37 @@ add_missing_parent_ptr(
 			ag_pptr->namelen);
 	if (error)
 		do_error(
- _("loading missing name for ino %llu parent pointer (ino %llu gen 0x%x diroffset %u namecookie 0x%llx) failed: %s\n"),
+ _("loading missing name for ino %llu parent pointer (ino %llu gen 0x%x namecookie 0x%llx) failed: %s\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)ag_pptr->parent_ino,
-				ag_pptr->parent_gen, ag_pptr->diroffset,
+				ag_pptr->parent_gen,
 				(unsigned long long)ag_pptr->name_cookie,
 				strerror(error));
 
 	if (no_modify) {
 		do_warn(
- _("would add missing ino %llu parent pointer (ino %llu gen 0x%x diroffset %u name '%.*s')\n"),
+ _("would add missing ino %llu parent pointer (ino %llu gen 0x%x name '%.*s')\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)ag_pptr->parent_ino,
-				ag_pptr->parent_gen, ag_pptr->diroffset,
+				ag_pptr->parent_gen,
 				ag_pptr->namelen, name);
 		return;
 	}
 
 	do_warn(
- _("adding missing ino %llu parent pointer (ino %llu gen 0x%x diroffset %u name '%.*s')\n"),
+ _("adding missing ino %llu parent pointer (ino %llu gen 0x%x name '%.*s')\n"),
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)ag_pptr->parent_ino,
-			ag_pptr->parent_gen, ag_pptr->diroffset,
+			ag_pptr->parent_gen,
 			ag_pptr->namelen, name);
 
 	error = add_file_pptr(ip, ag_pptr, name);
 	if (error)
 		do_error(
- _("adding ino %llu pptr (ino %llu gen 0x%x diroffset %u name '%.*s') failed: %s\n"),
+ _("adding ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)ag_pptr->parent_ino,
-			ag_pptr->parent_gen, ag_pptr->diroffset,
+			ag_pptr->parent_gen,
 			ag_pptr->namelen, name, strerror(error));
 }
 
@@ -711,37 +752,37 @@ remove_incorrect_parent_ptr(
 	error = load_file_pptr_name(fscan, file_pptr, name);
 	if (error)
 		do_error(
- _("loading incorrect name for ino %llu parent pointer (ino %llu gen 0x%x diroffset %u namecookie 0x%llx) failed: %s\n"),
+ _("loading incorrect name for ino %llu parent pointer (ino %llu gen 0x%x namecookie 0x%llx) failed: %s\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)file_pptr->parent_ino,
-				file_pptr->parent_gen, file_pptr->diroffset,
+				file_pptr->parent_gen,
 				(unsigned long long)file_pptr->name_cookie,
 				strerror(error));
 
 	if (no_modify) {
 		do_warn(
- _("would remove bad ino %llu parent pointer (ino %llu gen 0x%x diroffset %u name '%.*s')\n"),
+ _("would remove bad ino %llu parent pointer (ino %llu gen 0x%x name '%.*s')\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)file_pptr->parent_ino,
-				file_pptr->parent_gen, file_pptr->diroffset,
+				file_pptr->parent_gen,
 				file_pptr->namelen, name);
 		return;
 	}
 
 	do_warn(
- _("removing bad ino %llu parent pointer (ino %llu gen 0x%x diroffset %u name '%.*s')\n"),
+ _("removing bad ino %llu parent pointer (ino %llu gen 0x%x name '%.*s')\n"),
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)file_pptr->parent_ino,
-			file_pptr->parent_gen, file_pptr->diroffset,
+			file_pptr->parent_gen,
 			file_pptr->namelen, name);
 
-	error = remove_file_pptr(ip, file_pptr);
+	error = remove_file_pptr(ip, file_pptr, name);
 	if (error)
 		do_error(
- _("removing ino %llu pptr (ino %llu gen 0x%x diroffset %u name '%.*s') failed: %s\n"),
+ _("removing ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)file_pptr->parent_ino,
-			file_pptr->parent_gen, file_pptr->diroffset,
+			file_pptr->parent_gen,
 			file_pptr->namelen, name, strerror(error));
 }
 
@@ -764,20 +805,20 @@ compare_parent_pointers(
 			ag_pptr->namelen);
 	if (error)
 		do_error(
- _("loading master-list name for ino %llu parent pointer (ino %llu gen 0x%x diroffset %u namecookie 0x%llx namelen %u) failed: %s\n"),
+ _("loading master-list name for ino %llu parent pointer (ino %llu gen 0x%x  namecookie 0x%llx namelen %u) failed: %s\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)ag_pptr->parent_ino,
-				ag_pptr->parent_gen, ag_pptr->diroffset,
+				ag_pptr->parent_gen,
 				(unsigned long long)ag_pptr->name_cookie,
 				ag_pptr->namelen, strerror(error));
 
 	error = load_file_pptr_name(fscan, file_pptr, name2);
 	if (error)
 		do_error(
- _("loading file-list name for ino %llu parent pointer (ino %llu gen 0x%x diroffset %u namecookie 0x%llx namelen %u) failed: %s\n"),
+ _("loading file-list name for ino %llu parent pointer (ino %llu gen 0x%x namecookie 0x%llx namelen %u) failed: %s\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)file_pptr->parent_ino,
-				file_pptr->parent_gen, file_pptr->diroffset,
+				file_pptr->parent_gen,
 				(unsigned long long)file_pptr->name_cookie,
 				ag_pptr->namelen, strerror(error));
 
@@ -793,42 +834,67 @@ compare_parent_pointers(
 reset:
 	if (no_modify) {
 		do_warn(
- _("would update ino %llu parent pointer (ino %llu gen 0x%x diroffset %u name '%.*s')\n"),
+ _("would update ino %llu parent pointer (ino %llu gen 0x%x name '%.*s')\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)ag_pptr->parent_ino,
-				ag_pptr->parent_gen, ag_pptr->diroffset,
+				ag_pptr->parent_gen,
 				ag_pptr->namelen, name1);
 		return;
 	}
 
 	do_warn(
- _("updating ino %llu parent pointer (ino %llu gen 0x%x diroffset %u name '%.*s')\n"),
+ _("updating ino %llu parent pointer (ino %llu gen 0x%x name '%.*s')\n"),
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)ag_pptr->parent_ino,
-			ag_pptr->parent_gen, ag_pptr->diroffset,
+			ag_pptr->parent_gen,
 			ag_pptr->namelen, name1);
 
 	if (ag_pptr->parent_gen != file_pptr->parent_gen) {
-		error = remove_file_pptr(ip, file_pptr);
+		error = remove_file_pptr(ip, file_pptr, name2);
 		if (error)
 			do_error(
- _("erasing ino %llu pptr (ino %llu gen 0x%x diroffset %u name '%.*s') failed: %s\n"),
+ _("erasing ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)file_pptr->parent_ino,
-				file_pptr->parent_gen, file_pptr->diroffset,
+				file_pptr->parent_gen,
 				file_pptr->namelen, name2, strerror(error));
 	}
 
 	error = add_file_pptr(ip, ag_pptr, name1);
 	if (error)
 		do_error(
- _("updating ino %llu pptr (ino %llu gen 0x%x diroffset %u name '%.*s') failed: %s\n"),
+ _("updating ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"),
 			(unsigned long long)ip->i_ino,
 			(unsigned long long)ag_pptr->parent_ino,
-			ag_pptr->parent_gen, ag_pptr->diroffset,
+			ag_pptr->parent_gen,
 			ag_pptr->namelen, name1, strerror(error));
 }
 
+static int
+cmp_file_to_ag_pptr(
+	const struct file_pptr	*fp,
+	const struct ag_pptr	*ap)
+{
+	if (fp->parent_ino > ap->parent_ino)
+		return 1;
+	if (fp->parent_ino < ap->parent_ino)
+		return -1;
+
+	/*
+	 * If this parent pointer wasn't found in the dirent scan, we know it
+	 * should be removed.
+	 */
+	if (!fp->name_in_nameblobs)
+		return -1;
+
+	if (fp->name_cookie < ap->name_cookie)
+		return -1;
+	if (fp->name_cookie > ap->name_cookie)
+		return 1;
+
+	return 0;
+}
+
 /*
  * Make sure that the parent pointers we observed match the ones ondisk.
  *
@@ -894,26 +960,26 @@ crosscheck_file_parent_ptrs(
 				(unsigned long long)ip->i_ino, strerror(error));
 
 	do {
+		int	cmp_result;
+
 		file_pptr = peek_slab_cursor(fscan->file_pptr_recs_cur);
 
 		dbg_printf(
- _("%s: dp %llu dp_gen 0x%x namelen %u diroffset %u ino %llu namecookie 0x%llx (master)\n"),
+ _("%s: dp %llu dp_gen 0x%x namelen %u ino %llu namecookie 0x%llx (master)\n"),
 				__func__,
 				(unsigned long long)ag_pptr->parent_ino,
 				ag_pptr->parent_gen,
 				ag_pptr->namelen,
-				ag_pptr->diroffset,
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)ag_pptr->name_cookie);
 
 		if (file_pptr) {
 			dbg_printf(
- _("%s: dp %llu dp_gen 0x%x namelen %u diroffset %u ino %llu namecookie 0x%llx (file)\n"),
+ _("%s: dp %llu dp_gen 0x%x namelen %u ino %llu namecookie 0x%llx (file)\n"),
 					__func__,
 					(unsigned long long)file_pptr->parent_ino,
 					file_pptr->parent_gen,
 					file_pptr->namelen,
-					file_pptr->diroffset,
 					(unsigned long long)ip->i_ino,
 					(unsigned long long)file_pptr->name_cookie);
 		} else {
@@ -923,9 +989,8 @@ crosscheck_file_parent_ptrs(
 					(unsigned long long)ip->i_ino);
 		}
 
-		if (!file_pptr ||
-		    file_pptr->parent_ino > ag_pptr->parent_ino ||
-		    file_pptr->diroffset > ag_pptr->diroffset) {
+		cmp_result = file_pptr ? cmp_file_to_ag_pptr(file_pptr, ag_pptr) : 1;
+		if (cmp_result > 0) {
 			/*
 			 * The master pptr list knows about pptrs that are not
 			 * in the ondisk metadata.  Add the missing pptr and
@@ -933,8 +998,7 @@ crosscheck_file_parent_ptrs(
 			 */
 			add_missing_parent_ptr(ip, fscan, ag_pptr);
 			advance_slab_cursor(fscan->ag_pptr_recs_cur);
-		} else if (file_pptr->parent_ino < ag_pptr->parent_ino ||
-			   file_pptr->diroffset < ag_pptr->diroffset) {
+		} else if (cmp_result < 0) {
 			/*
 			 * The ondisk pptrs mention a link that is not in the
 			 * master list.  Delete the extra pptr and advance only
@@ -958,12 +1022,11 @@ crosscheck_file_parent_ptrs(
 
 	while ((file_pptr = pop_slab_cursor(fscan->file_pptr_recs_cur))) {
 		dbg_printf(
- _("%s: dp %llu dp_gen 0x%x namelen %u diroffset %u ino %llu namecookie 0x%llx (excess)\n"),
+ _("%s: dp %llu dp_gen 0x%x namelen %u ino %llu namecookie 0x%llx (excess)\n"),
 				__func__,
 				(unsigned long long)file_pptr->parent_ino,
 				file_pptr->parent_gen,
 				file_pptr->namelen,
-				file_pptr->diroffset,
 				(unsigned long long)ip->i_ino,
 				(unsigned long long)file_pptr->name_cookie);
 
diff --git a/repair/pptr.h b/repair/pptr.h
index d72c1ac2..1cf3444c 100644
--- a/repair/pptr.h
+++ b/repair/pptr.h
@@ -10,7 +10,7 @@ void parent_ptr_free(struct xfs_mount *mp);
 void parent_ptr_init(struct xfs_mount *mp);
 
 void add_parent_ptr(xfs_ino_t ino, const unsigned char *fname,
-		xfs_dir2_dataptr_t diroffset, struct xfs_inode *dp);
+		struct xfs_inode *dp);
 
 void check_parent_ptrs(struct xfs_mount *mp);
 




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux