]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: use WRITE_ONCE to update if_seq
authorChristoph Hellwig <hch@lst.de>
Fri, 5 Oct 2018 02:36:12 +0000 (21:36 -0500)
committerEric Sandeen <sandeen@redhat.com>
Fri, 5 Oct 2018 02:36:12 +0000 (21:36 -0500)
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 <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/libxfs_priv.h
libxfs/xfs_iext_tree.c

index 52aa55e53fcb859bfc8a469d36b001c97d0df38f..a2fbeacda728445f9ae20850db1e7a0de5cbe903 100644 (file)
@@ -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!
index be662077c92525621ab8c54509a4b4710eccae03..9e28a8e1cef6a02aaf262729be72dd662e8590cb 100644 (file)
@@ -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;