diff options
Diffstat (limited to 'fs/xfs/quota/xfs_trans_dquot.c')
-rw-r--r-- | fs/xfs/quota/xfs_trans_dquot.c | 68 |
1 files changed, 36 insertions, 32 deletions
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 | /* |