Skip to content

Commit

Permalink
xfs: add background scanning to clear eofblocks inodes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Brian Foster authored and Ben Myers committed Nov 8, 2012
1 parent 00ca79a commit 579b62f
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 1 deletion.
4 changes: 3 additions & 1 deletion fs/xfs/xfs_globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
/*
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
* other XFS code uses these values. Times are measured in centisecs (i.e.
* 100ths of a second).
* 100ths of a second) with the exception of eofb_timer, which is measured in
* seconds.
*/
xfs_param_t xfs_params = {
/* MIN DFLT MAX */
Expand All @@ -40,4 +41,5 @@ xfs_param_t xfs_params = {
.rotorstep = { 1, 1, 255 },
.inherit_nodfrg = { 0, 1, 1 },
.fstrm_timer = { 1, 30*100, 3600*100},
.eofb_timer = { 1, 300, 3600*24},
};
29 changes: 29 additions & 0 deletions fs/xfs/xfs_icache.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,32 @@ xfs_inode_ag_walk(
return last_error;
}

/*
* Background scanning to trim post-EOF preallocated space. This is queued
* based on the 'background_prealloc_discard_period' tunable (5m by default).
*/
STATIC void
xfs_queue_eofblocks(
struct xfs_mount *mp)
{
rcu_read_lock();
if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_EOFBLOCKS_TAG))
queue_delayed_work(mp->m_eofblocks_workqueue,
&mp->m_eofblocks_work,
msecs_to_jiffies(xfs_eofb_secs * 1000));
rcu_read_unlock();
}

void
xfs_eofblocks_worker(
struct work_struct *work)
{
struct xfs_mount *mp = container_of(to_delayed_work(work),
struct xfs_mount, m_eofblocks_work);
xfs_icache_free_eofblocks(mp, NULL);
xfs_queue_eofblocks(mp);
}

int
xfs_inode_ag_iterator(
struct xfs_mount *mp,
Expand Down Expand Up @@ -1273,6 +1299,9 @@ xfs_inode_set_eofblocks_tag(
XFS_ICI_EOFBLOCKS_TAG);
spin_unlock(&ip->i_mount->m_perag_lock);

/* kick off background trimming */
xfs_queue_eofblocks(ip->i_mount);

trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno,
-1, _RET_IP_);
}
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/xfs_icache.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *);
void xfs_eofblocks_worker(struct work_struct *);

int xfs_sync_inode_grab(struct xfs_inode *ip);
int xfs_inode_ag_iterator(struct xfs_mount *mp,
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/xfs_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#define xfs_rotorstep xfs_params.rotorstep.val
#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val
#define xfs_eofb_secs xfs_params.eofb_timer.val

#define current_cpu() (raw_smp_processor_id())
#define current_pid() (current->pid)
Expand Down
2 changes: 2 additions & 0 deletions fs/xfs/xfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,8 @@ xfs_unmountfs(
__uint64_t resblks;
int error;

cancel_delayed_work_sync(&mp->m_eofblocks_work);

xfs_qm_unmount_quotas(mp);
xfs_rtunmount_inodes(mp);
IRELE(mp->m_rootip);
Expand Down
3 changes: 3 additions & 0 deletions fs/xfs/xfs_mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ typedef struct xfs_mount {
#endif
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
struct delayed_work m_reclaim_work; /* background inode reclaim */
struct delayed_work m_eofblocks_work; /* background eof blocks
trimming */
__int64_t m_update_flags; /* sb flags we need to update
on the next remount,rw */
struct shrinker m_inode_shrink; /* inode reclaim shrinker */
Expand All @@ -207,6 +209,7 @@ typedef struct xfs_mount {
struct workqueue_struct *m_cil_workqueue;
struct workqueue_struct *m_reclaim_workqueue;
struct workqueue_struct *m_log_workqueue;
struct workqueue_struct *m_eofblocks_workqueue;
} xfs_mount_t;

/*
Expand Down
9 changes: 9 additions & 0 deletions fs/xfs/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,8 +874,15 @@ xfs_init_mount_workqueues(
if (!mp->m_log_workqueue)
goto out_destroy_reclaim;

mp->m_eofblocks_workqueue = alloc_workqueue("xfs-eofblocks/%s",
WQ_NON_REENTRANT, 0, mp->m_fsname);
if (!mp->m_eofblocks_workqueue)
goto out_destroy_log;

return 0;

out_destroy_log:
destroy_workqueue(mp->m_log_workqueue);
out_destroy_reclaim:
destroy_workqueue(mp->m_reclaim_workqueue);
out_destroy_cil:
Expand All @@ -892,6 +899,7 @@ STATIC void
xfs_destroy_mount_workqueues(
struct xfs_mount *mp)
{
destroy_workqueue(mp->m_eofblocks_workqueue);
destroy_workqueue(mp->m_log_workqueue);
destroy_workqueue(mp->m_reclaim_workqueue);
destroy_workqueue(mp->m_cil_workqueue);
Expand Down Expand Up @@ -1393,6 +1401,7 @@ xfs_fs_fill_super(
mutex_init(&mp->m_growlock);
atomic_set(&mp->m_active_trans, 0);
INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);

mp->m_super = sb;
sb->s_fs_info = mp;
Expand Down
9 changes: 9 additions & 0 deletions fs/xfs/xfs_sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,15 @@ static ctl_table xfs_table[] = {
.extra1 = &xfs_params.fstrm_timer.min,
.extra2 = &xfs_params.fstrm_timer.max,
},
{
.procname = "speculative_prealloc_lifetime",
.data = &xfs_params.eofb_timer.val,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &xfs_params.eofb_timer.min,
.extra2 = &xfs_params.eofb_timer.max,
},
/* please keep this the last entry */
#ifdef CONFIG_PROC_FS
{
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/xfs_sysctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef struct xfs_param {
xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */
xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */
xfs_sysctl_val_t eofb_timer; /* Interval between eofb scan wakeups */
} xfs_param_t;

/*
Expand Down

0 comments on commit 579b62f

Please sign in to comment.