[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 2624 { 2625 2625 int error; 2626 2626 xfs_mount_t *mp; 2627 - uint delblks, blkflags; 2627 + uint delblks, blkflags, prjflags = 0; 2628 2628 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; 2629 2629 2630 2630 ASSERT(XFS_ISLOCKED_INODE(ip)); ··· 2650 2650 } 2651 2651 } 2652 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))) { 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))) { 2657 2660 delblksgdq = gdqp; 2658 2661 if (delblks) { 2659 2662 ASSERT(ip->i_gdquot); ··· 2667 2664 2668 2665 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 2669 2666 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, 2670 - flags | blkflags))) 2667 + flags | blkflags | prjflags))) 2671 2668 return (error); 2672 2669 2673 2670 /* ··· 2684 2681 ASSERT(unresudq || unresgdq); 2685 2682 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2686 2683 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, 2687 - flags | blkflags))) 2684 + flags | blkflags | prjflags))) 2688 2685 return (error); 2689 2686 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2690 2687 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
+36 -32
fs/xfs/quota/xfs_trans_dquot.c
··· 595 595 } 596 596 } 597 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 + 598 606 /* 599 607 * This reserves disk blocks and inodes against a dquot. 600 608 * Flags indicate if the dquot is to be locked here and also 601 609 * if the blk reservation is for RT or regular blocks. 602 610 * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. 603 - * Returns EDQUOT if quota is exceeded. 604 611 */ 605 612 STATIC int 606 613 xfs_trans_dqresv( ··· 673 666 */ 674 667 if (hardlimit > 0ULL && 675 668 (hardlimit <= nblks + *resbcountp)) { 676 - error = EDQUOT; 669 + error = xfs_quota_error(flags); 677 670 goto error_return; 678 671 } 679 672 680 673 if (softlimit > 0ULL && 681 674 (softlimit <= nblks + *resbcountp)) { 682 - /* 683 - * If timer or warnings has expired, 684 - * return EDQUOT 685 - */ 686 675 if ((timer != 0 && get_seconds() > timer) || 687 676 (warns != 0 && warns >= warnlimit)) { 688 - error = EDQUOT; 677 + error = xfs_quota_error(flags); 689 678 goto error_return; 690 679 } 691 680 } ··· 698 695 if (!softlimit) 699 696 softlimit = q->qi_isoftlimit; 700 697 if (hardlimit > 0ULL && count >= hardlimit) { 701 - error = EDQUOT; 698 + error = xfs_quota_error(flags); 702 699 goto error_return; 703 700 } else if (softlimit > 0ULL && count >= softlimit) { 704 - /* 705 - * If timer or warnings has expired, 706 - * return EDQUOT 707 - */ 708 701 if ((timer != 0 && get_seconds() > timer) || 709 702 (warns != 0 && warns >= warnlimit)) { 710 - error = EDQUOT; 703 + error = xfs_quota_error(flags); 711 704 goto error_return; 712 705 } 713 706 } ··· 750 751 751 752 752 753 /* 753 - * Given a dquot(s), make disk block and/or inode reservations against them. 754 + * Given dquot(s), make disk block and/or inode reservations against them. 754 755 * 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 + * grp/prj quotas is important, because this follows a both-or-nothing 756 757 * approach. 757 758 * 758 759 * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. 759 760 * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. 761 + * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. 760 762 * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks 761 763 * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks 762 764 * dquots are unlocked on return, if they were not locked by caller. ··· 772 772 long ninos, 773 773 uint flags) 774 774 { 775 - int resvd; 775 + int resvd = 0, error; 776 776 777 - if (! XFS_IS_QUOTA_ON(mp)) 778 - return (0); 777 + if (!XFS_IS_QUOTA_ON(mp)) 778 + return 0; 779 779 780 780 if (tp && tp->t_dqinfo == NULL) 781 781 xfs_trans_alloc_dqinfo(tp); 782 782 783 783 ASSERT(flags & XFS_QMOPT_RESBLK_MASK); 784 - resvd = 0; 785 784 786 785 if (udqp) { 787 - if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) 788 - return (EDQUOT); 786 + error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, 787 + (flags & ~XFS_QMOPT_ENOSPC)); 788 + if (error) 789 + return error; 789 790 resvd = 1; 790 791 } 791 792 792 793 if (gdqp) { 793 - if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) { 794 + error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags); 795 + if (error) { 794 796 /* 795 797 * can't do it, so backout previous reservation 796 798 */ ··· 801 799 xfs_trans_dqresv(tp, mp, udqp, 802 800 -nblks, -ninos, flags); 803 801 } 804 - return (EDQUOT); 802 + return error; 805 803 } 806 804 } 807 805 808 806 /* 809 807 * Didn't change anything critical, so, no need to log 810 808 */ 811 - return (0); 809 + return 0; 812 810 } 813 811 814 812 ··· 816 814 * Lock the dquot and change the reservation if we can. 817 815 * This doesn't change the actual usage, just the reservation. 818 816 * The inode sent in is locked. 819 - * 820 - * Returns 0 on success, EDQUOT or other errors otherwise 821 817 */ 822 818 STATIC int 823 819 xfs_trans_reserve_quota_nblks( ··· 824 824 xfs_inode_t *ip, 825 825 long nblks, 826 826 long ninos, 827 - uint type) 827 + uint flags) 828 828 { 829 829 int error; 830 830 831 831 if (!XFS_IS_QUOTA_ON(mp)) 832 - return (0); 832 + return 0; 833 + if (XFS_IS_PQUOTA_ON(mp)) 834 + flags |= XFS_QMOPT_ENOSPC; 833 835 834 836 ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); 835 837 ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); 836 838 837 839 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 838 840 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 + 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); 841 845 842 846 /* 843 847 * Reserve nblks against these dquots, with trans as the mediator. ··· 849 845 error = xfs_trans_reserve_quota_bydquots(tp, mp, 850 846 ip->i_udquot, ip->i_gdquot, 851 847 nblks, ninos, 852 - type); 853 - return (error); 848 + flags); 849 + return error; 854 850 } 855 851 856 852 /*
+5 -6
fs/xfs/xfs_bmap.c
··· 4719 4719 /* 4720 4720 * Make a transaction-less quota reservation for 4721 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; 4722 + * adjusted later. We return if we haven't 4723 + * allocated blocks already inside this loop. 4725 4724 */ 4726 - if (XFS_TRANS_RESERVE_QUOTA_NBLKS( 4725 + if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS( 4727 4726 mp, NULL, ip, (long)alen, 0, 4728 4727 rt ? XFS_QMOPT_RES_RTBLKS : 4729 - XFS_QMOPT_RES_REGBLKS)) { 4728 + XFS_QMOPT_RES_REGBLKS))) { 4730 4729 if (n == 0) { 4731 4730 *nmap = 0; 4732 4731 ASSERT(cur == NULL); 4733 - return XFS_ERROR(EDQUOT); 4732 + return error; 4734 4733 } 4735 4734 break; 4736 4735 }
+3 -2
fs/xfs/xfs_quota.h
··· 196 196 #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ 197 197 #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ 198 198 #define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */ 199 - #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */ 199 + #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */ 200 200 #define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ 201 - #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */ 201 + #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */ 202 202 #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ 203 + #define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */ 203 204 204 205 /* 205 206 * flags to xfs_trans_mod_dquot to indicate which field needs to be