aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/quota/xfs_qm.c146
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c16
-rw-r--r--fs/xfs/xfs_quota.h1
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(
754STATIC void 724STATIC void
755xfs_qm_dqattach_grouphint( 725xfs_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
742error_return: 741error_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 */