diff options
| -rw-r--r-- | fs/xfs/quota/xfs_qm.c | 17 | ||||
| -rw-r--r-- | fs/xfs/quota/xfs_trans_dquot.c | 68 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 11 | ||||
| -rw-r--r-- | fs/xfs/xfs_quota.h | 5 |
4 files changed, 54 insertions, 47 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 73c1e5e80c07..7fb5eca9bd50 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
| @@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve( | |||
| 2624 | { | 2624 | { |
| 2625 | int error; | 2625 | int error; |
| 2626 | xfs_mount_t *mp; | 2626 | xfs_mount_t *mp; |
| 2627 | uint delblks, blkflags; | 2627 | uint delblks, blkflags, prjflags = 0; |
| 2628 | xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; | 2628 | xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; |
| 2629 | 2629 | ||
| 2630 | ASSERT(XFS_ISLOCKED_INODE(ip)); | 2630 | ASSERT(XFS_ISLOCKED_INODE(ip)); |
| @@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve( | |||
| 2650 | } | 2650 | } |
| 2651 | } | 2651 | } |
| 2652 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { | 2652 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { |
| 2653 | if ((XFS_IS_GQUOTA_ON(ip->i_mount) && | 2653 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && |
| 2654 | ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) || | 2654 | ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id)) |
| 2655 | (XFS_IS_PQUOTA_ON(ip->i_mount) && | 2655 | prjflags = XFS_QMOPT_ENOSPC; |
| 2656 | ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) { | 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 | delblksgdq = gdqp; | 2660 | delblksgdq = gdqp; |
| 2658 | if (delblks) { | 2661 | if (delblks) { |
| 2659 | ASSERT(ip->i_gdquot); | 2662 | ASSERT(ip->i_gdquot); |
| @@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve( | |||
| 2664 | 2667 | ||
| 2665 | if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, | 2668 | if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, |
| 2666 | delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, | 2669 | delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, |
| 2667 | flags | blkflags))) | 2670 | flags | blkflags | prjflags))) |
| 2668 | return (error); | 2671 | return (error); |
| 2669 | 2672 | ||
| 2670 | /* | 2673 | /* |
| @@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve( | |||
| 2681 | ASSERT(unresudq || unresgdq); | 2684 | ASSERT(unresudq || unresgdq); |
| 2682 | if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, | 2685 | if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
| 2683 | delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, | 2686 | delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, |
| 2684 | flags | blkflags))) | 2687 | flags | blkflags | prjflags))) |
| 2685 | return (error); | 2688 | return (error); |
| 2686 | xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, | 2689 | xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
| 2687 | unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, | 2690 | unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index d8e131ec0aa8..9168918db252 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
| @@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots( | |||
| 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 | * This reserves disk blocks and inodes against a dquot. | 607 | * This reserves disk blocks and inodes against a dquot. |
| 600 | * Flags indicate if the dquot is to be locked here and also | 608 | * Flags indicate if the dquot is to be locked here and also |
| 601 | * if the blk reservation is for RT or regular blocks. | 609 | * if the blk reservation is for RT or regular blocks. |
| 602 | * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. | 610 | * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. |
| 603 | * Returns EDQUOT if quota is exceeded. | ||
| 604 | */ | 611 | */ |
| 605 | STATIC int | 612 | STATIC int |
| 606 | xfs_trans_dqresv( | 613 | xfs_trans_dqresv( |
| @@ -666,19 +673,15 @@ xfs_trans_dqresv( | |||
| 666 | */ | 673 | */ |
| 667 | if (hardlimit > 0ULL && | 674 | if (hardlimit > 0ULL && |
| 668 | (hardlimit <= nblks + *resbcountp)) { | 675 | (hardlimit <= nblks + *resbcountp)) { |
| 669 | error = EDQUOT; | 676 | error = xfs_quota_error(flags); |
| 670 | goto error_return; | 677 | goto error_return; |
| 671 | } | 678 | } |
| 672 | 679 | ||
| 673 | if (softlimit > 0ULL && | 680 | if (softlimit > 0ULL && |
| 674 | (softlimit <= nblks + *resbcountp)) { | 681 | (softlimit <= nblks + *resbcountp)) { |
| 675 | /* | ||
| 676 | * If timer or warnings has expired, | ||
| 677 | * return EDQUOT | ||
| 678 | */ | ||
| 679 | if ((timer != 0 && get_seconds() > timer) || | 682 | if ((timer != 0 && get_seconds() > timer) || |
| 680 | (warns != 0 && warns >= warnlimit)) { | 683 | (warns != 0 && warns >= warnlimit)) { |
| 681 | error = EDQUOT; | 684 | error = xfs_quota_error(flags); |
| 682 | goto error_return; | 685 | goto error_return; |
| 683 | } | 686 | } |
| 684 | } | 687 | } |
| @@ -695,16 +698,12 @@ xfs_trans_dqresv( | |||
| 695 | if (!softlimit) | 698 | if (!softlimit) |
| 696 | softlimit = q->qi_isoftlimit; | 699 | softlimit = q->qi_isoftlimit; |
| 697 | if (hardlimit > 0ULL && count >= hardlimit) { | 700 | if (hardlimit > 0ULL && count >= hardlimit) { |
| 698 | error = EDQUOT; | 701 | error = xfs_quota_error(flags); |
| 699 | goto error_return; | 702 | goto error_return; |
| 700 | } else if (softlimit > 0ULL && count >= softlimit) { | 703 | } else if (softlimit > 0ULL && count >= softlimit) { |
| 701 | /* | ||
| 702 | * If timer or warnings has expired, | ||
| 703 | * return EDQUOT | ||
| 704 | */ | ||
| 705 | if ((timer != 0 && get_seconds() > timer) || | 704 | if ((timer != 0 && get_seconds() > timer) || |
| 706 | (warns != 0 && warns >= warnlimit)) { | 705 | (warns != 0 && warns >= warnlimit)) { |
| 707 | error = EDQUOT; | 706 | error = xfs_quota_error(flags); |
| 708 | goto error_return; | 707 | goto error_return; |
| 709 | } | 708 | } |
| 710 | } | 709 | } |
| @@ -751,13 +750,14 @@ error_return: | |||
| 751 | 750 | ||
| 752 | 751 | ||
| 753 | /* | 752 | /* |
| 754 | * Given a dquot(s), make disk block and/or inode reservations against them. | 753 | * 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 | 754 | * The fact that this does the reservation against both the usr and |
| 756 | * grp quotas is important, because this follows a both-or-nothing | 755 | * grp/prj quotas is important, because this follows a both-or-nothing |
| 757 | * approach. | 756 | * approach. |
| 758 | * | 757 | * |
| 759 | * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. | 758 | * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. |
| 760 | * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. | 759 | * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. |
| 760 | * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. | ||
| 761 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks | 761 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks |
| 762 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks | 762 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks |
| 763 | * dquots are unlocked on return, if they were not locked by caller. | 763 | * dquots are unlocked on return, if they were not locked by caller. |
| @@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots( | |||
| 772 | long ninos, | 772 | long ninos, |
| 773 | uint flags) | 773 | uint flags) |
| 774 | { | 774 | { |
| 775 | int resvd; | 775 | int resvd = 0, error; |
| 776 | 776 | ||
| 777 | if (! XFS_IS_QUOTA_ON(mp)) | 777 | if (!XFS_IS_QUOTA_ON(mp)) |
| 778 | return (0); | 778 | return 0; |
| 779 | 779 | ||
| 780 | if (tp && tp->t_dqinfo == NULL) | 780 | if (tp && tp->t_dqinfo == NULL) |
| 781 | xfs_trans_alloc_dqinfo(tp); | 781 | xfs_trans_alloc_dqinfo(tp); |
| 782 | 782 | ||
| 783 | ASSERT(flags & XFS_QMOPT_RESBLK_MASK); | 783 | ASSERT(flags & XFS_QMOPT_RESBLK_MASK); |
| 784 | resvd = 0; | ||
| 785 | 784 | ||
| 786 | if (udqp) { | 785 | if (udqp) { |
| 787 | if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) | 786 | error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, |
| 788 | return (EDQUOT); | 787 | (flags & ~XFS_QMOPT_ENOSPC)); |
| 788 | if (error) | ||
| 789 | return error; | ||
| 789 | resvd = 1; | 790 | resvd = 1; |
| 790 | } | 791 | } |
| 791 | 792 | ||
| 792 | if (gdqp) { | 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 | * can't do it, so backout previous reservation | 797 | * can't do it, so backout previous reservation |
| 796 | */ | 798 | */ |
| @@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots( | |||
| 799 | xfs_trans_dqresv(tp, mp, udqp, | 801 | xfs_trans_dqresv(tp, mp, udqp, |
| 800 | -nblks, -ninos, flags); | 802 | -nblks, -ninos, flags); |
| 801 | } | 803 | } |
| 802 | return (EDQUOT); | 804 | return error; |
| 803 | } | 805 | } |
| 804 | } | 806 | } |
| 805 | 807 | ||
| 806 | /* | 808 | /* |
| 807 | * Didn't change anything critical, so, no need to log | 809 | * Didn't change anything critical, so, no need to log |
| 808 | */ | 810 | */ |
| 809 | return (0); | 811 | return 0; |
| 810 | } | 812 | } |
| 811 | 813 | ||
| 812 | 814 | ||
| @@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots( | |||
| 814 | * Lock the dquot and change the reservation if we can. | 816 | * Lock the dquot and change the reservation if we can. |
| 815 | * This doesn't change the actual usage, just the reservation. | 817 | * This doesn't change the actual usage, just the reservation. |
| 816 | * The inode sent in is locked. | 818 | * The inode sent in is locked. |
| 817 | * | ||
| 818 | * Returns 0 on success, EDQUOT or other errors otherwise | ||
| 819 | */ | 819 | */ |
| 820 | STATIC int | 820 | STATIC int |
| 821 | xfs_trans_reserve_quota_nblks( | 821 | xfs_trans_reserve_quota_nblks( |
| @@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks( | |||
| 824 | xfs_inode_t *ip, | 824 | xfs_inode_t *ip, |
| 825 | long nblks, | 825 | long nblks, |
| 826 | long ninos, | 826 | long ninos, |
| 827 | uint type) | 827 | uint flags) |
| 828 | { | 828 | { |
| 829 | int error; | 829 | int error; |
| 830 | 830 | ||
| 831 | if (!XFS_IS_QUOTA_ON(mp)) | 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 | ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); | 836 | ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); |
| 835 | ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); | 837 | ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); |
| 836 | 838 | ||
| 837 | ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); | 839 | ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); |
| 838 | ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); | 840 | ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); |
| 839 | ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS || | 841 | ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) == |
| 840 | (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS); | 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 | * Reserve nblks against these dquots, with trans as the mediator. | 847 | * Reserve nblks against these dquots, with trans as the mediator. |
| @@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks( | |||
| 845 | error = xfs_trans_reserve_quota_bydquots(tp, mp, | 849 | error = xfs_trans_reserve_quota_bydquots(tp, mp, |
| 846 | ip->i_udquot, ip->i_gdquot, | 850 | ip->i_udquot, ip->i_gdquot, |
| 847 | nblks, ninos, | 851 | nblks, ninos, |
| 848 | type); | 852 | flags); |
| 849 | return (error); | 853 | return error; |
| 850 | } | 854 | } |
| 851 | 855 | ||
| 852 | /* | 856 | /* |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index d384e489705f..26939d364bc4 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -4719,18 +4719,17 @@ xfs_bmapi( | |||
| 4719 | /* | 4719 | /* |
| 4720 | * Make a transaction-less quota reservation for | 4720 | * Make a transaction-less quota reservation for |
| 4721 | * delayed allocation blocks. This number gets | 4721 | * delayed allocation blocks. This number gets |
| 4722 | * adjusted later. | 4722 | * adjusted later. We return if we haven't |
| 4723 | * We return EDQUOT if we haven't allocated | 4723 | * allocated blocks already inside this loop. |
| 4724 | * blks already inside this loop; | ||
| 4725 | */ | 4724 | */ |
| 4726 | if (XFS_TRANS_RESERVE_QUOTA_NBLKS( | 4725 | if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS( |
| 4727 | mp, NULL, ip, (long)alen, 0, | 4726 | mp, NULL, ip, (long)alen, 0, |
| 4728 | rt ? XFS_QMOPT_RES_RTBLKS : | 4727 | rt ? XFS_QMOPT_RES_RTBLKS : |
| 4729 | XFS_QMOPT_RES_REGBLKS)) { | 4728 | XFS_QMOPT_RES_REGBLKS))) { |
| 4730 | if (n == 0) { | 4729 | if (n == 0) { |
| 4731 | *nmap = 0; | 4730 | *nmap = 0; |
| 4732 | ASSERT(cur == NULL); | 4731 | ASSERT(cur == NULL); |
| 4733 | return XFS_ERROR(EDQUOT); | 4732 | return error; |
| 4734 | } | 4733 | } |
| 4735 | break; | 4734 | break; |
| 4736 | } | 4735 | } |
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 4f6a034de7f7..7fbef974bce6 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
| @@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat { | |||
| 196 | #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ | 196 | #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ |
| 197 | #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ | 197 | #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ |
| 198 | #define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */ | 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 | #define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ | 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 | #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ | 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 | * flags to xfs_trans_mod_dquot to indicate which field needs to be | 206 | * flags to xfs_trans_mod_dquot to indicate which field needs to be |
