Commit 91aae6be authored by Darrick J. Wong's avatar Darrick J. Wong

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: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent a192de26
...@@ -1536,8 +1536,23 @@ xfs_inode_free_quota_eofblocks( ...@@ -1536,8 +1536,23 @@ xfs_inode_free_quota_eofblocks(
return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks); return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks);
} }
static inline unsigned long
xfs_iflag_for_tag(
int tag)
{
switch (tag) {
case XFS_ICI_EOFBLOCKS_TAG:
return XFS_IEOFBLOCKS;
case XFS_ICI_COWBLOCKS_TAG:
return XFS_ICOWBLOCKS;
default:
ASSERT(0);
return 0;
}
}
static void static void
__xfs_inode_set_eofblocks_tag( __xfs_inode_set_blocks_tag(
xfs_inode_t *ip, xfs_inode_t *ip,
void (*execute)(struct xfs_mount *mp), void (*execute)(struct xfs_mount *mp),
void (*set_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, void (*set_tp)(struct xfs_mount *mp, xfs_agnumber_t agno,
...@@ -1552,10 +1567,10 @@ __xfs_inode_set_eofblocks_tag( ...@@ -1552,10 +1567,10 @@ __xfs_inode_set_eofblocks_tag(
* Don't bother locking the AG and looking up in the radix trees * Don't bother locking the AG and looking up in the radix trees
* if we already know that we have the tag set. * if we already know that we have the tag set.
*/ */
if (ip->i_flags & XFS_IEOFBLOCKS) if (ip->i_flags & xfs_iflag_for_tag(tag))
return; return;
spin_lock(&ip->i_flags_lock); spin_lock(&ip->i_flags_lock);
ip->i_flags |= XFS_IEOFBLOCKS; ip->i_flags |= xfs_iflag_for_tag(tag);
spin_unlock(&ip->i_flags_lock); spin_unlock(&ip->i_flags_lock);
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
...@@ -1587,13 +1602,13 @@ xfs_inode_set_eofblocks_tag( ...@@ -1587,13 +1602,13 @@ xfs_inode_set_eofblocks_tag(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
trace_xfs_inode_set_eofblocks_tag(ip); trace_xfs_inode_set_eofblocks_tag(ip);
return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_eofblocks, return __xfs_inode_set_blocks_tag(ip, xfs_queue_eofblocks,
trace_xfs_perag_set_eofblocks, trace_xfs_perag_set_eofblocks,
XFS_ICI_EOFBLOCKS_TAG); XFS_ICI_EOFBLOCKS_TAG);
} }
static void static void
__xfs_inode_clear_eofblocks_tag( __xfs_inode_clear_blocks_tag(
xfs_inode_t *ip, xfs_inode_t *ip,
void (*clear_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, void (*clear_tp)(struct xfs_mount *mp, xfs_agnumber_t agno,
int error, unsigned long caller_ip), int error, unsigned long caller_ip),
...@@ -1603,7 +1618,7 @@ __xfs_inode_clear_eofblocks_tag( ...@@ -1603,7 +1618,7 @@ __xfs_inode_clear_eofblocks_tag(
struct xfs_perag *pag; struct xfs_perag *pag;
spin_lock(&ip->i_flags_lock); spin_lock(&ip->i_flags_lock);
ip->i_flags &= ~XFS_IEOFBLOCKS; ip->i_flags &= ~xfs_iflag_for_tag(tag);
spin_unlock(&ip->i_flags_lock); spin_unlock(&ip->i_flags_lock);
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
...@@ -1630,7 +1645,7 @@ xfs_inode_clear_eofblocks_tag( ...@@ -1630,7 +1645,7 @@ xfs_inode_clear_eofblocks_tag(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
trace_xfs_inode_clear_eofblocks_tag(ip); trace_xfs_inode_clear_eofblocks_tag(ip);
return __xfs_inode_clear_eofblocks_tag(ip, return __xfs_inode_clear_blocks_tag(ip,
trace_xfs_perag_clear_eofblocks, XFS_ICI_EOFBLOCKS_TAG); trace_xfs_perag_clear_eofblocks, XFS_ICI_EOFBLOCKS_TAG);
} }
...@@ -1724,7 +1739,7 @@ xfs_inode_set_cowblocks_tag( ...@@ -1724,7 +1739,7 @@ xfs_inode_set_cowblocks_tag(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
trace_xfs_inode_set_cowblocks_tag(ip); trace_xfs_inode_set_cowblocks_tag(ip);
return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_cowblocks, return __xfs_inode_set_blocks_tag(ip, xfs_queue_cowblocks,
trace_xfs_perag_set_cowblocks, trace_xfs_perag_set_cowblocks,
XFS_ICI_COWBLOCKS_TAG); XFS_ICI_COWBLOCKS_TAG);
} }
...@@ -1734,6 +1749,6 @@ xfs_inode_clear_cowblocks_tag( ...@@ -1734,6 +1749,6 @@ xfs_inode_clear_cowblocks_tag(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
trace_xfs_inode_clear_cowblocks_tag(ip); trace_xfs_inode_clear_cowblocks_tag(ip);
return __xfs_inode_clear_eofblocks_tag(ip, return __xfs_inode_clear_blocks_tag(ip,
trace_xfs_perag_clear_cowblocks, XFS_ICI_COWBLOCKS_TAG); trace_xfs_perag_clear_cowblocks, XFS_ICI_COWBLOCKS_TAG);
} }
...@@ -232,6 +232,7 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) ...@@ -232,6 +232,7 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
* log recovery to replay a bmap operation on the inode. * log recovery to replay a bmap operation on the inode.
*/ */
#define XFS_IRECOVERY (1 << 11) #define XFS_IRECOVERY (1 << 11)
#define XFS_ICOWBLOCKS (1 << 12)/* has the cowblocks tag set */
/* /*
* Per-lifetime flags need to be reset when re-using a reclaimable inode during * Per-lifetime flags need to be reset when re-using a reclaimable inode during
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment