[PATCH 03/23] xfs: create a parent pointer walk function for scrubbers

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

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Build a parent pointer iteration function off of the existing xattr
walking code.  This will be used by subsequent patches.

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
---
 fs/xfs/scrub/listxattr.c |   84 +++++++++++++++++++++++++++++++++++++++++++---
 fs/xfs/scrub/listxattr.h |    9 +++++
 2 files changed, 88 insertions(+), 5 deletions(-)


diff --git a/fs/xfs/scrub/listxattr.c b/fs/xfs/scrub/listxattr.c
index 40a686901bcdc..afae7352c1e06 100644
--- a/fs/xfs/scrub/listxattr.c
+++ b/fs/xfs/scrub/listxattr.c
@@ -17,11 +17,46 @@
 #include "xfs_attr_leaf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_trans.h"
+#include "xfs_parent.h"
 #include "scrub/scrub.h"
 #include "scrub/bitmap.h"
 #include "scrub/dab_bitmap.h"
 #include "scrub/listxattr.h"
 
+struct xchk_pptr_walk {
+	struct xfs_parent_name_irec	*pptr_buf;
+	xchk_pptr_fn			fn;
+	void				*priv;
+};
+
+/* Call the parent pointer callback if this xattr is a valid parent pointer. */
+STATIC int
+xchk_pptr_walk_attr(
+	struct xfs_scrub	*sc,
+	struct xfs_inode	*ip,
+	unsigned int		attr_flags,
+	const unsigned char	*name,
+	unsigned int		namelen,
+	const void		*value,
+	unsigned int		valuelen,
+	void			*priv)
+{
+	struct xchk_pptr_walk	*pw = priv;
+	const struct xfs_parent_name_rec *rec = (const void *)name;
+
+	/* Ignore anything that isn't a parent pointer. */
+	if (!(attr_flags & XFS_ATTR_PARENT))
+		return 0;
+
+	if (!xfs_parent_namecheck(sc->mp, rec, namelen, attr_flags))
+		return -EFSCORRUPTED;
+	if (!xfs_parent_valuecheck(sc->mp, value, valuelen))
+		return -EFSCORRUPTED;
+
+	xfs_parent_irec_from_disk(pw->pptr_buf, rec, value, valuelen);
+	return pw->fn(sc, ip, pw->pptr_buf, pw->priv);
+}
+
 /* Call a function for every entry in a shortform xattr structure. */
 STATIC int
 xchk_xattr_walk_sf(
@@ -37,9 +72,16 @@ xchk_xattr_walk_sf(
 
 	sfe = xfs_attr_sf_firstentry(hdr);
 	for (i = 0; i < hdr->count; i++) {
-		error = attr_fn(sc, ip, sfe->flags, sfe->nameval, sfe->namelen,
-				&sfe->nameval[sfe->namelen], sfe->valuelen,
-				priv);
+		if (attr_fn == xchk_pptr_walk_attr)
+			error = xchk_pptr_walk_attr(sc, ip, sfe->flags,
+					sfe->nameval, sfe->namelen,
+					&sfe->nameval[sfe->namelen],
+					sfe->valuelen, priv);
+		else
+			error = attr_fn(sc, ip, sfe->flags,
+					sfe->nameval, sfe->namelen,
+					&sfe->nameval[sfe->namelen],
+					sfe->valuelen, priv);
 		if (error)
 			return error;
 
@@ -91,8 +133,12 @@ xchk_xattr_walk_leaf_entries(
 			valuelen = be32_to_cpu(name_rmt->valuelen);
 		}
 
-		error = attr_fn(sc, ip, entry->flags, name, namelen, value,
-				valuelen, priv);
+		if (attr_fn == xchk_pptr_walk_attr)
+			error = xchk_pptr_walk_attr(sc, ip, entry->flags, name,
+					namelen, value, valuelen, priv);
+		else
+			error = attr_fn(sc, ip, entry->flags, name, namelen,
+					value, valuelen, priv);
 		if (error)
 			return error;
 
@@ -310,3 +356,31 @@ xchk_xattr_walk(
 
 	return xchk_xattr_walk_node(sc, ip, attr_fn, priv);
 }
+
+/*
+ * Walk every parent pointer of this file.  The parent pointer will be
+ * formatted into the provided @pptr_buf, which is then passed to the callback
+ * function.
+ *
+ * The callback function must decide if an invalid parent_ino or invalid name
+ * should halt the parent pointer walk; the only validation done here is the
+ * structure of the xattrs themselves.
+ */
+int
+xchk_pptr_walk(
+	struct xfs_scrub		*sc,
+	struct xfs_inode		*ip,
+	xchk_pptr_fn			pptr_fn,
+	struct xfs_parent_name_irec	*pptr_buf,
+	void				*priv)
+{
+	struct xchk_pptr_walk		pw = {
+		.fn			= pptr_fn,
+		.pptr_buf		= pptr_buf,
+		.priv			= priv,
+	};
+
+	ASSERT(xfs_has_parent(sc->mp));
+
+	return xchk_xattr_walk(sc, ip, xchk_pptr_walk_attr, &pw);
+}
diff --git a/fs/xfs/scrub/listxattr.h b/fs/xfs/scrub/listxattr.h
index 48fe89d05946b..7e4bd3ae75e15 100644
--- a/fs/xfs/scrub/listxattr.h
+++ b/fs/xfs/scrub/listxattr.h
@@ -14,4 +14,13 @@ typedef int (*xchk_xattr_fn)(struct xfs_scrub *sc, struct xfs_inode *ip,
 int xchk_xattr_walk(struct xfs_scrub *sc, struct xfs_inode *ip,
 		xchk_xattr_fn attr_fn, void *priv);
 
+struct xfs_parent_name_irec;
+
+typedef int (*xchk_pptr_fn)(struct xfs_scrub *sc, struct xfs_inode *ip,
+		const struct xfs_parent_name_irec *pptr, void *priv);
+
+int xchk_pptr_walk(struct xfs_scrub *sc, struct xfs_inode *ip,
+		xchk_pptr_fn pptr_fn, struct xfs_parent_name_irec *pptr_buf,
+		void *priv);
+
 #endif /* __XFS_SCRUB_LISTXATTR_H__ */





[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