[XFS] Make project quota enforcement return an error code consistent with its use.

SGI-PV: 951300
SGI-Modid: xfs-linux-melb:xfs-kern:25633a

Signed-off-by: Nathan Scott <nathans@sgi.com>

+54 -47
+10 -7
fs/xfs/quota/xfs_qm.c
··· 2624 { 2625 int error; 2626 xfs_mount_t *mp; 2627 - uint delblks, blkflags; 2628 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; 2629 2630 ASSERT(XFS_ISLOCKED_INODE(ip)); ··· 2650 } 2651 } 2652 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { 2653 - if ((XFS_IS_GQUOTA_ON(ip->i_mount) && 2654 - ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) || 2655 - (XFS_IS_PQUOTA_ON(ip->i_mount) && 2656 - ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) { 2657 delblksgdq = gdqp; 2658 if (delblks) { 2659 ASSERT(ip->i_gdquot); ··· 2667 2668 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 2669 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, 2670 - flags | blkflags))) 2671 return (error); 2672 2673 /* ··· 2684 ASSERT(unresudq || unresgdq); 2685 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2686 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, 2687 - flags | blkflags))) 2688 return (error); 2689 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2690 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
··· 2624 { 2625 int error; 2626 xfs_mount_t *mp; 2627 + uint delblks, blkflags, prjflags = 0; 2628 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; 2629 2630 ASSERT(XFS_ISLOCKED_INODE(ip)); ··· 2650 } 2651 } 2652 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { 2653 + if (XFS_IS_PQUOTA_ON(ip->i_mount) && 2654 + ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id)) 2655 + prjflags = XFS_QMOPT_ENOSPC; 2656 + 2657 + if (prjflags || 2658 + (XFS_IS_GQUOTA_ON(ip->i_mount) && 2659 + ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { 2660 delblksgdq = gdqp; 2661 if (delblks) { 2662 ASSERT(ip->i_gdquot); ··· 2664 2665 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 2666 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, 2667 + flags | blkflags | prjflags))) 2668 return (error); 2669 2670 /* ··· 2681 ASSERT(unresudq || unresgdq); 2682 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2683 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, 2684 + flags | blkflags | prjflags))) 2685 return (error); 2686 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2687 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
+36 -32
fs/xfs/quota/xfs_trans_dquot.c
··· 595 } 596 } 597 598 /* 599 * This reserves disk blocks and inodes against a dquot. 600 * Flags indicate if the dquot is to be locked here and also 601 * 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 */ 605 STATIC int 606 xfs_trans_dqresv( ··· 673 */ 674 if (hardlimit > 0ULL && 675 (hardlimit <= nblks + *resbcountp)) { 676 - error = EDQUOT; 677 goto error_return; 678 } 679 680 if (softlimit > 0ULL && 681 (softlimit <= nblks + *resbcountp)) { 682 - /* 683 - * If timer or warnings has expired, 684 - * return EDQUOT 685 - */ 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 EDQUOT 707 - */ 708 if ((timer != 0 && get_seconds() > timer) || 709 (warns != 0 && warns >= warnlimit)) { 710 - error = EDQUOT; 711 goto error_return; 712 } 713 } ··· 750 751 752 /* 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 and 755 - * grp quotas is important, because this follows a both-or-nothing 756 * 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. 760 * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks 761 * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks 762 * dquots are unlocked on return, if they were not locked by caller. ··· 772 long ninos, 773 uint flags) 774 { 775 - int resvd; 776 777 - if (! XFS_IS_QUOTA_ON(mp)) 778 - return (0); 779 780 if (tp && tp->t_dqinfo == NULL) 781 xfs_trans_alloc_dqinfo(tp); 782 783 ASSERT(flags & XFS_QMOPT_RESBLK_MASK); 784 - resvd = 0; 785 786 if (udqp) { 787 - if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) 788 - return (EDQUOT); 789 resvd = 1; 790 } 791 792 if (gdqp) { 793 - if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) { 794 /* 795 * can't do it, so backout previous reservation 796 */ ··· 801 xfs_trans_dqresv(tp, mp, udqp, 802 -nblks, -ninos, flags); 803 } 804 - return (EDQUOT); 805 } 806 } 807 808 /* 809 * Didn't change anything critical, so, no need to log 810 */ 811 - return (0); 812 } 813 814 ··· 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 otherwise 821 */ 822 STATIC int 823 xfs_trans_reserve_quota_nblks( ··· 824 xfs_inode_t *ip, 825 long nblks, 826 long ninos, 827 - uint type) 828 { 829 int error; 830 831 if (!XFS_IS_QUOTA_ON(mp)) 832 - return (0); 833 834 ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); 835 ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); 836 837 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); 841 842 /* 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 } 855 856 /*
··· 595 } 596 } 597 598 + STATIC int 599 + 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 also 609 * if the blk reservation is for RT or regular blocks. 610 * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. 611 */ 612 STATIC int 613 xfs_trans_dqresv( ··· 666 */ 667 if (hardlimit > 0ULL && 668 (hardlimit <= nblks + *resbcountp)) { 669 + error = xfs_quota_error(flags); 670 goto error_return; 671 } 672 673 if (softlimit > 0ULL && 674 (softlimit <= nblks + *resbcountp)) { 675 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) { 701 if ((timer != 0 && get_seconds() > timer) || 702 (warns != 0 && warns >= warnlimit)) { 703 + error = xfs_quota_error(flags); 704 goto error_return; 705 } 706 } ··· 751 752 753 /* 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 and 756 + * grp/prj quotas is important, because this follows a both-or-nothing 757 * 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 blocks 763 * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks 764 * dquots are unlocked on return, if they were not locked by caller. ··· 772 long ninos, 773 uint flags) 774 { 775 + int resvd = 0, error; 776 777 + if (!XFS_IS_QUOTA_ON(mp)) 778 + return 0; 779 780 if (tp && tp->t_dqinfo == NULL) 781 xfs_trans_alloc_dqinfo(tp); 782 783 ASSERT(flags & XFS_QMOPT_RESBLK_MASK); 784 785 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 } 792 793 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 reservation 798 */ ··· 799 xfs_trans_dqresv(tp, mp, udqp, 800 -nblks, -ninos, flags); 801 } 802 + return error; 803 } 804 } 805 806 /* 807 * Didn't change anything critical, so, no need to log 808 */ 809 + return 0; 810 } 811 812 ··· 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. 817 */ 818 STATIC int 819 xfs_trans_reserve_quota_nblks( ··· 824 xfs_inode_t *ip, 825 long nblks, 826 long ninos, 827 + uint flags) 828 { 829 int error; 830 831 if (!XFS_IS_QUOTA_ON(mp)) 832 + return 0; 833 + if (XFS_IS_PQUOTA_ON(mp)) 834 + flags |= XFS_QMOPT_ENOSPC; 835 836 ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); 837 ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); 838 839 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); 845 846 /* 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 } 851 852 /*
+5 -6
fs/xfs/xfs_bmap.c
··· 4719 /* 4720 * Make a transaction-less quota reservation for 4721 * delayed allocation blocks. This number gets 4722 - * adjusted later. 4723 - * We return EDQUOT if we haven't allocated 4724 - * 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 for 4721 * delayed allocation blocks. This number gets 4722 + * adjusted later. We return if we haven't 4723 + * allocated blocks already inside this loop. 4724 */ 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 */ 203 204 /* 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) */ 204 205 /* 206 * flags to xfs_trans_mod_dquot to indicate which field needs to be