diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2017-12-14 18:42:22 -0500 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2017-12-20 20:11:48 -0500 |
commit | 91aae6be4139b9e3902656d819e6af66e051bd7a (patch) | |
tree | a51589201fbdbdbe00c0426baeba80ada0220038 | |
parent | a192de265b26c525672884630d5376c405e83b2a (diff) |
xfs: track cowblocks separately in i_flags
The EOFBLOCKS/COWBLOCKS tags are totally separate things, so track them
with separate i_flags. Right now we're abusing IEOFBLOCKS for both,
which is totally bogus because we won't tag the inode with COWBLOCKS if
IEOFBLOCKS was set by a previous tagging of the inode with EOFBLOCKS.
Found by wiring up clonerange to fsstress in xfs/017.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | fs/xfs/xfs_icache.c | 33 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 1 |
2 files changed, 25 insertions, 9 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 43005fbe8b1e..58d2d4253c8e 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -1536,8 +1536,23 @@ xfs_inode_free_quota_eofblocks( | |||
1536 | return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks); | 1536 | return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks); |
1537 | } | 1537 | } |
1538 | 1538 | ||
1539 | static inline unsigned long | ||
1540 | xfs_iflag_for_tag( | ||
1541 | int tag) | ||
1542 | { | ||
1543 | switch (tag) { | ||
1544 | case XFS_ICI_EOFBLOCKS_TAG: | ||
1545 | return XFS_IEOFBLOCKS; | ||
1546 | case XFS_ICI_COWBLOCKS_TAG: | ||
1547 | return XFS_ICOWBLOCKS; | ||
1548 | default: | ||
1549 | ASSERT(0); | ||
1550 | return 0; | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1539 | static void | 1554 | static void |
1540 | __xfs_inode_set_eofblocks_tag( | 1555 | __xfs_inode_set_blocks_tag( |
1541 | xfs_inode_t *ip, | 1556 | xfs_inode_t *ip, |
1542 | void (*execute)(struct xfs_mount *mp), | 1557 | void (*execute)(struct xfs_mount *mp), |
1543 | void (*set_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, | 1558 | void (*set_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, |
@@ -1552,10 +1567,10 @@ __xfs_inode_set_eofblocks_tag( | |||
1552 | * Don't bother locking the AG and looking up in the radix trees | 1567 | * Don't bother locking the AG and looking up in the radix trees |
1553 | * if we already know that we have the tag set. | 1568 | * if we already know that we have the tag set. |
1554 | */ | 1569 | */ |
1555 | if (ip->i_flags & XFS_IEOFBLOCKS) | 1570 | if (ip->i_flags & xfs_iflag_for_tag(tag)) |
1556 | return; | 1571 | return; |
1557 | spin_lock(&ip->i_flags_lock); | 1572 | spin_lock(&ip->i_flags_lock); |
1558 | ip->i_flags |= XFS_IEOFBLOCKS; | 1573 | ip->i_flags |= xfs_iflag_for_tag(tag); |
1559 | spin_unlock(&ip->i_flags_lock); | 1574 | spin_unlock(&ip->i_flags_lock); |
1560 | 1575 | ||
1561 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); | 1576 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); |
@@ -1587,13 +1602,13 @@ xfs_inode_set_eofblocks_tag( | |||
1587 | xfs_inode_t *ip) | 1602 | xfs_inode_t *ip) |
1588 | { | 1603 | { |
1589 | trace_xfs_inode_set_eofblocks_tag(ip); | 1604 | trace_xfs_inode_set_eofblocks_tag(ip); |
1590 | return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_eofblocks, | 1605 | return __xfs_inode_set_blocks_tag(ip, xfs_queue_eofblocks, |
1591 | trace_xfs_perag_set_eofblocks, | 1606 | trace_xfs_perag_set_eofblocks, |
1592 | XFS_ICI_EOFBLOCKS_TAG); | 1607 | XFS_ICI_EOFBLOCKS_TAG); |
1593 | } | 1608 | } |
1594 | 1609 | ||
1595 | static void | 1610 | static void |
1596 | __xfs_inode_clear_eofblocks_tag( | 1611 | __xfs_inode_clear_blocks_tag( |
1597 | xfs_inode_t *ip, | 1612 | xfs_inode_t *ip, |
1598 | void (*clear_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, | 1613 | void (*clear_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, |
1599 | int error, unsigned long caller_ip), | 1614 | int error, unsigned long caller_ip), |
@@ -1603,7 +1618,7 @@ __xfs_inode_clear_eofblocks_tag( | |||
1603 | struct xfs_perag *pag; | 1618 | struct xfs_perag *pag; |
1604 | 1619 | ||
1605 | spin_lock(&ip->i_flags_lock); | 1620 | spin_lock(&ip->i_flags_lock); |
1606 | ip->i_flags &= ~XFS_IEOFBLOCKS; | 1621 | ip->i_flags &= ~xfs_iflag_for_tag(tag); |
1607 | spin_unlock(&ip->i_flags_lock); | 1622 | spin_unlock(&ip->i_flags_lock); |
1608 | 1623 | ||
1609 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); | 1624 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); |
@@ -1630,7 +1645,7 @@ xfs_inode_clear_eofblocks_tag( | |||
1630 | xfs_inode_t *ip) | 1645 | xfs_inode_t *ip) |
1631 | { | 1646 | { |
1632 | trace_xfs_inode_clear_eofblocks_tag(ip); | 1647 | trace_xfs_inode_clear_eofblocks_tag(ip); |
1633 | return __xfs_inode_clear_eofblocks_tag(ip, | 1648 | return __xfs_inode_clear_blocks_tag(ip, |
1634 | trace_xfs_perag_clear_eofblocks, XFS_ICI_EOFBLOCKS_TAG); | 1649 | trace_xfs_perag_clear_eofblocks, XFS_ICI_EOFBLOCKS_TAG); |
1635 | } | 1650 | } |
1636 | 1651 | ||
@@ -1724,7 +1739,7 @@ xfs_inode_set_cowblocks_tag( | |||
1724 | xfs_inode_t *ip) | 1739 | xfs_inode_t *ip) |
1725 | { | 1740 | { |
1726 | trace_xfs_inode_set_cowblocks_tag(ip); | 1741 | trace_xfs_inode_set_cowblocks_tag(ip); |
1727 | return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_cowblocks, | 1742 | return __xfs_inode_set_blocks_tag(ip, xfs_queue_cowblocks, |
1728 | trace_xfs_perag_set_cowblocks, | 1743 | trace_xfs_perag_set_cowblocks, |
1729 | XFS_ICI_COWBLOCKS_TAG); | 1744 | XFS_ICI_COWBLOCKS_TAG); |
1730 | } | 1745 | } |
@@ -1734,6 +1749,6 @@ xfs_inode_clear_cowblocks_tag( | |||
1734 | xfs_inode_t *ip) | 1749 | xfs_inode_t *ip) |
1735 | { | 1750 | { |
1736 | trace_xfs_inode_clear_cowblocks_tag(ip); | 1751 | trace_xfs_inode_clear_cowblocks_tag(ip); |
1737 | return __xfs_inode_clear_eofblocks_tag(ip, | 1752 | return __xfs_inode_clear_blocks_tag(ip, |
1738 | trace_xfs_perag_clear_cowblocks, XFS_ICI_COWBLOCKS_TAG); | 1753 | trace_xfs_perag_clear_cowblocks, XFS_ICI_COWBLOCKS_TAG); |
1739 | } | 1754 | } |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index b2136af9289f..d383e392ec9d 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -232,6 +232,7 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) | |||
232 | * log recovery to replay a bmap operation on the inode. | 232 | * log recovery to replay a bmap operation on the inode. |
233 | */ | 233 | */ |
234 | #define XFS_IRECOVERY (1 << 11) | 234 | #define XFS_IRECOVERY (1 << 11) |
235 | #define XFS_ICOWBLOCKS (1 << 12)/* has the cowblocks tag set */ | ||
235 | 236 | ||
236 | /* | 237 | /* |
237 | * Per-lifetime flags need to be reset when re-using a reclaimable inode during | 238 | * Per-lifetime flags need to be reset when re-using a reclaimable inode during |