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@xxxxxxxxxx> --- 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