diff --git a/COPYING-5.14.0-687.25.1.el9 b/COPYING-5.14.0-687.26.1.el9 similarity index 100% rename from COPYING-5.14.0-687.25.1.el9 rename to COPYING-5.14.0-687.26.1.el9 diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index b11769c009..0e4a66ff4e 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -389,6 +389,7 @@ xfs_reflink_fill_cow_hole( struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; xfs_filblks_t resaligned; + unsigned int seq_before = READ_ONCE(ip->i_df.if_seq); xfs_extlen_t resblks; int nimaps; int error; @@ -408,6 +409,22 @@ xfs_reflink_fill_cow_hole( *lockmode = XFS_ILOCK_EXCL; + /* + * The data fork mapping may have changed while we dropped the ILOCK + * (a racing O_DIRECT writer under IOLOCK_SHARED can complete a full + * CoW cycle including xfs_reflink_end_cow(), which remaps this offset + * and drops the refcount of the old shared block). Re-read it so the + * shared-status recheck below and the caller's in-place iomap both + * operate on the current mapping rather than a stale physical block. + */ + if (seq_before != READ_ONCE(ip->i_df.if_seq)) { + nimaps = 1; + error = xfs_bmapi_read(ip, imap->br_startoff, + imap->br_blockcount, imap, &nimaps, 0); + if (error) + goto out_trans_cancel; + } + error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); if (error || !*shared) goto out_trans_cancel; @@ -454,6 +471,8 @@ xfs_reflink_fill_delalloc( bool found; do { + unsigned int seq_before = READ_ONCE(ip->i_df.if_seq); + xfs_iunlock(ip, *lockmode); *lockmode = 0; @@ -464,6 +483,23 @@ xfs_reflink_fill_delalloc( *lockmode = XFS_ILOCK_EXCL; + /* + * The data fork mapping may have changed while we dropped the + * ILOCK (a racing O_DIRECT writer under IOLOCK_SHARED can + * complete a full CoW cycle including xfs_reflink_end_cow(), + * which remaps this offset and drops the refcount of the old + * shared block). Re-read it so the shared-status recheck + * below and the caller's in-place iomap both operate on the + * current mapping rather than a stale physical block. + */ + if (seq_before != READ_ONCE(ip->i_df.if_seq)) { + nimaps = 1; + error = xfs_bmapi_read(ip, imap->br_startoff, + imap->br_blockcount, imap, &nimaps, 0); + if (error) + goto out_trans_cancel; + } + error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); if (error || !*shared) diff --git a/kernel.sbat b/kernel.sbat index 46672cc7eb..770bb44afe 100644 --- a/kernel.sbat +++ b/kernel.sbat @@ -1,3 +1,3 @@ sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md -kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.25.1.el9.x86_64,mailto:secalert@redhat.com -kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.25.1.el9.x86_64,mailto:security@almalinux.org +kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.26.1.el9.x86_64,mailto:secalert@redhat.com +kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.26.1.el9.x86_64,mailto:security@almalinux.org