aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2012-11-06 09:50:47 -0500
committerBen Myers <bpm@sgi.com>2012-11-08 16:34:59 -0500
commit579b62faa5fb16ffeeb88cda5e2c4e95730881af (patch)
treeb0d71a823d2b6e5718786f99921968109d8f644e /fs/xfs
parent00ca79a04bef1a1b30ef8afd992d905b6d986caf (diff)
xfs: add background scanning to clear eofblocks inodes
Create a new mount workqueue and delayed_work to enable background scanning and freeing of eofblocks inodes. The scanner kicks in once speculative preallocation occurs and stops requeueing itself when no eofblocks inodes exist. The scan interval is based on the new 'speculative_prealloc_lifetime' tunable (default to 5m). The background scanner performs unfiltered, best effort scans (which skips inodes under lock contention or with a dirty cache mapping). Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_globals.c4
-rw-r--r--fs/xfs/xfs_icache.c29
-rw-r--r--fs/xfs/xfs_icache.h1
-rw-r--r--fs/xfs/xfs_linux.h1
-rw-r--r--fs/xfs/xfs_mount.c2
-rw-r--r--fs/xfs/xfs_mount.h3
-rw-r--r--fs/xfs/xfs_super.c9
-rw-r--r--fs/xfs/xfs_sysctl.c9
-rw-r--r--fs/xfs/xfs_sysctl.h1
9 files changed, 58 insertions, 1 deletions
diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c
index 76e81cff70b9..5399ef222dd7 100644
--- a/fs/xfs/xfs_globals.c
+++ b/fs/xfs/xfs_globals.c
@@ -21,7 +21,8 @@
21/* 21/*
22 * Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n, 22 * Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
23 * other XFS code uses these values. Times are measured in centisecs (i.e. 23 * other XFS code uses these values. Times are measured in centisecs (i.e.
24 * 100ths of a second). 24 * 100ths of a second) with the exception of eofb_timer, which is measured in
25 * seconds.
25 */ 26 */
26xfs_param_t xfs_params = { 27xfs_param_t xfs_params = {
27 /* MIN DFLT MAX */ 28 /* MIN DFLT MAX */
@@ -40,4 +41,5 @@ xfs_param_t xfs_params = {
40 .rotorstep = { 1, 1, 255 }, 41 .rotorstep = { 1, 1, 255 },
41 .inherit_nodfrg = { 0, 1, 1 }, 42 .inherit_nodfrg = { 0, 1, 1 },
42 .fstrm_timer = { 1, 30*100, 3600*100}, 43 .fstrm_timer = { 1, 30*100, 3600*100},
44 .eofb_timer = { 1, 300, 3600*24},
43}; 45};
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 906e6dcd2c55..96e344e3e927 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -615,6 +615,32 @@ restart:
615 return last_error; 615 return last_error;
616} 616}
617 617
618/*
619 * Background scanning to trim post-EOF preallocated space. This is queued
620 * based on the 'background_prealloc_discard_period' tunable (5m by default).
621 */
622STATIC void
623xfs_queue_eofblocks(
624 struct xfs_mount *mp)
625{
626 rcu_read_lock();
627 if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_EOFBLOCKS_TAG))
628 queue_delayed_work(mp->m_eofblocks_workqueue,
629 &mp->m_eofblocks_work,
630 msecs_to_jiffies(xfs_eofb_secs * 1000));
631 rcu_read_unlock();
632}
633
634void
635xfs_eofblocks_worker(
636 struct work_struct *work)
637{
638 struct xfs_mount *mp = container_of(to_delayed_work(work),
639 struct xfs_mount, m_eofblocks_work);
640 xfs_icache_free_eofblocks(mp, NULL);
641 xfs_queue_eofblocks(mp);
642}
643
618int 644int
619xfs_inode_ag_iterator( 645xfs_inode_ag_iterator(
620 struct xfs_mount *mp, 646 struct xfs_mount *mp,
@@ -1273,6 +1299,9 @@ xfs_inode_set_eofblocks_tag(
1273 XFS_ICI_EOFBLOCKS_TAG); 1299 XFS_ICI_EOFBLOCKS_TAG);
1274 spin_unlock(&ip->i_mount->m_perag_lock); 1300 spin_unlock(&ip->i_mount->m_perag_lock);
1275 1301
1302 /* kick off background trimming */
1303 xfs_queue_eofblocks(ip->i_mount);
1304
1276 trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno, 1305 trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno,
1277 -1, _RET_IP_); 1306 -1, _RET_IP_);
1278 } 1307 }
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 4934a77024cf..e0f138c70a2f 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -38,6 +38,7 @@ void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
38void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); 38void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
39void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); 39void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
40int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); 40int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *);
41void xfs_eofblocks_worker(struct work_struct *);
41 42
42int xfs_sync_inode_grab(struct xfs_inode *ip); 43int xfs_sync_inode_grab(struct xfs_inode *ip);
43int xfs_inode_ag_iterator(struct xfs_mount *mp, 44int xfs_inode_ag_iterator(struct xfs_mount *mp,
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index 828662f70d64..0a134ca5211c 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -118,6 +118,7 @@
118#define xfs_rotorstep xfs_params.rotorstep.val 118#define xfs_rotorstep xfs_params.rotorstep.val
119#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val 119#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
120#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val 120#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val
121#define xfs_eofb_secs xfs_params.eofb_timer.val
121 122
122#define current_cpu() (raw_smp_processor_id()) 123#define current_cpu() (raw_smp_processor_id())
123#define current_pid() (current->pid) 124#define current_pid() (current->pid)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 6f1c997704cd..41ae7e1590f5 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1428,6 +1428,8 @@ xfs_unmountfs(
1428 __uint64_t resblks; 1428 __uint64_t resblks;
1429 int error; 1429 int error;
1430 1430
1431 cancel_delayed_work_sync(&mp->m_eofblocks_work);
1432
1431 xfs_qm_unmount_quotas(mp); 1433 xfs_qm_unmount_quotas(mp);
1432 xfs_rtunmount_inodes(mp); 1434 xfs_rtunmount_inodes(mp);
1433 IRELE(mp->m_rootip); 1435 IRELE(mp->m_rootip);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index a631ca3b9065..dc306a09f56f 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -196,6 +196,8 @@ typedef struct xfs_mount {
196#endif 196#endif
197 struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ 197 struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
198 struct delayed_work m_reclaim_work; /* background inode reclaim */ 198 struct delayed_work m_reclaim_work; /* background inode reclaim */
199 struct delayed_work m_eofblocks_work; /* background eof blocks
200 trimming */
199 __int64_t m_update_flags; /* sb flags we need to update 201 __int64_t m_update_flags; /* sb flags we need to update
200 on the next remount,rw */ 202 on the next remount,rw */
201 struct shrinker m_inode_shrink; /* inode reclaim shrinker */ 203 struct shrinker m_inode_shrink; /* inode reclaim shrinker */
@@ -207,6 +209,7 @@ typedef struct xfs_mount {
207 struct workqueue_struct *m_cil_workqueue; 209 struct workqueue_struct *m_cil_workqueue;
208 struct workqueue_struct *m_reclaim_workqueue; 210 struct workqueue_struct *m_reclaim_workqueue;
209 struct workqueue_struct *m_log_workqueue; 211 struct workqueue_struct *m_log_workqueue;
212 struct workqueue_struct *m_eofblocks_workqueue;
210} xfs_mount_t; 213} xfs_mount_t;
211 214
212/* 215/*
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 3d9ea947e9f8..ab8839b26272 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -874,8 +874,15 @@ xfs_init_mount_workqueues(
874 if (!mp->m_log_workqueue) 874 if (!mp->m_log_workqueue)
875 goto out_destroy_reclaim; 875 goto out_destroy_reclaim;
876 876
877 mp->m_eofblocks_workqueue = alloc_workqueue("xfs-eofblocks/%s",
878 WQ_NON_REENTRANT, 0, mp->m_fsname);
879 if (!mp->m_eofblocks_workqueue)
880 goto out_destroy_log;
881
877 return 0; 882 return 0;
878 883
884out_destroy_log:
885 destroy_workqueue(mp->m_log_workqueue);
879out_destroy_reclaim: 886out_destroy_reclaim:
880 destroy_workqueue(mp->m_reclaim_workqueue); 887 destroy_workqueue(mp->m_reclaim_workqueue);
881out_destroy_cil: 888out_destroy_cil:
@@ -892,6 +899,7 @@ STATIC void
892xfs_destroy_mount_workqueues( 899xfs_destroy_mount_workqueues(
893 struct xfs_mount *mp) 900 struct xfs_mount *mp)
894{ 901{
902 destroy_workqueue(mp->m_eofblocks_workqueue);
895 destroy_workqueue(mp->m_log_workqueue); 903 destroy_workqueue(mp->m_log_workqueue);
896 destroy_workqueue(mp->m_reclaim_workqueue); 904 destroy_workqueue(mp->m_reclaim_workqueue);
897 destroy_workqueue(mp->m_cil_workqueue); 905 destroy_workqueue(mp->m_cil_workqueue);
@@ -1393,6 +1401,7 @@ xfs_fs_fill_super(
1393 mutex_init(&mp->m_growlock); 1401 mutex_init(&mp->m_growlock);
1394 atomic_set(&mp->m_active_trans, 0); 1402 atomic_set(&mp->m_active_trans, 0);
1395 INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker); 1403 INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
1404 INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);
1396 1405
1397 mp->m_super = sb; 1406 mp->m_super = sb;
1398 sb->s_fs_info = mp; 1407 sb->s_fs_info = mp;
diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c
index ee2d2adaa438..2801b5ce6cdb 100644
--- a/fs/xfs/xfs_sysctl.c
+++ b/fs/xfs/xfs_sysctl.c
@@ -202,6 +202,15 @@ static ctl_table xfs_table[] = {
202 .extra1 = &xfs_params.fstrm_timer.min, 202 .extra1 = &xfs_params.fstrm_timer.min,
203 .extra2 = &xfs_params.fstrm_timer.max, 203 .extra2 = &xfs_params.fstrm_timer.max,
204 }, 204 },
205 {
206 .procname = "speculative_prealloc_lifetime",
207 .data = &xfs_params.eofb_timer.val,
208 .maxlen = sizeof(int),
209 .mode = 0644,
210 .proc_handler = proc_dointvec_minmax,
211 .extra1 = &xfs_params.eofb_timer.min,
212 .extra2 = &xfs_params.eofb_timer.max,
213 },
205 /* please keep this the last entry */ 214 /* please keep this the last entry */
206#ifdef CONFIG_PROC_FS 215#ifdef CONFIG_PROC_FS
207 { 216 {
diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h
index b9937d450f8e..bd8e157c20ef 100644
--- a/fs/xfs/xfs_sysctl.h
+++ b/fs/xfs/xfs_sysctl.h
@@ -47,6 +47,7 @@ typedef struct xfs_param {
47 xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */ 47 xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */
48 xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */ 48 xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
49 xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */ 49 xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */
50 xfs_sysctl_val_t eofb_timer; /* Interval between eofb scan wakeups */
50} xfs_param_t; 51} xfs_param_t;
51 52
52/* 53/*