···595 }596}59700000000598/*599 * This reserves disk blocks and inodes against a dquot.600 * Flags indicate if the dquot is to be locked here and also601 * if the blk reservation is for RT or regular blocks.602 * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.603- * Returns EDQUOT if quota is exceeded.604 */605STATIC int606xfs_trans_dqresv(···673 */674 if (hardlimit > 0ULL &&675 (hardlimit <= nblks + *resbcountp)) {676- error = EDQUOT;677 goto error_return;678 }679680 if (softlimit > 0ULL &&681 (softlimit <= nblks + *resbcountp)) {682- /*683- * If timer or warnings has expired,684- * return EDQUOT685- */686 if ((timer != 0 && get_seconds() > timer) ||687 (warns != 0 && warns >= warnlimit)) {688- error = EDQUOT;689 goto error_return;690 }691 }···698 if (!softlimit)699 softlimit = q->qi_isoftlimit;700 if (hardlimit > 0ULL && count >= hardlimit) {701- error = EDQUOT;702 goto error_return;703 } else if (softlimit > 0ULL && count >= softlimit) {704- /*705- * If timer or warnings has expired,706- * return EDQUOT707- */708 if ((timer != 0 && get_seconds() > timer) ||709 (warns != 0 && warns >= warnlimit)) {710- error = EDQUOT;711 goto error_return;712 }713 }···750751752/*753- * Given a dquot(s), make disk block and/or inode reservations against them.754 * The fact that this does the reservation against both the usr and755- * grp quotas is important, because this follows a both-or-nothing756 * approach.757 *758 * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.759 * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.0760 * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks761 * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks762 * dquots are unlocked on return, if they were not locked by caller.···772 long ninos,773 uint flags)774{775- int resvd;776777- if (! XFS_IS_QUOTA_ON(mp))778- return (0);779780 if (tp && tp->t_dqinfo == NULL)781 xfs_trans_alloc_dqinfo(tp);782783 ASSERT(flags & XFS_QMOPT_RESBLK_MASK);784- resvd = 0;785786 if (udqp) {787- if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))788- return (EDQUOT);00789 resvd = 1;790 }791792 if (gdqp) {793- if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {0794 /*795 * can't do it, so backout previous reservation796 */···801 xfs_trans_dqresv(tp, mp, udqp,802 -nblks, -ninos, flags);803 }804- return (EDQUOT);805 }806 }807808 /*809 * Didn't change anything critical, so, no need to log810 */811- return (0);812}813814···816 * Lock the dquot and change the reservation if we can.817 * This doesn't change the actual usage, just the reservation.818 * The inode sent in is locked.819- *820- * Returns 0 on success, EDQUOT or other errors otherwise821 */822STATIC int823xfs_trans_reserve_quota_nblks(···824 xfs_inode_t *ip,825 long nblks,826 long ninos,827- uint type)828{829 int error;830831 if (!XFS_IS_QUOTA_ON(mp))832- return (0);00833834 ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);835 ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);836837 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));838 ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));839- ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||840- (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);00841842 /*843 * Reserve nblks against these dquots, with trans as the mediator.···849 error = xfs_trans_reserve_quota_bydquots(tp, mp,850 ip->i_udquot, ip->i_gdquot,851 nblks, ninos,852- type);853- return (error);854}855856/*
···595 }596}597598+STATIC int599+xfs_quota_error(uint flags)600+{601+ if (flags & XFS_QMOPT_ENOSPC)602+ return ENOSPC;603+ return EDQUOT;604+}605+606/*607 * This reserves disk blocks and inodes against a dquot.608 * Flags indicate if the dquot is to be locked here and also609 * if the blk reservation is for RT or regular blocks.610 * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.0611 */612STATIC int613xfs_trans_dqresv(···666 */667 if (hardlimit > 0ULL &&668 (hardlimit <= nblks + *resbcountp)) {669+ error = xfs_quota_error(flags);670 goto error_return;671 }672673 if (softlimit > 0ULL &&674 (softlimit <= nblks + *resbcountp)) {0000675 if ((timer != 0 && get_seconds() > timer) ||676 (warns != 0 && warns >= warnlimit)) {677+ error = xfs_quota_error(flags);678 goto error_return;679 }680 }···695 if (!softlimit)696 softlimit = q->qi_isoftlimit;697 if (hardlimit > 0ULL && count >= hardlimit) {698+ error = xfs_quota_error(flags);699 goto error_return;700 } else if (softlimit > 0ULL && count >= softlimit) {0000701 if ((timer != 0 && get_seconds() > timer) ||702 (warns != 0 && warns >= warnlimit)) {703+ error = xfs_quota_error(flags);704 goto error_return;705 }706 }···751752753/*754+ * Given dquot(s), make disk block and/or inode reservations against them.755 * The fact that this does the reservation against both the usr and756+ * grp/prj quotas is important, because this follows a both-or-nothing757 * approach.758 *759 * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.760 * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.761+ * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota.762 * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks763 * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks764 * dquots are unlocked on return, if they were not locked by caller.···772 long ninos,773 uint flags)774{775+ int resvd = 0, error;776777+ if (!XFS_IS_QUOTA_ON(mp))778+ return 0;779780 if (tp && tp->t_dqinfo == NULL)781 xfs_trans_alloc_dqinfo(tp);782783 ASSERT(flags & XFS_QMOPT_RESBLK_MASK);0784785 if (udqp) {786+ error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,787+ (flags & ~XFS_QMOPT_ENOSPC));788+ if (error)789+ return error;790 resvd = 1;791 }792793 if (gdqp) {794+ error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);795+ if (error) {796 /*797 * can't do it, so backout previous reservation798 */···799 xfs_trans_dqresv(tp, mp, udqp,800 -nblks, -ninos, flags);801 }802+ return error;803 }804 }805806 /*807 * Didn't change anything critical, so, no need to log808 */809+ return 0;810}811812···814 * Lock the dquot and change the reservation if we can.815 * This doesn't change the actual usage, just the reservation.816 * The inode sent in is locked.00817 */818STATIC int819xfs_trans_reserve_quota_nblks(···824 xfs_inode_t *ip,825 long nblks,826 long ninos,827+ uint flags)828{829 int error;830831 if (!XFS_IS_QUOTA_ON(mp))832+ return 0;833+ if (XFS_IS_PQUOTA_ON(mp))834+ flags |= XFS_QMOPT_ENOSPC;835836 ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);837 ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);838839 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));840 ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));841+ ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==842+ XFS_TRANS_DQ_RES_RTBLKS ||843+ (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==844+ XFS_TRANS_DQ_RES_BLKS);845846 /*847 * Reserve nblks against these dquots, with trans as the mediator.···845 error = xfs_trans_reserve_quota_bydquots(tp, mp,846 ip->i_udquot, ip->i_gdquot,847 nblks, ninos,848+ flags);849+ return error;850}851852/*
+5-6
fs/xfs/xfs_bmap.c
···4719 /*4720 * Make a transaction-less quota reservation for4721 * delayed allocation blocks. This number gets4722- * adjusted later.4723- * We return EDQUOT if we haven't allocated4724- * blks already inside this loop;4725 */4726- if (XFS_TRANS_RESERVE_QUOTA_NBLKS(4727 mp, NULL, ip, (long)alen, 0,4728 rt ? XFS_QMOPT_RES_RTBLKS :4729- XFS_QMOPT_RES_REGBLKS)) {4730 if (n == 0) {4731 *nmap = 0;4732 ASSERT(cur == NULL);4733- return XFS_ERROR(EDQUOT);4734 }4735 break;4736 }
···4719 /*4720 * Make a transaction-less quota reservation for4721 * delayed allocation blocks. This number gets4722+ * adjusted later. We return if we haven't4723+ * allocated blocks already inside this loop.04724 */4725+ if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(4726 mp, NULL, ip, (long)alen, 0,4727 rt ? XFS_QMOPT_RES_RTBLKS :4728+ XFS_QMOPT_RES_REGBLKS))) {4729 if (n == 0) {4730 *nmap = 0;4731 ASSERT(cur == NULL);4732+ return error;4733 }4734 break;4735 }
+3-2
fs/xfs/xfs_quota.h
···196#define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */197#define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */198#define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */199-#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */200#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */201-#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */202#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */0203204/*205 * flags to xfs_trans_mod_dquot to indicate which field needs to be
···196#define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */197#define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */198#define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */199+#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */200#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */201+#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */202#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */203+#define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */204205/*206 * flags to xfs_trans_mod_dquot to indicate which field needs to be