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
Unified · Split
| @@ -2122,11 +2122,31 @@ xfs_swap_extents( · 2121 unmodified lines | |||
| 2122 | ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; | 2122 | ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; |
| 2123 | tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; | 2123 | tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; |
| 2124 | tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK; | 2124 | 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 | |||
| 2125 | cowfp = ip->i_cowfp; | 2138 | cowfp = ip->i_cowfp; |
| 2126 | ip->i_cowfp = tip->i_cowfp; | 2139 | ip->i_cowfp = tip->i_cowfp; |
| 2127 | tip->i_cowfp = cowfp; | 2140 | tip->i_cowfp = cowfp; |
| 2128 | xfs_inode_set_cowblocks_tag(ip); | 2141 | |
| 2129 | xfs_inode_set_cowblocks_tag(tip); | 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); | ||
| 2130 | } | 2150 | } |
| 2131 | 2151 | ||
| 2132 | xfs_trans_log_inode(tp, ip, src_log_flags); | 2152 | xfs_trans_log_inode(tp, ip, src_log_flags); |
| @@ -736,7 +736,13 @@ xfs_reflink_end_cow( · 735 unmodified lines | |||
| 736 | /* If there is a hole at end_fsb - 1 go to the previous extent */ | 736 | /* If there is a hole at end_fsb - 1 go to the previous extent */ |
| 737 | if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) || | 737 | if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) || |
| 738 | got.br_startoff > end_fsb) { | 738 | 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; | ||
| 740 | xfs_iext_get_extent(ifp, --idx, &got); | 746 | xfs_iext_get_extent(ifp, --idx, &got); |
| 741 | } | 747 | } |
| 742 | 748 | ||
| @@ -809,6 +815,7 @@ next_extent: · 66 unmodified lines | |||
| 809 | 815 | ||
| 810 | out_defer: | 816 | out_defer: |
| 811 | xfs_defer_cancel(&dfops); | 817 | xfs_defer_cancel(&dfops); |
| 818 | out_cancel: | ||
| 812 | xfs_trans_cancel(tp); | 819 | xfs_trans_cancel(tp); |
| 813 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 820 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 814 | out: | 821 | out: |