aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/xfs/xfs_ag.h1
-rw-r--r--fs/xfs/xfs_icache.c62
-rw-r--r--fs/xfs/xfs_icache.h3
-rw-r--r--fs/xfs/xfs_iomap.c8
-rw-r--r--fs/xfs/xfs_iops.c4
-rw-r--r--fs/xfs/xfs_trace.h5
-rw-r--r--fs/xfs/xfs_vnodeops.c2
7 files changed, 85 insertions, 0 deletions
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 44d65c1533c0..22bd4db011c8 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -233,6 +233,7 @@ typedef struct xfs_perag {
233#define XFS_ICI_NO_TAG (-1) /* special flag for an untagged lookup 233#define XFS_ICI_NO_TAG (-1) /* special flag for an untagged lookup
234 in xfs_inode_ag_iterator */ 234 in xfs_inode_ag_iterator */
235#define XFS_ICI_RECLAIM_TAG 0 /* inode is to be reclaimed */ 235#define XFS_ICI_RECLAIM_TAG 0 /* inode is to be reclaimed */
236#define XFS_ICI_EOFBLOCKS_TAG 1 /* inode has blocks beyond EOF */
236 237
237#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels) 238#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
238#define XFS_MIN_FREELIST_RAW(bl,cl,mp) \ 239#define XFS_MIN_FREELIST_RAW(bl,cl,mp) \
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
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 222e22f16b4a..db3613075dc6 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -35,6 +35,9 @@ void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
35 35
36void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); 36void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
37 37
38void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
39void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
40
38int xfs_sync_inode_grab(struct xfs_inode *ip); 41int xfs_sync_inode_grab(struct xfs_inode *ip);
39int xfs_inode_ag_iterator(struct xfs_mount *mp, 42int xfs_inode_ag_iterator(struct xfs_mount *mp,
40 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), 43 int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index a066cf1766ab..add06b4e9a63 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -41,6 +41,7 @@
41#include "xfs_utils.h" 41#include "xfs_utils.h"
42#include "xfs_iomap.h" 42#include "xfs_iomap.h"
43#include "xfs_trace.h" 43#include "xfs_trace.h"
44#include "xfs_icache.h"
44 45
45 46
46#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ 47#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
@@ -450,6 +451,13 @@ retry:
450 if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip))) 451 if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
451 return xfs_alert_fsblock_zero(ip, &imap[0]); 452 return xfs_alert_fsblock_zero(ip, &imap[0]);
452 453
454 /*
455 * Tag the inode as speculatively preallocated so we can reclaim this
456 * space on demand, if necessary.
457 */
458 if (prealloc)
459 xfs_inode_set_eofblocks_tag(ip);
460
453 *ret_imap = imap[0]; 461 *ret_imap = imap[0];
454 return 0; 462 return 0;
455} 463}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 4e00cf091d2c..81f5c4953287 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -38,6 +38,7 @@
38#include "xfs_vnodeops.h" 38#include "xfs_vnodeops.h"
39#include "xfs_inode_item.h" 39#include "xfs_inode_item.h"
40#include "xfs_trace.h" 40#include "xfs_trace.h"
41#include "xfs_icache.h"
41 42
42#include <linux/capability.h> 43#include <linux/capability.h>
43#include <linux/xattr.h> 44#include <linux/xattr.h>
@@ -854,6 +855,9 @@ xfs_setattr_size(
854 * and do not wait the usual (long) time for writeout. 855 * and do not wait the usual (long) time for writeout.
855 */ 856 */
856 xfs_iflags_set(ip, XFS_ITRUNCATED); 857 xfs_iflags_set(ip, XFS_ITRUNCATED);
858
859 /* A truncate down always removes post-EOF blocks. */
860 xfs_inode_clear_eofblocks_tag(ip);
857 } 861 }
858 862
859 if (mask & ATTR_CTIME) { 863 if (mask & ATTR_CTIME) {
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 7d36ccf57f93..6f46e034b766 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -130,6 +130,8 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_get_tag);
130DEFINE_PERAG_REF_EVENT(xfs_perag_put); 130DEFINE_PERAG_REF_EVENT(xfs_perag_put);
131DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim); 131DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim);
132DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim); 132DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
133DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks);
134DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks);
133 135
134TRACE_EVENT(xfs_attr_list_node_descend, 136TRACE_EVENT(xfs_attr_list_node_descend,
135 TP_PROTO(struct xfs_attr_list_context *ctx, 137 TP_PROTO(struct xfs_attr_list_context *ctx,
@@ -585,6 +587,9 @@ DEFINE_INODE_EVENT(xfs_update_time);
585DEFINE_INODE_EVENT(xfs_dquot_dqalloc); 587DEFINE_INODE_EVENT(xfs_dquot_dqalloc);
586DEFINE_INODE_EVENT(xfs_dquot_dqdetach); 588DEFINE_INODE_EVENT(xfs_dquot_dqdetach);
587 589
590DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag);
591DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag);
592
588DECLARE_EVENT_CLASS(xfs_iref_class, 593DECLARE_EVENT_CLASS(xfs_iref_class,
589 TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), 594 TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip),
590 TP_ARGS(ip, caller_ip), 595 TP_ARGS(ip, caller_ip),
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 2ee1f49da0aa..e6e1d11dfdf2 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -238,6 +238,8 @@ xfs_free_eofblocks(
238 } else { 238 } else {
239 error = xfs_trans_commit(tp, 239 error = xfs_trans_commit(tp,
240 XFS_TRANS_RELEASE_LOG_RES); 240 XFS_TRANS_RELEASE_LOG_RES);
241 if (!error)
242 xfs_inode_clear_eofblocks_tag(ip);
241 } 243 }
242 244
243 xfs_iunlock(ip, XFS_ILOCK_EXCL); 245 xfs_iunlock(ip, XFS_ILOCK_EXCL);