]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: use iomap_valid method to detect stale cached iomaps
authorDave Chinner <dchinner@redhat.com>
Wed, 15 Mar 2023 14:47:39 +0000 (15:47 +0100)
committerCarlos Maiolino <cem@kernel.org>
Fri, 17 Mar 2023 10:38:46 +0000 (11:38 +0100)
Source kernel commit: 304a68b9c63bbfc1f6e159d68e8892fc54a06067

Now that iomap supports a mechanism to validate cached iomaps for
buffered write operations, hook it up to the XFS buffered write ops
so that we can avoid data corruptions that result from stale cached
iomaps. See:

https://lore.kernel.org/linux-xfs/20220817093627.GZ3600936@dread.disaster.area/

or the ->iomap_valid() introduction commit for exact details of the
corruption vector.

The validity cookie we store in the iomap is based on the type of
iomap we return. It is expected that the iomap->flags we set in
xfs_bmbt_to_iomap() is not perturbed by the iomap core and are
returned to us in the iomap passed via the .iomap_valid() callback.
This ensures that the validity cookie is always checking the correct
inode fork sequence numbers to detect potential changes that affect
the extent cached by the iomap.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
libxfs/libxfs_priv.h
libxfs/xfs_bmap.c

index ad4b9475832d6ff0cea99c638f9d97cf6ce05423..456c82d70dca11a6011373141d27c049d65f68aa 100644 (file)
@@ -68,7 +68,7 @@ extern struct kmem_cache *xfs_trans_cache;
 
 /* fake up iomap, (not) used in xfs_bmap.[ch] */
 #define IOMAP_F_SHARED                         0x04
-#define xfs_bmbt_to_iomap(a, b, c, d, e)       ((void) 0)
+#define xfs_bmbt_to_iomap(a, b, c, d, e, f)    ((void) 0)
 
 /* CRC stuff, buffer API dependent on it */
 #define crc32c(c,p,l)  crc32c_le((c),(unsigned char const *)(p),(l))
index 6d6f9e7dd647fadc94b8d2a82928c3b5d6bccb65..3b1739bdb0ff6d888d3eddd67d8add17e08f3b07 100644 (file)
@@ -4544,7 +4544,8 @@ xfs_bmapi_convert_delalloc(
         * the extent.  Just return the real extent at this offset.
         */
        if (!isnullstartblock(bma.got.br_startblock)) {
-               xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags);
+               xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags,
+                               xfs_iomap_inode_sequence(ip, flags));
                *seq = READ_ONCE(ifp->if_seq);
                goto out_trans_cancel;
        }
@@ -4592,7 +4593,8 @@ xfs_bmapi_convert_delalloc(
        XFS_STATS_INC(mp, xs_xstrat_quick);
 
        ASSERT(!isnullstartblock(bma.got.br_startblock));
-       xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags);
+       xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags,
+                               xfs_iomap_inode_sequence(ip, flags));
        *seq = READ_ONCE(ifp->if_seq);
 
        if (whichfork == XFS_COW_FORK)