diff mbox series

[09/14] xfs: add interface to set CRC on leaf attributes

Message ID 20241229133836.1194272-10-aalbersh@kernel.org (mailing list archive)
State New
Headers show
Series Direct mapped extended attribute data | expand

Commit Message

Andrey Albershteyn Dec. 29, 2024, 1:38 p.m. UTC
With attributes' data passed through page cache we need to update
CRC when IO is complete. This function calculates CRC of newly
written data and swaps CRC with a new one (the old one is still in
there).

Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
 fs/xfs/libxfs/xfs_attr_leaf.c | 50 +++++++++++++++++++++++++++++++++++
 fs/xfs/libxfs/xfs_attr_leaf.h |  1 +
 fs/xfs/xfs_trace.h            |  1 +
 3 files changed, 52 insertions(+)
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index c657638efe04..409c91827b47 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -3035,3 +3035,53 @@  xfs_attr3_leaf_flipflags(
 
 	return 0;
 }
+
+/*
+ * Set CRC field of remote attribute
+ */
+int
+xfs_attr3_leaf_setcrc(
+	struct xfs_da_args			*args)
+{
+	struct xfs_attr_leafblock		*leaf;
+	struct xfs_attr_leaf_entry		*entry;
+	struct xfs_attr_leaf_name_remote	*name_rmt;
+	struct xfs_buf				*bp;
+	struct xfs_mount			*mp = args->dp->i_mount;
+	int					error;
+	unsigned int				whichcrc;
+	uint32_t				crc;
+
+	trace_xfs_attr_leaf_setcrc(args);
+
+	xfs_calc_cksum(args->value, args->valuelen, &crc);
+
+	/*
+	 * Set up the operation.
+	 */
+	error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
+			args->blkno, &bp);
+	if (error)
+		return error;
+
+	leaf = bp->b_addr;
+	entry = &xfs_attr3_leaf_entryp(leaf)[args->index];
+	ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) != 0);
+
+	whichcrc = (entry->flags & XFS_ATTR_RMCRC_SEL) == 0;
+	name_rmt = xfs_attr3_leaf_name_remote(&(mp->m_sb), leaf,
+					      args->index);
+	name_rmt->crc[whichcrc] = crc;
+	xfs_trans_log_buf(args->trans, bp,
+			XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
+
+	/* Flip the XFS_ATTR_RMCRC_SEL bit to point to the right/new CRC and
+	 * clear XFS_ATTR_INCOMPLETE bit as this is final point of directly
+	 * mapped attr data write flow */
+	entry->flags ^= XFS_ATTR_RMCRC_SEL;
+	entry->flags &= ~XFS_ATTR_INCOMPLETE;
+	xfs_trans_log_buf(args->trans, bp,
+			XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
+
+	return 0;
+}
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h
index 589f810eedc0..c8722c8accb0 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.h
+++ b/fs/xfs/libxfs/xfs_attr_leaf.h
@@ -66,6 +66,7 @@  int	xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
 int	xfs_attr3_leaf_clearflag(struct xfs_da_args *args);
 int	xfs_attr3_leaf_setflag(struct xfs_da_args *args);
 int	xfs_attr3_leaf_flipflags(struct xfs_da_args *args);
+int	xfs_attr3_leaf_setcrc(struct xfs_da_args *args);
 
 /*
  * Routines used for growing the Btree.
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 7b16cdd72e9d..5c3b8929179d 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2189,6 +2189,7 @@  DEFINE_ATTR_EVENT(xfs_attr_leaf_to_node);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_rebalance);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_unbalance);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_toosmall);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_setcrc);
 
 DEFINE_ATTR_EVENT(xfs_attr_node_addname);
 DEFINE_ATTR_EVENT(xfs_attr_node_get);