diff options
author | Brian Foster <bfoster@redhat.com> | 2012-11-06 09:50:42 -0500 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-11-08 16:25:40 -0500 |
commit | 41176a68e3f710630feace536d0277a092e206b5 (patch) | |
tree | b1452aae0f00c37ff769e9f4620aa3936e70b837 /fs/xfs | |
parent | 40165e27617e2a98bf8588001d2f2872fae2fee2 (diff) |
xfs: create function to scan and clear EOFBLOCKS inodes
xfs_inodes_free_eofblocks() implements scanning functionality for
EOFBLOCKS inodes. It uses the AG iterator to walk the tagged inodes
and free post-EOF blocks via the xfs_inode_free_eofblocks() execute
function. The scan can be invoked in best-effort mode or wait
(force) mode.
A best-effort scan (default) handles all inodes that do not have a
dirty cache and we successfully acquire the io lock via trylock. In
wait mode, we continue to cycle through an AG until all inodes are
handled.
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')
-rw-r--r-- | fs/xfs/xfs_icache.c | 43 | ||||
-rw-r--r-- | fs/xfs/xfs_icache.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 1 |
3 files changed, 45 insertions, 0 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 2a96dc48ebe6..d115cb44b103 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -1170,6 +1170,49 @@ xfs_reclaim_inodes_count( | |||
1170 | return reclaimable; | 1170 | return reclaimable; |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | STATIC int | ||
1174 | xfs_inode_free_eofblocks( | ||
1175 | struct xfs_inode *ip, | ||
1176 | struct xfs_perag *pag, | ||
1177 | int flags, | ||
1178 | void *args) | ||
1179 | { | ||
1180 | int ret; | ||
1181 | |||
1182 | if (!xfs_can_free_eofblocks(ip, false)) { | ||
1183 | /* inode could be preallocated or append-only */ | ||
1184 | trace_xfs_inode_free_eofblocks_invalid(ip); | ||
1185 | xfs_inode_clear_eofblocks_tag(ip); | ||
1186 | return 0; | ||
1187 | } | ||
1188 | |||
1189 | /* | ||
1190 | * If the mapping is dirty the operation can block and wait for some | ||
1191 | * time. Unless we are waiting, skip it. | ||
1192 | */ | ||
1193 | if (!(flags & SYNC_WAIT) && | ||
1194 | mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY)) | ||
1195 | return 0; | ||
1196 | |||
1197 | ret = xfs_free_eofblocks(ip->i_mount, ip, true); | ||
1198 | |||
1199 | /* don't revisit the inode if we're not waiting */ | ||
1200 | if (ret == EAGAIN && !(flags & SYNC_WAIT)) | ||
1201 | ret = 0; | ||
1202 | |||
1203 | return ret; | ||
1204 | } | ||
1205 | |||
1206 | int | ||
1207 | xfs_icache_free_eofblocks( | ||
1208 | struct xfs_mount *mp, | ||
1209 | int flags) | ||
1210 | { | ||
1211 | ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0); | ||
1212 | return xfs_inode_ag_iterator_tag(mp, xfs_inode_free_eofblocks, flags, | ||
1213 | NULL, XFS_ICI_EOFBLOCKS_TAG); | ||
1214 | } | ||
1215 | |||
1173 | void | 1216 | void |
1174 | xfs_inode_set_eofblocks_tag( | 1217 | xfs_inode_set_eofblocks_tag( |
1175 | xfs_inode_t *ip) | 1218 | xfs_inode_t *ip) |
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 54c113478dfc..cb6b8d0eee61 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h | |||
@@ -37,6 +37,7 @@ void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); | |||
37 | 37 | ||
38 | void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); | 38 | void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); |
39 | void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); | 39 | void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); |
40 | int xfs_icache_free_eofblocks(struct xfs_mount *, int); | ||
40 | 41 | ||
41 | int xfs_sync_inode_grab(struct xfs_inode *ip); | 42 | int xfs_sync_inode_grab(struct xfs_inode *ip); |
42 | int xfs_inode_ag_iterator(struct xfs_mount *mp, | 43 | int xfs_inode_ag_iterator(struct xfs_mount *mp, |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6f46e034b766..cb5234632072 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -589,6 +589,7 @@ DEFINE_INODE_EVENT(xfs_dquot_dqdetach); | |||
589 | 589 | ||
590 | DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag); | 590 | DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag); |
591 | DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); | 591 | DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); |
592 | DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); | ||
592 | 593 | ||
593 | DECLARE_EVENT_CLASS(xfs_iref_class, | 594 | DECLARE_EVENT_CLASS(xfs_iref_class, |
594 | TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), | 595 | TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), |