{
        struct xfs_quotainfo    *q = mp->m_quotainfo;
        struct xfs_disk_dquot   *d = &dq->q_core;
+       int                     prealloc = 0;
 
        ASSERT(d->d_id);
 
-       if (q->qi_bsoftlimit && !d->d_blk_softlimit)
+       if (q->qi_bsoftlimit && !d->d_blk_softlimit) {
                d->d_blk_softlimit = cpu_to_be64(q->qi_bsoftlimit);
-       if (q->qi_bhardlimit && !d->d_blk_hardlimit)
+               prealloc = 1;
+       }
+       if (q->qi_bhardlimit && !d->d_blk_hardlimit) {
                d->d_blk_hardlimit = cpu_to_be64(q->qi_bhardlimit);
+               prealloc = 1;
+       }
        if (q->qi_isoftlimit && !d->d_ino_softlimit)
                d->d_ino_softlimit = cpu_to_be64(q->qi_isoftlimit);
        if (q->qi_ihardlimit && !d->d_ino_hardlimit)
                d->d_rtb_softlimit = cpu_to_be64(q->qi_rtbsoftlimit);
        if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit)
                d->d_rtb_hardlimit = cpu_to_be64(q->qi_rtbhardlimit);
+
+       if (prealloc)
+               xfs_dquot_set_prealloc_limits(dq);
 }
 
 /*
        xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
 }
 
+/*
+ * Initialize the dynamic speculative preallocation thresholds. The lo/hi
+ * watermarks correspond to the soft and hard limits by default. If a soft limit
+ * is not specified, we use 95% of the hard limit.
+ */
+void
+xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
+{
+       __uint64_t space;
+
+       dqp->q_prealloc_hi_wmark = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
+       dqp->q_prealloc_lo_wmark = be64_to_cpu(dqp->q_core.d_blk_softlimit);
+       if (!dqp->q_prealloc_lo_wmark) {
+               dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
+               do_div(dqp->q_prealloc_lo_wmark, 100);
+               dqp->q_prealloc_lo_wmark *= 95;
+       }
+
+       space = dqp->q_prealloc_hi_wmark;
+
+       do_div(space, 100);
+       dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
+       dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
+       dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
+}
+
 static void
 xfs_dquot_buf_verify(
        struct xfs_buf          *bp)
        dqp->q_res_icount = be64_to_cpu(ddqp->d_icount);
        dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
 
+       /* initialize the dquot speculative prealloc thresholds */
+       xfs_dquot_set_prealloc_limits(dqp);
+
        /* Mark the buf so that this will stay incore a little longer */
        xfs_buf_set_ref(bp, XFS_DQUOT_REF);
 
 
 struct xfs_mount;
 struct xfs_trans;
 
+enum {
+       XFS_QLOWSP_1_PCNT = 0,
+       XFS_QLOWSP_3_PCNT,
+       XFS_QLOWSP_5_PCNT,
+       XFS_QLOWSP_MAX
+};
+
 /*
  * The incore dquot structure
  */
        xfs_qcnt_t       q_res_bcount;  /* total regular nblks used+reserved */
        xfs_qcnt_t       q_res_icount;  /* total inos allocd+reserved */
        xfs_qcnt_t       q_res_rtbcount;/* total realtime blks used+reserved */
+       xfs_qcnt_t       q_prealloc_lo_wmark;/* prealloc throttle wmark */
+       xfs_qcnt_t       q_prealloc_hi_wmark;/* prealloc disabled wmark */
+       int64_t          q_low_space[XFS_QLOWSP_MAX];
        struct mutex     q_qlock;       /* quota lock */
        struct completion q_flush;      /* flush completion queue */
        atomic_t          q_pincount;   /* dquot pin count */
 
 extern void            xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
 
+extern void            xfs_dquot_set_prealloc_limits(struct xfs_dquot *);
+
 static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
 {
        xfs_dqlock(dqp);
 
 extern int             xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
 extern int             xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
                                        fs_disk_quota_t *);
-extern int             xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint,
+extern int             xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
                                        fs_disk_quota_t *);
 extern int             xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
 extern int             xfs_qm_scall_quotaon(xfs_mount_t *, uint);