xfs: add EOFBLOCKS inode tagging/untagging
Add the XFS_ICI_EOFBLOCKS_TAG inode tag to identify inodes with speculatively preallocated blocks beyond EOF. An inode is tagged when speculative preallocation occurs and untagged either via truncate down or when post-EOF blocks are freed via release or reclaim. The tag management is intentionally not aggressive to prefer simplicity over the complexity of handling all the corner cases under which post-EOF blocks could be freed (i.e., forward truncation, fallocate, write error conditions, etc.). This means that a tagged inode may or may not have post-EOF blocks after a period of time. The tag is eventually cleared when the inode is released or reclaimed. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
@@ -1128,3 +1128,65 @@ xfs_reclaim_inodes_count(
|
||||
return reclaimable;
|
||||
}
|
||||
|
||||
void
|
||||
xfs_inode_set_eofblocks_tag(
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_perag *pag;
|
||||
int tagged;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
|
||||
spin_lock(&pag->pag_ici_lock);
|
||||
trace_xfs_inode_set_eofblocks_tag(ip);
|
||||
|
||||
tagged = radix_tree_tagged(&pag->pag_ici_root,
|
||||
XFS_ICI_EOFBLOCKS_TAG);
|
||||
radix_tree_tag_set(&pag->pag_ici_root,
|
||||
XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
|
||||
XFS_ICI_EOFBLOCKS_TAG);
|
||||
if (!tagged) {
|
||||
/* propagate the eofblocks tag up into the perag radix tree */
|
||||
spin_lock(&ip->i_mount->m_perag_lock);
|
||||
radix_tree_tag_set(&ip->i_mount->m_perag_tree,
|
||||
XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
|
||||
XFS_ICI_EOFBLOCKS_TAG);
|
||||
spin_unlock(&ip->i_mount->m_perag_lock);
|
||||
|
||||
trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno,
|
||||
-1, _RET_IP_);
|
||||
}
|
||||
|
||||
spin_unlock(&pag->pag_ici_lock);
|
||||
xfs_perag_put(pag);
|
||||
}
|
||||
|
||||
void
|
||||
xfs_inode_clear_eofblocks_tag(
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
|
||||
spin_lock(&pag->pag_ici_lock);
|
||||
trace_xfs_inode_clear_eofblocks_tag(ip);
|
||||
|
||||
radix_tree_tag_clear(&pag->pag_ici_root,
|
||||
XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
|
||||
XFS_ICI_EOFBLOCKS_TAG);
|
||||
if (!radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_EOFBLOCKS_TAG)) {
|
||||
/* clear the eofblocks tag from the perag radix tree */
|
||||
spin_lock(&ip->i_mount->m_perag_lock);
|
||||
radix_tree_tag_clear(&ip->i_mount->m_perag_tree,
|
||||
XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
|
||||
XFS_ICI_EOFBLOCKS_TAG);
|
||||
spin_unlock(&ip->i_mount->m_perag_lock);
|
||||
trace_xfs_perag_clear_eofblocks(ip->i_mount, pag->pag_agno,
|
||||
-1, _RET_IP_);
|
||||
}
|
||||
|
||||
spin_unlock(&pag->pag_ici_lock);
|
||||
xfs_perag_put(pag);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user