Skip to content

Commit eab26ad

Browse files
committed
Merge tag 'xfs-4.14-fixes-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Darrick Wong: - fix a race between overlapping copy on write aio - fix cow fork swapping when we defragment reflinked files * tag 'xfs-4.14-fixes-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: handle racy AIO in xfs_reflink_end_cow xfs: always swap the cow forks when swapping extents
2 parents 17d084c + e12199f commit eab26ad

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

fs/xfs/xfs_bmap_util.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,11 +2122,31 @@ xfs_swap_extents(
21222122
ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
21232123
tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
21242124
tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK;
2125+
}
2126+
2127+
/* Swap the cow forks. */
2128+
if (xfs_sb_version_hasreflink(&mp->m_sb)) {
2129+
xfs_extnum_t extnum;
2130+
2131+
ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
2132+
ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
2133+
2134+
extnum = ip->i_cnextents;
2135+
ip->i_cnextents = tip->i_cnextents;
2136+
tip->i_cnextents = extnum;
2137+
21252138
cowfp = ip->i_cowfp;
21262139
ip->i_cowfp = tip->i_cowfp;
21272140
tip->i_cowfp = cowfp;
2128-
xfs_inode_set_cowblocks_tag(ip);
2129-
xfs_inode_set_cowblocks_tag(tip);
2141+
2142+
if (ip->i_cowfp && ip->i_cnextents)
2143+
xfs_inode_set_cowblocks_tag(ip);
2144+
else
2145+
xfs_inode_clear_cowblocks_tag(ip);
2146+
if (tip->i_cowfp && tip->i_cnextents)
2147+
xfs_inode_set_cowblocks_tag(tip);
2148+
else
2149+
xfs_inode_clear_cowblocks_tag(tip);
21302150
}
21312151

21322152
xfs_trans_log_inode(tp, ip, src_log_flags);

fs/xfs/xfs_reflink.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,13 @@ xfs_reflink_end_cow(
736736
/* If there is a hole at end_fsb - 1 go to the previous extent */
737737
if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) ||
738738
got.br_startoff > end_fsb) {
739-
ASSERT(idx > 0);
739+
/*
740+
* In case of racing, overlapping AIO writes no COW extents
741+
* might be left by the time I/O completes for the loser of
742+
* the race. In that case we are done.
743+
*/
744+
if (idx <= 0)
745+
goto out_cancel;
740746
xfs_iext_get_extent(ifp, --idx, &got);
741747
}
742748

@@ -809,6 +815,7 @@ xfs_reflink_end_cow(
809815

810816
out_defer:
811817
xfs_defer_cancel(&dfops);
818+
out_cancel:
812819
xfs_trans_cancel(tp);
813820
xfs_iunlock(ip, XFS_ILOCK_EXCL);
814821
out:

0 commit comments

Comments
 (0)