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>
/* fake up iomap, (not) used in xfs_bmap.[ch] */
#define IOMAP_F_SHARED 0x04
/* 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))
/* CRC stuff, buffer API dependent on it */
#define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l))
* the extent. Just return the real extent at this offset.
*/
if (!isnullstartblock(bma.got.br_startblock)) {
* 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;
}
*seq = READ_ONCE(ifp->if_seq);
goto out_trans_cancel;
}
XFS_STATS_INC(mp, xs_xstrat_quick);
ASSERT(!isnullstartblock(bma.got.br_startblock));
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)
*seq = READ_ONCE(ifp->if_seq);
if (whichfork == XFS_COW_FORK)