/*
  * 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     */
        .rotorstep      = {     1,              1,              255     },
        .inherit_nodfrg = {     0,              1,              1       },
        .fstrm_timer    = {     1,              30*100,         3600*100},
+       .eofb_timer     = {     1,              300,            3600*24},
 };
 
        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,
                                   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_);
        }
 
 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,
 
 #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)
 
        __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);
 
 #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 */
        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;
 
 /*
 
        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:
 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);
        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;
 
                .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
        {
 
        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;
 
 /*