aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2012-11-06 09:50:38 -0500
committerBen Myers <bpm@sgi.com>2012-11-08 15:20:44 -0500
commit27b52867925e3aaed090063c1c58a7537e6373f3 (patch)
tree901719517ac8dc751053f6bf9d86cbe2b73bf538 /fs/xfs/xfs_icache.c
parent69a58a43f74eb2cb23d9bce2524dae33c289a40f (diff)
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>
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 9c8703b5cd72..f9afc5ff0482 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1128,3 +1128,65 @@ xfs_reclaim_inodes_count(
1128 return reclaimable; 1128 return reclaimable;
1129} 1129}
1130 1130
1131void
1132xfs_inode_set_eofblocks_tag(
1133 xfs_inode_t *ip)
1134{
1135 struct xfs_mount *mp = ip->i_mount;
1136 struct xfs_perag *pag;
1137 int tagged;
1138
1139 pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
1140 spin_lock(&pag->pag_ici_lock);
1141 trace_xfs_inode_set_eofblocks_tag(ip);
1142
1143 tagged = radix_tree_tagged(&pag->pag_ici_root,
1144 XFS_ICI_EOFBLOCKS_TAG);
1145 radix_tree_tag_set(&pag->pag_ici_root,
1146 XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
1147 XFS_ICI_EOFBLOCKS_TAG);
1148 if (!tagged) {
1149 /* propagate the eofblocks tag up into the perag radix tree */
1150 spin_lock(&ip->i_mount->m_perag_lock);
1151 radix_tree_tag_set(&ip->i_mount->m_perag_tree,
1152 XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
1153 XFS_ICI_EOFBLOCKS_TAG);
1154 spin_unlock(&ip->i_mount->m_perag_lock);
1155
1156 trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno,
1157 -1, _RET_IP_);
1158 }
1159
1160 spin_unlock(&pag->pag_ici_lock);
1161 xfs_perag_put(pag);
1162}
1163
1164void
1165xfs_inode_clear_eofblocks_tag(
1166 xfs_inode_t *ip)
1167{
1168 struct xfs_mount *mp = ip->i_mount;
1169 struct xfs_perag *pag;
1170
1171 pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
1172 spin_lock(&pag->pag_ici_lock);
1173 trace_xfs_inode_clear_eofblocks_tag(ip);
1174
1175 radix_tree_tag_clear(&pag->pag_ici_root,
1176 XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
1177 XFS_ICI_EOFBLOCKS_TAG);
1178 if (!radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_EOFBLOCKS_TAG)) {
1179 /* clear the eofblocks tag from the perag radix tree */
1180 spin_lock(&ip->i_mount->m_perag_lock);
1181 radix_tree_tag_clear(&ip->i_mount->m_perag_tree,
1182 XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
1183 XFS_ICI_EOFBLOCKS_TAG);
1184 spin_unlock(&ip->i_mount->m_perag_lock);
1185 trace_xfs_perag_clear_eofblocks(ip->i_mount, pag->pag_agno,
1186 -1, _RET_IP_);
1187 }
1188
1189 spin_unlock(&pag->pag_ici_lock);
1190 xfs_perag_put(pag);
1191}
1192