diff options
| author | Christoph Hellwig <hch@lst.de> | 2018-08-07 13:57:12 -0400 |
|---|---|---|
| committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-08-07 13:57:12 -0400 |
| commit | 2ba090d521c5e09f32316c179d25bb6f699d3568 (patch) | |
| tree | 1171512eca076f1e10fea00dcf8e07766486c1a4 | |
| parent | a0e336ba3e3d1c7ec0f738a2e2e203434c00b08e (diff) | |
xfs: use WRITE_ONCE to update if_seq
This adds ordering of the updates and makes sure we always see the if_seq
update before the extent tree is modified.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
| -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 | ||
