diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_iext_tree.c | 20 | ||||
-rw-r--r-- | fs/xfs/xfs_aops.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.c | 3 |
3 files changed, 21 insertions, 6 deletions
diff --git a/fs/xfs/libxfs/xfs_iext_tree.c b/fs/xfs/libxfs/xfs_iext_tree.c index 8a7aea041ee1..771dd072015d 100644 --- a/fs/xfs/libxfs/xfs_iext_tree.c +++ b/fs/xfs/libxfs/xfs_iext_tree.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "xfs_inode_fork.h" | 14 | #include "xfs_inode_fork.h" |
15 | #include "xfs_trans_resv.h" | 15 | #include "xfs_trans_resv.h" |
16 | #include "xfs_mount.h" | 16 | #include "xfs_mount.h" |
17 | #include "xfs_bmap.h" | ||
17 | #include "xfs_trace.h" | 18 | #include "xfs_trace.h" |
18 | 19 | ||
19 | /* | 20 | /* |
@@ -612,6 +613,19 @@ xfs_iext_realloc_root( | |||
612 | cur->leaf = new; | 613 | cur->leaf = new; |
613 | } | 614 | } |
614 | 615 | ||
616 | /* | ||
617 | * Increment the sequence counter if we are on a COW fork. This allows | ||
618 | * the writeback code to skip looking for a COW extent if the COW fork | ||
619 | * hasn't changed. We use WRITE_ONCE here to ensure the update to the | ||
620 | * sequence counter is seen before the modifications to the extent | ||
621 | * tree itself take effect. | ||
622 | */ | ||
623 | static inline void xfs_iext_inc_seq(struct xfs_ifork *ifp, int state) | ||
624 | { | ||
625 | if (state & BMAP_COWFORK) | ||
626 | WRITE_ONCE(ifp->if_seq, READ_ONCE(ifp->if_seq) + 1); | ||
627 | } | ||
628 | |||
615 | void | 629 | void |
616 | xfs_iext_insert( | 630 | xfs_iext_insert( |
617 | struct xfs_inode *ip, | 631 | struct xfs_inode *ip, |
@@ -624,7 +638,7 @@ xfs_iext_insert( | |||
624 | struct xfs_iext_leaf *new = NULL; | 638 | struct xfs_iext_leaf *new = NULL; |
625 | int nr_entries, i; | 639 | int nr_entries, i; |
626 | 640 | ||
627 | ifp->if_seq++; | 641 | xfs_iext_inc_seq(ifp, state); |
628 | 642 | ||
629 | if (ifp->if_height == 0) | 643 | if (ifp->if_height == 0) |
630 | xfs_iext_alloc_root(ifp, cur); | 644 | xfs_iext_alloc_root(ifp, cur); |
@@ -866,7 +880,7 @@ xfs_iext_remove( | |||
866 | ASSERT(ifp->if_u1.if_root != NULL); | 880 | ASSERT(ifp->if_u1.if_root != NULL); |
867 | ASSERT(xfs_iext_valid(ifp, cur)); | 881 | ASSERT(xfs_iext_valid(ifp, cur)); |
868 | 882 | ||
869 | ifp->if_seq++; | 883 | xfs_iext_inc_seq(ifp, state); |
870 | 884 | ||
871 | nr_entries = xfs_iext_leaf_nr_entries(ifp, leaf, cur->pos) - 1; | 885 | nr_entries = xfs_iext_leaf_nr_entries(ifp, leaf, cur->pos) - 1; |
872 | for (i = cur->pos; i < nr_entries; i++) | 886 | for (i = cur->pos; i < nr_entries; i++) |
@@ -974,7 +988,7 @@ xfs_iext_update_extent( | |||
974 | { | 988 | { |
975 | struct xfs_ifork *ifp = xfs_iext_state_to_fork(ip, state); | 989 | struct xfs_ifork *ifp = xfs_iext_state_to_fork(ip, state); |
976 | 990 | ||
977 | ifp->if_seq++; | 991 | xfs_iext_inc_seq(ifp, state); |
978 | 992 | ||
979 | if (cur->pos == 0) { | 993 | if (cur->pos == 0) { |
980 | struct xfs_bmbt_irec old; | 994 | struct xfs_bmbt_irec old; |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 235b4ddcd324..49f5f5896a43 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -351,7 +351,7 @@ xfs_map_blocks( | |||
351 | if (imap_valid && | 351 | if (imap_valid && |
352 | (!xfs_inode_has_cow_data(ip) || | 352 | (!xfs_inode_has_cow_data(ip) || |
353 | wpc->io_type == XFS_IO_COW || | 353 | wpc->io_type == XFS_IO_COW || |
354 | wpc->cow_seq == ip->i_cowfp->if_seq)) | 354 | wpc->cow_seq == READ_ONCE(ip->i_cowfp->if_seq))) |
355 | return 0; | 355 | return 0; |
356 | 356 | ||
357 | if (XFS_FORCED_SHUTDOWN(mp)) | 357 | if (XFS_FORCED_SHUTDOWN(mp)) |
@@ -380,7 +380,7 @@ xfs_map_blocks( | |||
380 | xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &imap)) | 380 | xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &imap)) |
381 | cow_fsb = imap.br_startoff; | 381 | cow_fsb = imap.br_startoff; |
382 | if (cow_fsb != NULLFILEOFF && cow_fsb <= offset_fsb) { | 382 | if (cow_fsb != NULLFILEOFF && cow_fsb <= offset_fsb) { |
383 | wpc->cow_seq = ip->i_cowfp->if_seq; | 383 | wpc->cow_seq = READ_ONCE(ip->i_cowfp->if_seq); |
384 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 384 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
385 | /* | 385 | /* |
386 | * Truncate can race with writeback since writeback doesn't | 386 | * Truncate can race with writeback since writeback doesn't |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 3282575e2df4..6320aca39f39 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -655,6 +655,7 @@ xfs_iomap_write_allocate( | |||
655 | unsigned int *cow_seq) | 655 | unsigned int *cow_seq) |
656 | { | 656 | { |
657 | xfs_mount_t *mp = ip->i_mount; | 657 | xfs_mount_t *mp = ip->i_mount; |
658 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); | ||
658 | xfs_fileoff_t offset_fsb, last_block; | 659 | xfs_fileoff_t offset_fsb, last_block; |
659 | xfs_fileoff_t end_fsb, map_start_fsb; | 660 | xfs_fileoff_t end_fsb, map_start_fsb; |
660 | xfs_filblks_t count_fsb; | 661 | xfs_filblks_t count_fsb; |
@@ -768,7 +769,7 @@ xfs_iomap_write_allocate( | |||
768 | goto error0; | 769 | goto error0; |
769 | 770 | ||
770 | if (whichfork == XFS_COW_FORK) | 771 | if (whichfork == XFS_COW_FORK) |
771 | *cow_seq = XFS_IFORK_PTR(ip, whichfork)->if_seq; | 772 | *cow_seq = READ_ONCE(ifp->if_seq); |
772 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 773 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
773 | } | 774 | } |
774 | 775 | ||