From c02e03410e8a51959ff376fff301dea8ecb2984f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 4 Oct 2018 21:36:12 -0500 Subject: [PATCH] xfs: use WRITE_ONCE to update if_seq Source kernel commit: 2ba090d521c5e09f32316c179d25bb6f699d3568 This adds ordering of the updates and makes sure we always see the if_seq update before the extent tree is modified. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Signed-off-by: Eric Sandeen --- libxfs/libxfs_priv.h | 3 +++ libxfs/xfs_iext_tree.c | 20 +++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 52aa55e53..a2fbeacda 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -204,6 +204,9 @@ static inline bool WARN_ON_ONCE(bool expr) { #define percpu_counter_read_positive(x) ((*x) > 0 ? (*x) : 0) #define percpu_counter_sum(x) (*x) +#define READ_ONCE(x) (x) +#define WRITE_ONCE(x, val) ((x) = (val)) + /* * prandom_u32 is used for di_gen inode allocation, it must be zero for libxfs * or all sorts of badness can occur! diff --git a/libxfs/xfs_iext_tree.c b/libxfs/xfs_iext_tree.c index be662077c..9e28a8e1c 100644 --- a/libxfs/xfs_iext_tree.c +++ b/libxfs/xfs_iext_tree.c @@ -14,6 +14,7 @@ #include "xfs_inode_fork.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_bmap.h" #include "xfs_trace.h" /* @@ -612,6 +613,19 @@ xfs_iext_realloc_root( cur->leaf = new; } +/* + * Increment the sequence counter if we are on a COW fork. This allows + * the writeback code to skip looking for a COW extent if the COW fork + * hasn't changed. We use WRITE_ONCE here to ensure the update to the + * sequence counter is seen before the modifications to the extent + * tree itself take effect. + */ +static inline void xfs_iext_inc_seq(struct xfs_ifork *ifp, int state) +{ + if (state & BMAP_COWFORK) + WRITE_ONCE(ifp->if_seq, READ_ONCE(ifp->if_seq) + 1); +} + void xfs_iext_insert( struct xfs_inode *ip, @@ -624,7 +638,7 @@ xfs_iext_insert( struct xfs_iext_leaf *new = NULL; int nr_entries, i; - ifp->if_seq++; + xfs_iext_inc_seq(ifp, state); if (ifp->if_height == 0) xfs_iext_alloc_root(ifp, cur); @@ -866,7 +880,7 @@ xfs_iext_remove( ASSERT(ifp->if_u1.if_root != NULL); ASSERT(xfs_iext_valid(ifp, cur)); - ifp->if_seq++; + xfs_iext_inc_seq(ifp, state); nr_entries = xfs_iext_leaf_nr_entries(ifp, leaf, cur->pos) - 1; for (i = cur->pos; i < nr_entries; i++) @@ -974,7 +988,7 @@ xfs_iext_update_extent( { struct xfs_ifork *ifp = xfs_iext_state_to_fork(ip, state); - ifp->if_seq++; + xfs_iext_inc_seq(ifp, state); if (cur->pos == 0) { struct xfs_bmbt_irec old; -- 2.47.2