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

Andrey Albershteyn
2024-12-29T13:39:06Z

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 --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);
--
2.47.0