]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/xfs/quota/xfs_qm.c
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / fs / xfs / quota / xfs_qm.c
index 9a92407109a19921b2a0914711be6ce70b1b1f12..f8e854b4fde87c49f17ff07dc87893b172bb6203 100644 (file)
@@ -55,8 +55,6 @@ uint          ndquot;
 kmem_zone_t    *qm_dqzone;
 kmem_zone_t    *qm_dqtrxzone;
 
-static cred_t  xfs_zerocr;
-
 STATIC void    xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void    xfs_qm_list_destroy(xfs_dqlist_t *);
 
@@ -837,7 +835,7 @@ xfs_qm_dqattach_locked(
                        xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
                                                flags & XFS_QMOPT_DQALLOC,
                                                ip->i_udquot, &ip->i_gdquot) :
-                       xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
+                       xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
                                                flags & XFS_QMOPT_DQALLOC,
                                                ip->i_udquot, &ip->i_gdquot);
                /*
@@ -1199,87 +1197,6 @@ xfs_qm_list_destroy(
        mutex_destroy(&(list->qh_lock));
 }
 
-
-/*
- * Stripped down version of dqattach. This doesn't attach, or even look at the
- * dquots attached to the inode. The rationale is that there won't be any
- * attached at the time this is called from quotacheck.
- */
-STATIC int
-xfs_qm_dqget_noattach(
-       xfs_inode_t     *ip,
-       xfs_dquot_t     **O_udqpp,
-       xfs_dquot_t     **O_gdqpp)
-{
-       int             error;
-       xfs_mount_t     *mp;
-       xfs_dquot_t     *udqp, *gdqp;
-
-       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-       mp = ip->i_mount;
-       udqp = NULL;
-       gdqp = NULL;
-
-       if (XFS_IS_UQUOTA_ON(mp)) {
-               ASSERT(ip->i_udquot == NULL);
-               /*
-                * We want the dquot allocated if it doesn't exist.
-                */
-               if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_uid, XFS_DQ_USER,
-                                        XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN,
-                                        &udqp))) {
-                       /*
-                        * Shouldn't be able to turn off quotas here.
-                        */
-                       ASSERT(error != ESRCH);
-                       ASSERT(error != ENOENT);
-                       return error;
-               }
-               ASSERT(udqp);
-       }
-
-       if (XFS_IS_OQUOTA_ON(mp)) {
-               ASSERT(ip->i_gdquot == NULL);
-               if (udqp)
-                       xfs_dqunlock(udqp);
-               error = XFS_IS_GQUOTA_ON(mp) ?
-                               xfs_qm_dqget(mp, ip,
-                                            ip->i_d.di_gid, XFS_DQ_GROUP,
-                                            XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-                                            &gdqp) :
-                               xfs_qm_dqget(mp, ip,
-                                            ip->i_d.di_projid, XFS_DQ_PROJ,
-                                            XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-                                            &gdqp);
-               if (error) {
-                       if (udqp)
-                               xfs_qm_dqrele(udqp);
-                       ASSERT(error != ESRCH);
-                       ASSERT(error != ENOENT);
-                       return error;
-               }
-               ASSERT(gdqp);
-
-               /* Reacquire the locks in the right order */
-               if (udqp) {
-                       if (! xfs_qm_dqlock_nowait(udqp)) {
-                               xfs_dqunlock(gdqp);
-                               xfs_dqlock(udqp);
-                               xfs_dqlock(gdqp);
-                       }
-               }
-       }
-
-       *O_udqpp = udqp;
-       *O_gdqpp = gdqp;
-
-#ifdef QUOTADEBUG
-       if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp));
-       if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp));
-#endif
-       return 0;
-}
-
 /*
  * Create an inode and return with a reference already taken, but unlocked
  * This is how we create quota inodes
@@ -1305,8 +1222,8 @@ xfs_qm_qino_alloc(
                return error;
        }
 
-       if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
-                                  &xfs_zerocr, 0, 1, ip, &committed))) {
+       error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
+       if (error) {
                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
                                 XFS_TRANS_ABORT);
                return error;
@@ -1516,7 +1433,7 @@ xfs_qm_dqiterate(
                                rablkcnt =  map[i+1].br_blockcount;
                                rablkno = map[i+1].br_startblock;
                                while (rablkcnt--) {
-                                       xfs_baread(mp->m_ddev_targp,
+                                       xfs_buf_readahead(mp->m_ddev_targp,
                                               XFS_FSB_TO_DADDR(mp, rablkno),
                                               mp->m_quotainfo->qi_dqchunklen);
                                        rablkno++;
@@ -1546,18 +1463,34 @@ xfs_qm_dqiterate(
 
 /*
  * Called by dqusage_adjust in doing a quotacheck.
- * Given the inode, and a dquot (either USR or GRP, doesn't matter),
- * this updates its incore copy as well as the buffer copy. This is
- * so that once the quotacheck is done, we can just log all the buffers,
- * as opposed to logging numerous updates to individual dquots.
+ *
+ * Given the inode, and a dquot id this updates both the incore dqout as well
+ * as the buffer copy. This is so that once the quotacheck is done, we can
+ * just log all the buffers, as opposed to logging numerous updates to
+ * individual dquots.
  */
