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 |