io-wq: wait for worker startup when forking a new one
[linux-2.6-microblaze.git] / fs / xfs / xfs_trans_dquot.c
index 28b8ac7..48e09ea 100644 (file)
@@ -16,6 +16,7 @@
 #include "xfs_quota.h"
 #include "xfs_qm.h"
 #include "xfs_trace.h"
+#include "xfs_error.h"
 
 STATIC void    xfs_trans_alloc_dqinfo(xfs_trans_t *);
 
@@ -691,9 +692,11 @@ xfs_trans_dqresv(
                                    nblks);
                xfs_trans_mod_dquot(tp, dqp, XFS_TRANS_DQ_RES_INOS, ninos);
        }
-       ASSERT(dqp->q_blk.reserved >= dqp->q_blk.count);
-       ASSERT(dqp->q_rtb.reserved >= dqp->q_rtb.count);
-       ASSERT(dqp->q_ino.reserved >= dqp->q_ino.count);
+
+       if (XFS_IS_CORRUPT(mp, dqp->q_blk.reserved < dqp->q_blk.count) ||
+           XFS_IS_CORRUPT(mp, dqp->q_rtb.reserved < dqp->q_rtb.count) ||
+           XFS_IS_CORRUPT(mp, dqp->q_ino.reserved < dqp->q_ino.count))
+               goto error_corrupt;
 
        xfs_dqunlock(dqp);
        return 0;
@@ -703,6 +706,10 @@ error_return:
        if (xfs_dquot_type(dqp) == XFS_DQTYPE_PROJ)
                return -ENOSPC;
        return -EDQUOT;
+error_corrupt:
+       xfs_dqunlock(dqp);
+       xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+       return -EFSCORRUPTED;
 }
 
 
@@ -780,28 +787,60 @@ int
 xfs_trans_reserve_quota_nblks(
        struct xfs_trans        *tp,
        struct xfs_inode        *ip,
-       int64_t                 nblks,
-       long                    ninos,
-       uint                    flags)
+       int64_t                 dblocks,
+       int64_t                 rblocks,
+       bool                    force)
 {
        struct xfs_mount        *mp = ip->i_mount;
+       unsigned int            qflags = 0;
+       int                     error;
 
        if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
                return 0;
 
        ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
-
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-       ASSERT((flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_RTBLKS ||
-              (flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_BLKS);
 
-       /*
-        * Reserve nblks against these dquots, with trans as the mediator.
-        */
-       return xfs_trans_reserve_quota_bydquots(tp, mp,
-                                               ip->i_udquot, ip->i_gdquot,
-                                               ip->i_pdquot,
-                                               nblks, ninos, flags);
+       if (force)
+               qflags |= XFS_QMOPT_FORCE_RES;
+
+       /* Reserve data device quota against the inode's dquots. */
+       error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
+                       ip->i_gdquot, ip->i_pdquot, dblocks, 0,
+                       XFS_QMOPT_RES_REGBLKS | qflags);
+       if (error)
+               return error;
+
+       /* Do the same but for realtime blocks. */
+       error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
+                       ip->i_gdquot, ip->i_pdquot, rblocks, 0,
+                       XFS_QMOPT_RES_RTBLKS | qflags);
+       if (error) {
+               xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
+                               ip->i_gdquot, ip->i_pdquot, -dblocks, 0,
+                               XFS_QMOPT_RES_REGBLKS);
+               return error;
+       }
+
+       return 0;
+}
+
+/* Change the quota reservations for an inode creation activity. */
+int
+xfs_trans_reserve_quota_icreate(
+       struct xfs_trans        *tp,
+       struct xfs_dquot        *udqp,
+       struct xfs_dquot        *gdqp,
+       struct xfs_dquot        *pdqp,
+       int64_t                 dblocks)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+
+       if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+               return 0;
+
+       return xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp,
+                       dblocks, 1, XFS_QMOPT_RES_REGBLKS);
 }
 
 /*