-STATIC void
+STATIC int
 xfs_qm_quotacheck_dqadjust(
-       xfs_dquot_t             *dqp,
+       struct xfs_inode        *ip,
+       xfs_dqid_t              id,
+       uint                    type,
        xfs_qcnt_t              nblks,
        xfs_qcnt_t              rtblks)
 {
-       ASSERT(XFS_DQ_IS_LOCKED(dqp));
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_dquot        *dqp;
+       int                     error;
+
+       error = xfs_qm_dqget(mp, ip, id, type,
+                            XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, &dqp);
+       if (error) {
+               /*
+                * Shouldn't be able to turn off quotas here.
+                */
+               ASSERT(error != ESRCH);
+               ASSERT(error != ENOENT);
+               return error;
+       }
 
        trace_xfs_dqadjust(dqp);
 
@@ -1582,11 +1515,13 @@ xfs_qm_quotacheck_dqadjust(
         * There are no timers for the default values set in the root dquot.
         */
        if (dqp->q_core.d_id) {
-               xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
-               xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
+               xfs_qm_adjust_dqlimits(mp, &dqp->q_core);
+               xfs_qm_adjust_dqtimers(mp, &dqp->q_core);
        }
 
        dqp->dq_flags |= XFS_DQ_DIRTY;
+       xfs_qm_dqput(dqp);
+       return 0;
 }
 
 STATIC int
@@ -1629,8 +1564,7 @@ xfs_qm_dqusage_adjust(
        int             *res)           /* result code value */
 {
        xfs_inode_t     *ip;
-       xfs_dquot_t     *udqp, *gdqp;
-       xfs_qcnt_t      nblks, rtblks;
+       xfs_qcnt_t      nblks, rtblks = 0;
        int             error;
 
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
@@ -1650,51 +1584,24 @@ xfs_qm_dqusage_adjust(
         * the case in all other instances. It's OK that we do this because
         * quotacheck is done only at mount time.
         */
-       if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
+       error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip);
+       if (error) {
                *res = BULKSTAT_RV_NOTHING;
                return error;
        }
 
-       /*
-        * Obtain the locked dquots. In case of an error (eg. allocation
-        * fails for ENOSPC), we return the negative of the error number
-        * to bulkstat, so that it can get propagated to quotacheck() and
-        * making us disable quotas for the file system.
-        */
-       if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) {
-               xfs_iunlock(ip, XFS_ILOCK_EXCL);
-               IRELE(ip);
-               *res = BULKSTAT_RV_GIVEUP;
-               return error;
-       }
+       ASSERT(ip->i_delayed_blks == 0);
 
-       rtblks = 0;
-       if (! XFS_IS_REALTIME_INODE(ip)) {
-               nblks = (xfs_qcnt_t)ip->i_d.di_nblocks;
-       } else {
+       if (XFS_IS_REALTIME_INODE(ip)) {
                /*
                 * Walk thru the extent list and count the realtime blocks.
                 */
-               if ((error = xfs_qm_get_rtblks(ip, &rtblks))) {
-                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                       IRELE(ip);
-                       if (udqp)
-                               xfs_qm_dqput(udqp);
-                       if (gdqp)
-                               xfs_qm_dqput(gdqp);
-                       *res = BULKSTAT_RV_GIVEUP;
-                       return error;
-               }
-               nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
+               error = xfs_qm_get_rtblks(ip, &rtblks);
+               if (error)
+                       goto error0;
        }
-       ASSERT(ip->i_delayed_blks == 0);
 
-       /*
-        * We can't release the inode while holding its dquot locks.
-        * The inode can go into inactive and might try to acquire the dquotlocks.
-        * So, just unlock here and do a vn_rele at the end.
-        */
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
 
        /*
         * Add the (disk blocks and inode) resources occupied by this
@@ -1709,26 +1616,36 @@ xfs_qm_dqusage_adjust(
         * and quotaoffs don't race. (Quotachecks happen at mount time only).
         */
        if (XFS_IS_UQUOTA_ON(mp)) {
-               ASSERT(udqp);
-               xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
-               xfs_qm_dqput(udqp);
+               error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_uid,
+                                                  XFS_DQ_USER, nblks, rtblks);
+               if (error)
+                       goto error0;
        }
-       if (XFS_IS_OQUOTA_ON(mp)) {
-               ASSERT(gdqp);
-               xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
-               xfs_qm_dqput(gdqp);
+
+       if (XFS_IS_GQUOTA_ON(mp)) {
+               error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_gid,
+                                                  XFS_DQ_GROUP, nblks, rtblks);
+               if (error)
+                       goto error0;
        }
-       /*
-        * Now release the inode. This will send it to 'inactive', and
-        * possibly even free blocks.
-        */
-       IRELE(ip);
 
-       /*
-        * Goto next inode.
-        */
+       if (XFS_IS_PQUOTA_ON(mp)) {
+               error = xfs_qm_quotacheck_dqadjust(ip, xfs_get_projid(ip),
+                                                  XFS_DQ_PROJ, nblks, rtblks);
+               if (error)
+                       goto error0;
+       }
+
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       IRELE(ip);
        *res = BULKSTAT_RV_DIDONE;
        return 0;
+
+error0:
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       IRELE(ip);
+       *res = BULKSTAT_RV_GIVEUP;
+       return error;
 }
 
 /*
@@ -2224,7 +2141,7 @@ xfs_qm_write_sb_changes(
 
 
 /*
- * Given an inode, a uid and gid (from cred_t) make sure that we have
+ * Given an inode, a uid, gid and prid make sure that we have
  * allocated relevant dquot(s) on disk, and that we won't exceed inode
  * quotas by creating this file.
  * This also attaches dquot(s) to the given inode after locking it,
@@ -2332,7 +2249,7 @@ xfs_qm_vop_dqalloc(
                        xfs_dqunlock(gq);
                }
        } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
-               if (ip->i_d.di_projid != prid) {
+               if (xfs_get_projid(ip) != prid) {
                        xfs_iunlock(ip, lockflags);
                        if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
                                                 XFS_DQ_PROJ,
@@ -2454,7 +2371,7 @@ xfs_qm_vop_chown_reserve(
        }
        if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
                if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-                    ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+                    xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
                        prjflags = XFS_QMOPT_ENOSPC;
 
                if (prjflags ||
@@ -2558,7 +2475,7 @@ xfs_qm_vop_create_dqattach(
                ip->i_gdquot = gdqp;
                ASSERT(XFS_IS_OQUOTA_ON(mp));
                ASSERT((XFS_IS_GQUOTA_ON(mp) ?
-                       ip->i_d.di_gid : ip->i_d.di_projid) ==
+                       ip->i_d.di_gid : xfs_get_projid(ip)) ==
                                be32_to_cpu(gdqp->q_core.d_id));
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }