dquot->dq_dqb.dqb_curspace += number;
 }
 
+static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
+{
+       dquot->dq_dqb.dqb_rsvspace += number;
+}
+
 static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
 {
        if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
        kfree_skb(skb);
 }
 #endif
-
+/*
+ * Write warnings to the console and send warning messages over netlink.
+ *
+ * Note that this function can sleep.
+ */
 static inline void flush_warnings(struct dquot * const *dquots, char *warntype)
 {
        int i;
 /* needs dq_data_lock */
 static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
 {
+       qsize_t tspace;
+
        *warntype = QUOTA_NL_NOWARN;
        if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
            test_bit(DQ_FAKE_B, &dquot->dq_flags))
                return QUOTA_OK;
 
+       tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace
+               + space;
+
        if (dquot->dq_dqb.dqb_bhardlimit &&
-           dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit &&
+           tspace > dquot->dq_dqb.dqb_bhardlimit &&
             !ignore_hardlimit(dquot)) {
                if (!prealloc)
                        *warntype = QUOTA_NL_BHARDWARN;
        }
 
        if (dquot->dq_dqb.dqb_bsoftlimit &&
-           dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
+           tspace > dquot->dq_dqb.dqb_bsoftlimit &&
            dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
             !ignore_hardlimit(dquot)) {
                if (!prealloc)
        }
 
        if (dquot->dq_dqb.dqb_bsoftlimit &&
-           dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
+           tspace > dquot->dq_dqb.dqb_bsoftlimit &&
            dquot->dq_dqb.dqb_btime == 0) {
                if (!prealloc) {
                        *warntype = QUOTA_NL_BSOFTWARN;
 /*
  * This operation can block, but only after everything is updated
  */
-int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+int __dquot_alloc_space(struct inode *inode, qsize_t number,
+                       int warn, int reserve)
 {
-       int cnt, ret = NO_QUOTA;
+       int cnt, ret = QUOTA_OK;
        char warntype[MAXQUOTAS];
 
-       /* First test before acquiring mutex - solves deadlocks when we
-         * re-enter the quota code and are already holding the mutex */
-       if (IS_NOQUOTA(inode)) {
-out_add:
-               inode_add_bytes(inode, number);
-               return QUOTA_OK;
-       }
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                warntype[cnt] = QUOTA_NL_NOWARN;
 
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-       if (IS_NOQUOTA(inode)) {        /* Now we can do reliable test... */
-               up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-               goto out_add;
-       }
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (inode->i_dquot[cnt] == NODQUOT)
                        continue;
-               if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)
-                       goto warn_put_all;
+               if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
+                   == NO_QUOTA) {
+                       ret = NO_QUOTA;
+                       goto out_unlock;
+               }
        }
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (inode->i_dquot[cnt] == NODQUOT)
                        continue;
-               dquot_incr_space(inode->i_dquot[cnt], number);
+               if (reserve)
+                       dquot_resv_space(inode->i_dquot[cnt], number);
+               else
+                       dquot_incr_space(inode->i_dquot[cnt], number);
        }
-       inode_add_bytes(inode, number);
-       ret = QUOTA_OK;
-warn_put_all:
+       if (!reserve)
+               inode_add_bytes(inode, number);
+out_unlock:
        spin_unlock(&dq_data_lock);
-       if (ret == QUOTA_OK)
-               /* Dirtify all the dquots - this can block when journalling */
-               for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-                       if (inode->i_dquot[cnt])
-                               mark_dquot_dirty(inode->i_dquot[cnt]);
        flush_warnings(inode->i_dquot, warntype);
+       return ret;
+}
+
+int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+{
+       int cnt, ret = QUOTA_OK;
+
+       /*
+        * First test before acquiring mutex - solves deadlocks when we
+        * re-enter the quota code and are already holding the mutex
+        */
+       if (IS_NOQUOTA(inode)) {
+               inode_add_bytes(inode, number);
+               goto out;
+       }
+
+       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       if (IS_NOQUOTA(inode)) {
+               inode_add_bytes(inode, number);
+               goto out_unlock;
+       }
+
+       ret = __dquot_alloc_space(inode, number, warn, 0);
+       if (ret == NO_QUOTA)
+               goto out_unlock;
+
+       /* Dirtify all the dquots - this can block when journalling */
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               if (inode->i_dquot[cnt])
+                       mark_dquot_dirty(inode->i_dquot[cnt]);
+out_unlock:
        up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+       return ret;
+}
+
+int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
+{
+       int ret = QUOTA_OK;
+
+       if (IS_NOQUOTA(inode))
+               goto out;
+
+       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       if (IS_NOQUOTA(inode))
+               goto out_unlock;
+
+       ret = __dquot_alloc_space(inode, number, warn, 1);
+out_unlock:
+       up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
        return ret;
 }
+EXPORT_SYMBOL(dquot_reserve_space);
 
 /*
  * This operation can block, but only after everything is updated
        spin_lock(&dq_data_lock);
        di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit);
        di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit);
-       di->dqb_curspace = dm->dqb_curspace;
+       di->dqb_curspace = dm->dqb_curspace + dm->dqb_rsvspace;
        di->dqb_ihardlimit = dm->dqb_ihardlimit;
        di->dqb_isoftlimit = dm->dqb_isoftlimit;
        di->dqb_curinodes = dm->dqb_curinodes;
 
        spin_lock(&dq_data_lock);
        if (di->dqb_valid & QIF_SPACE) {
-               dm->dqb_curspace = di->dqb_curspace;
+               dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace;
                check_blim = 1;
                __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
        }