linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / xfs / quota / xfs_trans_dquot.c
index 416cc95..3290975 100644 (file)
@@ -1,39 +1,25 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.
+ * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.         Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
 #include "xfs.h"
 #include "xfs_fs.h"
-#include "xfs_inum.h"
+#include "xfs_bit.h"
 #include "xfs_log.h"
+#include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
 #include "xfs_dmapi.h"
 #include "xfs_quota.h"
 #include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
+#include "xfs_ialloc.h"
+#include "xfs_itable.h"
+#include "xfs_btree.h"
 #include "xfs_bmap.h"
-#include "xfs_bit.h"
 #include "xfs_rtalloc.h"
 #include "xfs_error.h"
-#include "xfs_itable.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
 #include "xfs_cap.h"
@@ -65,7 +50,6 @@
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_priv.h"
-
 #include "xfs_qm.h"
 
 STATIC void    xfs_trans_alloc_dqinfo(xfs_trans_t *);
@@ -187,7 +171,7 @@ xfs_trans_dup_dqinfo(
 /*
  * Wrap around mod_dquot to account for both user and group quotas.
  */
-void
+STATIC void
 xfs_trans_mod_dquot_byino(
        xfs_trans_t     *tp,
        xfs_inode_t     *ip,
@@ -207,12 +191,10 @@ xfs_trans_mod_dquot_byino(
        if (tp->t_dqinfo == NULL)
                xfs_trans_alloc_dqinfo(tp);
 
-       if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) {
+       if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
                (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
-       }
-       if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
+       if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
                (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
-       }
 }
 
 STATIC xfs_dqtrx_t *
@@ -368,7 +350,7 @@ xfs_trans_dqlockedjoin(
  * Unreserve just the reservations done by this transaction.
  * dquot is still left locked at exit.
  */
-void
+STATIC void
 xfs_trans_apply_dquot_deltas(
        xfs_trans_t             *tp)
 {
@@ -431,30 +413,34 @@ xfs_trans_apply_dquot_deltas(
                                qtrx->qt_delrtb_delta;
 #ifdef QUOTADEBUG
                        if (totalbdelta < 0)
-                               ASSERT(INT_GET(d->d_bcount, ARCH_CONVERT) >=
+                               ASSERT(be64_to_cpu(d->d_bcount) >=
                                       (xfs_qcnt_t) -totalbdelta);
 
                        if (totalrtbdelta < 0)
-                               ASSERT(INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+                               ASSERT(be64_to_cpu(d->d_rtbcount) >=
                                       (xfs_qcnt_t) -totalrtbdelta);
 
                        if (qtrx->qt_icount_delta < 0)
-                               ASSERT(INT_GET(d->d_icount, ARCH_CONVERT) >=
+                               ASSERT(be64_to_cpu(d->d_icount) >=
                                       (xfs_qcnt_t) -qtrx->qt_icount_delta);
 #endif
                        if (totalbdelta)
-                               INT_MOD(d->d_bcount, ARCH_CONVERT, (xfs_qcnt_t)totalbdelta);
+                               be64_add(&d->d_bcount, (xfs_qcnt_t)totalbdelta);
 
                        if (qtrx->qt_icount_delta)
-                               INT_MOD(d->d_icount, ARCH_CONVERT, (xfs_qcnt_t)qtrx->qt_icount_delta);
+                               be64_add(&d->d_icount, (xfs_qcnt_t)qtrx->qt_icount_delta);
 
                        if (totalrtbdelta)
-                               INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);
+                               be64_add(&d->d_rtbcount, (xfs_qcnt_t)totalrtbdelta);
 
                        /*
+                        * Get any default limits in use.
                         * Start/reset the timer(s) if needed.
                         */
-                       xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+                       if (d->d_id) {
+                               xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+                               xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+                       }
 
                        dqp->dq_flags |= XFS_DQ_DIRTY;
                        /*
@@ -495,7 +481,7 @@ xfs_trans_apply_dquot_deltas(
                         * Adjust the RT reservation.
                         */
                        if (qtrx->qt_rtblk_res != 0) {
-                               if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
+                               if (qtrx->qt_rtblk_res != qtrx->qt_rtblk_res_used) {
                                        if (qtrx->qt_rtblk_res >
                                            qtrx->qt_rtblk_res_used)
                                               dqp->q_res_rtbcount -= (xfs_qcnt_t)
@@ -528,18 +514,12 @@ xfs_trans_apply_dquot_deltas(
                                            (xfs_qcnt_t)qtrx->qt_icount_delta;
                        }
 
-
-#ifdef QUOTADEBUG
-                       if (qtrx->qt_rtblk_res != 0)
-                               cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
-                                       (int) qtrx->qt_rtblk_res, dqp);
-#endif
                        ASSERT(dqp->q_res_bcount >=
-                               INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
+                               be64_to_cpu(dqp->q_core.d_bcount));
                        ASSERT(dqp->q_res_icount >=
-                               INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
+                               be64_to_cpu(dqp->q_core.d_icount));
                        ASSERT(dqp->q_res_rtbcount >=
-                               INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
+                               be64_to_cpu(dqp->q_core.d_rtbcount));
                }
                /*
                 * Do the group quotas next
@@ -625,6 +605,7 @@ xfs_trans_unreserve_and_mod_dquots(
 STATIC int
 xfs_trans_dqresv(
        xfs_trans_t     *tp,
+       xfs_mount_t     *mp,
        xfs_dquot_t     *dqp,
        long            nblks,
        long            ninos,
@@ -633,29 +614,45 @@ xfs_trans_dqresv(
        int             error;
        xfs_qcnt_t      hardlimit;
        xfs_qcnt_t      softlimit;
-       time_t          btimer;
+       time_t          timer;
+       xfs_qwarncnt_t  warns;
+       xfs_qwarncnt_t  warnlimit;
+       xfs_qcnt_t      count;
        xfs_qcnt_t      *resbcountp;
+       xfs_quotainfo_t *q = mp->m_quotainfo;
 
        if (! (flags & XFS_QMOPT_DQLOCK)) {
                xfs_dqlock(dqp);
        }
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
        if (flags & XFS_TRANS_DQ_RES_BLKS) {
-               hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT);
-               softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
-               btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+               hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
+               if (!hardlimit)
+                       hardlimit = q->qi_bhardlimit;
+               softlimit = be64_to_cpu(dqp->q_core.d_blk_softlimit);
+               if (!softlimit)
+                       softlimit = q->qi_bsoftlimit;
+               timer = be32_to_cpu(dqp->q_core.d_btimer);
+               warns = be16_to_cpu(dqp->q_core.d_bwarns);
+               warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);
                resbcountp = &dqp->q_res_bcount;
        } else {
                ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
-               hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT);
-               softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
-               btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+               hardlimit = be64_to_cpu(dqp->q_core.d_rtb_hardlimit);
+               if (!hardlimit)
+                       hardlimit = q->qi_rtbhardlimit;
+               softlimit = be64_to_cpu(dqp->q_core.d_rtb_softlimit);
+               if (!softlimit)
+                       softlimit = q->qi_rtbsoftlimit;
+               timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
+               warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
+               warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);
                resbcountp = &dqp->q_res_rtbcount;
        }
        error = 0;
 
        if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
-           !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT) &&
+           dqp->q_core.d_id &&
            XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) {
 #ifdef QUOTADEBUG
                cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
@@ -679,33 +676,34 @@ xfs_trans_dqresv(
                                 * If timer or warnings has expired,
                                 * return EDQUOT
                                 */
-                               if ((btimer != 0 && get_seconds() > btimer) ||
-                                   (!INT_ISZERO(dqp->q_core.d_bwarns, ARCH_CONVERT) &&
-                                    INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
-                                    XFS_QI_BWARNLIMIT(dqp->q_mount))) {
+                               if ((timer != 0 && get_seconds() > timer) ||
+                                   (warns != 0 && warns >= warnlimit)) {
                                        error = EDQUOT;
                                        goto error_return;
                                }
                        }
                }
                if (ninos > 0) {
-                       if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL &&
-                           INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-                           INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) {
+                       count = be64_to_cpu(dqp->q_core.d_icount);
+                       timer = be32_to_cpu(dqp->q_core.d_itimer);
+                       warns = be16_to_cpu(dqp->q_core.d_iwarns);
+                       warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);
+                       hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
+                       if (!hardlimit)
+                               hardlimit = q->qi_ihardlimit;
+                       softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
+                       if (!softlimit)
+                               softlimit = q->qi_isoftlimit;
+                       if (hardlimit > 0ULL && count >= hardlimit) {
                                error = EDQUOT;
                                goto error_return;
-                       } else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL &&
-                                  INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-                                  INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
+                       } else if (softlimit > 0ULL && count >= softlimit) {
                                /*
                                 * If timer or warnings has expired,
                                 * return EDQUOT
                                 */
-                               if ((!INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
-                                    get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
-                                   (!INT_ISZERO(dqp->q_core.d_iwarns, ARCH_CONVERT) &&
-                                    INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
-                                    XFS_QI_IWARNLIMIT(dqp->q_mount))) {
+                               if ((timer != 0 && get_seconds() > timer) ||
+                                    (warns != 0 && warns >= warnlimit)) {
                                        error = EDQUOT;
                                        goto error_return;
                                }
@@ -740,9 +738,9 @@ xfs_trans_dqresv(
                                            XFS_TRANS_DQ_RES_INOS,
                                            ninos);
        }
-       ASSERT(dqp->q_res_bcount >= INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
-       ASSERT(dqp->q_res_rtbcount >= INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
-       ASSERT(dqp->q_res_icount >= INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
+       ASSERT(dqp->q_res_bcount >= be64_to_cpu(dqp->q_core.d_bcount));
+       ASSERT(dqp->q_res_rtbcount >= be64_to_cpu(dqp->q_core.d_rtbcount));
+       ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount));
 
 error_return:
        if (! (flags & XFS_QMOPT_DQLOCK)) {
@@ -786,19 +784,20 @@ xfs_trans_reserve_quota_bydquots(
        resvd = 0;
 
        if (udqp) {
-               if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags))
+               if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
                        return (EDQUOT);
                resvd = 1;
        }
 
        if (gdqp) {
-               if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) {
+               if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
                        /*
                         * can't do it, so backout previous reservation
                         */
                        if (resvd) {
-                               xfs_trans_dqresv(tp, udqp,  -nblks, -ninos,
-                                                flags);
+                               flags |= XFS_QMOPT_FORCE_RES;
+                               xfs_trans_dqresv(tp, mp, udqp,
+                                                -nblks, -ninos, flags);
                        }
                        return (EDQUOT);
                }