diff options
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 146 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_trans_dquot.c | 16 | ||||
-rw-r--r-- | fs/xfs/xfs_quota.h | 1 |
3 files changed, 50 insertions, 113 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7a2beb64314f..fd0b383d72a5 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -632,7 +632,6 @@ xfs_qm_dqattach_one( | |||
632 | xfs_dqid_t id, | 632 | xfs_dqid_t id, |
633 | uint type, | 633 | uint type, |
634 | uint doalloc, | 634 | uint doalloc, |
635 | uint dolock, | ||
636 | xfs_dquot_t *udqhint, /* hint */ | 635 | xfs_dquot_t *udqhint, /* hint */ |
637 | xfs_dquot_t **IO_idqpp) | 636 | xfs_dquot_t **IO_idqpp) |
638 | { | 637 | { |
@@ -641,16 +640,16 @@ xfs_qm_dqattach_one( | |||
641 | 640 | ||
642 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 641 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
643 | error = 0; | 642 | error = 0; |
643 | |||
644 | /* | 644 | /* |
645 | * See if we already have it in the inode itself. IO_idqpp is | 645 | * See if we already have it in the inode itself. IO_idqpp is |
646 | * &i_udquot or &i_gdquot. This made the code look weird, but | 646 | * &i_udquot or &i_gdquot. This made the code look weird, but |
647 | * made the logic a lot simpler. | 647 | * made the logic a lot simpler. |
648 | */ | 648 | */ |
649 | if ((dqp = *IO_idqpp)) { | 649 | dqp = *IO_idqpp; |
650 | if (dolock) | 650 | if (dqp) { |
651 | xfs_dqlock(dqp); | ||
652 | xfs_dqtrace_entry(dqp, "DQATTACH: found in ip"); | 651 | xfs_dqtrace_entry(dqp, "DQATTACH: found in ip"); |
653 | goto done; | 652 | return 0; |
654 | } | 653 | } |
655 | 654 | ||
656 | /* | 655 | /* |
@@ -659,38 +658,38 @@ xfs_qm_dqattach_one( | |||
659 | * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside | 658 | * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside |
660 | * the user dquot. | 659 | * the user dquot. |
661 | */ | 660 | */ |
662 | ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); | 661 | if (udqhint) { |
663 | if (udqhint && !dolock) | 662 | ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); |
664 | xfs_dqlock(udqhint); | 663 | xfs_dqlock(udqhint); |
665 | 664 | ||
666 | /* | 665 | /* |
667 | * No need to take dqlock to look at the id. | 666 | * No need to take dqlock to look at the id. |
668 | * The ID can't change until it gets reclaimed, and it won't | 667 | * |
669 | * be reclaimed as long as we have a ref from inode and we hold | 668 | * The ID can't change until it gets reclaimed, and it won't |
670 | * the ilock. | 669 | * be reclaimed as long as we have a ref from inode and we |
671 | */ | 670 | * hold the ilock. |
672 | if (udqhint && | 671 | */ |
673 | (dqp = udqhint->q_gdquot) && | 672 | dqp = udqhint->q_gdquot; |
674 | (be32_to_cpu(dqp->q_core.d_id) == id)) { | 673 | if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { |
675 | ASSERT(XFS_DQ_IS_LOCKED(udqhint)); | 674 | xfs_dqlock(dqp); |
676 | xfs_dqlock(dqp); | 675 | XFS_DQHOLD(dqp); |
677 | XFS_DQHOLD(dqp); | 676 | ASSERT(*IO_idqpp == NULL); |
678 | ASSERT(*IO_idqpp == NULL); | 677 | *IO_idqpp = dqp; |
679 | *IO_idqpp = dqp; | 678 | |
680 | if (!dolock) { | ||
681 | xfs_dqunlock(dqp); | 679 | xfs_dqunlock(dqp); |
682 | xfs_dqunlock(udqhint); | 680 | xfs_dqunlock(udqhint); |
681 | return 0; | ||
683 | } | 682 | } |
684 | goto done; | 683 | |
685 | } | 684 | /* |
686 | /* | 685 | * We can't hold a dquot lock when we call the dqget code. |
687 | * We can't hold a dquot lock when we call the dqget code. | 686 | * We'll deadlock in no time, because of (not conforming to) |
688 | * We'll deadlock in no time, because of (not conforming to) | 687 | * lock ordering - the inodelock comes before any dquot lock, |
689 | * lock ordering - the inodelock comes before any dquot lock, | 688 | * and we may drop and reacquire the ilock in xfs_qm_dqget(). |
690 | * and we may drop and reacquire the ilock in xfs_qm_dqget(). | 689 | */ |
691 | */ | ||
692 | if (udqhint) | ||
693 | xfs_dqunlock(udqhint); | 690 | xfs_dqunlock(udqhint); |
691 | } | ||
692 | |||
694 | /* | 693 | /* |
695 | * Find the dquot from somewhere. This bumps the | 694 | * Find the dquot from somewhere. This bumps the |
696 | * reference count of dquot and returns it locked. | 695 | * reference count of dquot and returns it locked. |
@@ -698,48 +697,19 @@ xfs_qm_dqattach_one( | |||
698 | * disk and we didn't ask it to allocate; | 697 | * disk and we didn't ask it to allocate; |
699 | * ESRCH if quotas got turned off suddenly. | 698 | * ESRCH if quotas got turned off suddenly. |
700 | */ | 699 | */ |
701 | if ((error = xfs_qm_dqget(ip->i_mount, ip, id, type, | 700 | error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp); |
702 | doalloc|XFS_QMOPT_DOWARN, &dqp))) { | 701 | if (error) |
703 | if (udqhint && dolock) | 702 | return error; |
704 | xfs_dqlock(udqhint); | ||
705 | goto done; | ||
706 | } | ||
707 | 703 | ||
708 | xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget"); | 704 | xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget"); |
705 | |||
709 | /* | 706 | /* |
710 | * dqget may have dropped and re-acquired the ilock, but it guarantees | 707 | * dqget may have dropped and re-acquired the ilock, but it guarantees |
711 | * that the dquot returned is the one that should go in the inode. | 708 | * that the dquot returned is the one that should go in the inode. |
712 | */ | 709 | */ |
713 | *IO_idqpp = dqp; | 710 | *IO_idqpp = dqp; |
714 | ASSERT(dqp); | 711 | xfs_dqunlock(dqp); |
715 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 712 | return 0; |
716 | if (! dolock) { | ||
717 | xfs_dqunlock(dqp); | ||
718 | goto done; | ||
719 | } | ||
720 | if (! udqhint) | ||
721 | goto done; | ||
722 | |||
723 | ASSERT(udqhint); | ||
724 | ASSERT(dolock); | ||
725 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
726 | if (! xfs_qm_dqlock_nowait(udqhint)) { | ||
727 | xfs_dqunlock(dqp); | ||
728 | xfs_dqlock(udqhint); | ||
729 | xfs_dqlock(dqp); | ||
730 | } | ||
731 | done: | ||
732 | #ifdef QUOTADEBUG | ||
733 | if (udqhint) { | ||
734 | if (dolock) | ||
735 | ASSERT(XFS_DQ_IS_LOCKED(udqhint)); | ||
736 | } | ||
737 | if (! error) { | ||
738 | if (dolock) | ||
739 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
740 | } | ||
741 | #endif | ||
742 | return error; | ||
743 | } | 713 | } |
744 | 714 | ||
745 | 715 | ||
@@ -754,24 +724,15 @@ xfs_qm_dqattach_one( | |||
754 | STATIC void | 724 | STATIC void |
755 | xfs_qm_dqattach_grouphint( | 725 | xfs_qm_dqattach_grouphint( |
756 | xfs_dquot_t *udq, | 726 | xfs_dquot_t *udq, |
757 | xfs_dquot_t *gdq, | 727 | xfs_dquot_t *gdq) |
758 | uint locked) | ||
759 | { | 728 | { |
760 | xfs_dquot_t *tmp; | 729 | xfs_dquot_t *tmp; |
761 | 730 | ||
762 | #ifdef QUOTADEBUG | 731 | xfs_dqlock(udq); |
763 | if (locked) { | ||
764 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | ||
765 | ASSERT(XFS_DQ_IS_LOCKED(gdq)); | ||
766 | } | ||
767 | #endif | ||
768 | if (! locked) | ||
769 | xfs_dqlock(udq); | ||
770 | 732 | ||
771 | if ((tmp = udq->q_gdquot)) { | 733 | if ((tmp = udq->q_gdquot)) { |
772 | if (tmp == gdq) { | 734 | if (tmp == gdq) { |
773 | if (! locked) | 735 | xfs_dqunlock(udq); |
774 | xfs_dqunlock(udq); | ||
775 | return; | 736 | return; |
776 | } | 737 | } |
777 | 738 | ||
@@ -781,8 +742,6 @@ xfs_qm_dqattach_grouphint( | |||
781 | * because the freelist lock comes before dqlocks. | 742 | * because the freelist lock comes before dqlocks. |
782 | */ | 743 | */ |
783 | xfs_dqunlock(udq); | 744 | xfs_dqunlock(udq); |
784 | if (locked) | ||
785 | xfs_dqunlock(gdq); | ||
786 | /* | 745 | /* |
787 | * we took a hard reference once upon a time in dqget, | 746 | * we took a hard reference once upon a time in dqget, |
788 | * so give it back when the udquot no longer points at it | 747 | * so give it back when the udquot no longer points at it |
@@ -795,9 +754,7 @@ xfs_qm_dqattach_grouphint( | |||
795 | 754 | ||
796 | } else { | 755 | } else { |
797 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | 756 | ASSERT(XFS_DQ_IS_LOCKED(udq)); |
798 | if (! locked) { | 757 | xfs_dqlock(gdq); |
799 | xfs_dqlock(gdq); | ||
800 | } | ||
801 | } | 758 | } |
802 | 759 | ||
803 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | 760 | ASSERT(XFS_DQ_IS_LOCKED(udq)); |
@@ -810,10 +767,9 @@ xfs_qm_dqattach_grouphint( | |||
810 | XFS_DQHOLD(gdq); | 767 | XFS_DQHOLD(gdq); |
811 | udq->q_gdquot = gdq; | 768 | udq->q_gdquot = gdq; |
812 | } | 769 | } |
813 | if (! locked) { | 770 | |
814 | xfs_dqunlock(gdq); | 771 | xfs_dqunlock(gdq); |
815 | xfs_dqunlock(udq); | 772 | xfs_dqunlock(udq); |
816 | } | ||
817 | } | 773 | } |
818 | 774 | ||
819 | 775 | ||
@@ -821,8 +777,6 @@ xfs_qm_dqattach_grouphint( | |||
821 | * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON | 777 | * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON |
822 | * into account. | 778 | * into account. |
823 | * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. | 779 | * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. |
824 | * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty | ||
825 | * much made this code a complete mess, but it has been pretty useful. | ||
826 | * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL. | 780 | * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL. |
827 | * Inode may get unlocked and relocked in here, and the caller must deal with | 781 | * Inode may get unlocked and relocked in here, and the caller must deal with |
828 | * the consequences. | 782 | * the consequences. |
@@ -851,7 +805,6 @@ xfs_qm_dqattach( | |||
851 | if (XFS_IS_UQUOTA_ON(mp)) { | 805 | if (XFS_IS_UQUOTA_ON(mp)) { |
852 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, | 806 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, |
853 | flags & XFS_QMOPT_DQALLOC, | 807 | flags & XFS_QMOPT_DQALLOC, |
854 | flags & XFS_QMOPT_DQLOCK, | ||
855 | NULL, &ip->i_udquot); | 808 | NULL, &ip->i_udquot); |
856 | if (error) | 809 | if (error) |
857 | goto done; | 810 | goto done; |
@@ -863,11 +816,9 @@ xfs_qm_dqattach( | |||
863 | error = XFS_IS_GQUOTA_ON(mp) ? | 816 | error = XFS_IS_GQUOTA_ON(mp) ? |
864 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, | 817 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, |
865 | flags & XFS_QMOPT_DQALLOC, | 818 | flags & XFS_QMOPT_DQALLOC, |
866 | flags & XFS_QMOPT_DQLOCK, | ||
867 | ip->i_udquot, &ip->i_gdquot) : | 819 | ip->i_udquot, &ip->i_gdquot) : |
868 | xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ, | 820 | xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ, |
869 | flags & XFS_QMOPT_DQALLOC, | 821 | flags & XFS_QMOPT_DQALLOC, |
870 | flags & XFS_QMOPT_DQLOCK, | ||
871 | ip->i_udquot, &ip->i_gdquot); | 822 | ip->i_udquot, &ip->i_gdquot); |
872 | /* | 823 | /* |
873 | * Don't worry about the udquot that we may have | 824 | * Don't worry about the udquot that we may have |
@@ -898,22 +849,13 @@ xfs_qm_dqattach( | |||
898 | /* | 849 | /* |
899 | * Attach i_gdquot to the gdquot hint inside the i_udquot. | 850 | * Attach i_gdquot to the gdquot hint inside the i_udquot. |
900 | */ | 851 | */ |
901 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot, | 852 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); |
902 | flags & XFS_QMOPT_DQLOCK); | ||
903 | } | 853 | } |
904 | 854 | ||
905 | done: | 855 | done: |
906 | 856 | ||
907 | #ifdef QUOTADEBUG | 857 | #ifdef QUOTADEBUG |
908 | if (! error) { | 858 | if (! error) { |
909 | if (ip->i_udquot) { | ||
910 | if (flags & XFS_QMOPT_DQLOCK) | ||
911 | ASSERT(XFS_DQ_IS_LOCKED(ip->i_udquot)); | ||
912 | } | ||
913 | if (ip->i_gdquot) { | ||
914 | if (flags & XFS_QMOPT_DQLOCK) | ||
915 | ASSERT(XFS_DQ_IS_LOCKED(ip->i_gdquot)); | ||
916 | } | ||
917 | if (XFS_IS_UQUOTA_ON(mp)) | 859 | if (XFS_IS_UQUOTA_ON(mp)) |
918 | ASSERT(ip->i_udquot); | 860 | ASSERT(ip->i_udquot); |
919 | if (XFS_IS_OQUOTA_ON(mp)) | 861 | if (XFS_IS_OQUOTA_ON(mp)) |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 99611381e740..447173bcf96d 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -624,10 +624,9 @@ xfs_trans_dqresv( | |||
624 | xfs_qcnt_t *resbcountp; | 624 | xfs_qcnt_t *resbcountp; |
625 | xfs_quotainfo_t *q = mp->m_quotainfo; | 625 | xfs_quotainfo_t *q = mp->m_quotainfo; |
626 | 626 | ||
627 | if (! (flags & XFS_QMOPT_DQLOCK)) { | 627 | |
628 | xfs_dqlock(dqp); | 628 | xfs_dqlock(dqp); |
629 | } | 629 | |
630 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
631 | if (flags & XFS_TRANS_DQ_RES_BLKS) { | 630 | if (flags & XFS_TRANS_DQ_RES_BLKS) { |
632 | hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit); | 631 | hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit); |
633 | if (!hardlimit) | 632 | if (!hardlimit) |
@@ -740,10 +739,8 @@ xfs_trans_dqresv( | |||
740 | ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount)); | 739 | ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount)); |
741 | 740 | ||
742 | error_return: | 741 | error_return: |
743 | if (! (flags & XFS_QMOPT_DQLOCK)) { | 742 | xfs_dqunlock(dqp); |
744 | xfs_dqunlock(dqp); | 743 | return error; |
745 | } | ||
746 | return (error); | ||
747 | } | 744 | } |
748 | 745 | ||
749 | 746 | ||
@@ -753,8 +750,7 @@ error_return: | |||
753 | * grp/prj quotas is important, because this follows a both-or-nothing | 750 | * grp/prj quotas is important, because this follows a both-or-nothing |
754 | * approach. | 751 | * approach. |
755 | * | 752 | * |
756 | * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. | 753 | * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. |
757 | * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. | ||
758 | * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. | 754 | * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. |
759 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks | 755 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks |
760 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks | 756 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks |
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 48965ecaa155..63d41acf4533 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
@@ -185,7 +185,6 @@ typedef struct xfs_qoff_logformat { | |||
185 | * to a single function. None of these XFS_QMOPT_* flags are meant to have | 185 | * to a single function. None of these XFS_QMOPT_* flags are meant to have |
186 | * persistent values (ie. their values can and will change between versions) | 186 | * persistent values (ie. their values can and will change between versions) |
187 | */ | 187 | */ |
188 | #define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */ | ||
189 | #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ | 188 | #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ |
190 | #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ | 189 | #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ |
191 | #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ | 190 | #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ |