diff options
| -rw-r--r-- | fs/xfs/xfs_qm.c | 64 |
1 files changed, 16 insertions, 48 deletions
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 22360bb26af9..3c553454443c 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
| @@ -650,11 +650,7 @@ xfs_qm_dqattach_one( | |||
| 650 | 650 | ||
| 651 | /* | 651 | /* |
| 652 | * Given a udquot and gdquot, attach a ptr to the group dquot in the | 652 | * Given a udquot and gdquot, attach a ptr to the group dquot in the |
| 653 | * udquot as a hint for future lookups. The idea sounds simple, but the | 653 | * udquot as a hint for future lookups. |
| 654 | * execution isn't, because the udquot might have a group dquot attached | ||
| 655 | * already and getting rid of that gets us into lock ordering constraints. | ||
| 656 | * The process is complicated more by the fact that the dquots may or may not | ||
| 657 | * be locked on entry. | ||
| 658 | */ | 654 | */ |
| 659 | STATIC void | 655 | STATIC void |
| 660 | xfs_qm_dqattach_grouphint( | 656 | xfs_qm_dqattach_grouphint( |
| @@ -665,45 +661,21 @@ xfs_qm_dqattach_grouphint( | |||
| 665 | 661 | ||
| 666 | xfs_dqlock(udq); | 662 | xfs_dqlock(udq); |
| 667 | 663 | ||
| 668 | if ((tmp = udq->q_gdquot)) { | 664 | tmp = udq->q_gdquot; |
| 669 | if (tmp == gdq) { | 665 | if (tmp) { |
| 670 | xfs_dqunlock(udq); | 666 | if (tmp == gdq) |
| 671 | return; | 667 | goto done; |
| 672 | } | ||
| 673 | 668 | ||
| 674 | udq->q_gdquot = NULL; | 669 | udq->q_gdquot = NULL; |
| 675 | /* | ||
| 676 | * We can't keep any dqlocks when calling dqrele, | ||
| 677 | * because the freelist lock comes before dqlocks. | ||
| 678 | */ | ||
| 679 | xfs_dqunlock(udq); | ||
| 680 | /* | ||
| 681 | * we took a hard reference once upon a time in dqget, | ||
| 682 | * so give it back when the udquot no longer points at it | ||
| 683 | * dqput() does the unlocking of the dquot. | ||
| 684 | */ | ||
| 685 | xfs_qm_dqrele(tmp); | 670 | xfs_qm_dqrele(tmp); |
| 686 | |||
| 687 | xfs_dqlock(udq); | ||
| 688 | xfs_dqlock(gdq); | ||
| 689 | |||
| 690 | } else { | ||
| 691 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | ||
| 692 | xfs_dqlock(gdq); | ||
| 693 | } | ||
| 694 | |||
| 695 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | ||
| 696 | ASSERT(XFS_DQ_IS_LOCKED(gdq)); | ||
| 697 | /* | ||
| 698 | * Somebody could have attached a gdquot here, | ||
| 699 | * when we dropped the uqlock. If so, just do nothing. | ||
| 700 | */ | ||
| 701 | if (udq->q_gdquot == NULL) { | ||
| 702 | XFS_DQHOLD(gdq); | ||
| 703 | udq->q_gdquot = gdq; | ||
| 704 | } | 671 | } |
| 705 | 672 | ||
| 673 | xfs_dqlock(gdq); | ||
| 674 | XFS_DQHOLD(gdq); | ||
| 706 | xfs_dqunlock(gdq); | 675 | xfs_dqunlock(gdq); |
| 676 | |||
| 677 | udq->q_gdquot = gdq; | ||
| 678 | done: | ||
| 707 | xfs_dqunlock(udq); | 679 | xfs_dqunlock(udq); |
| 708 | } | 680 | } |
| 709 | 681 | ||
| @@ -770,17 +742,13 @@ xfs_qm_dqattach_locked( | |||
| 770 | ASSERT(ip->i_gdquot); | 742 | ASSERT(ip->i_gdquot); |
| 771 | 743 | ||
| 772 | /* | 744 | /* |
| 773 | * We may or may not have the i_udquot locked at this point, | 745 | * We do not have i_udquot locked at this point, but this check |
| 774 | * but this check is OK since we don't depend on the i_gdquot to | 746 | * is OK since we don't depend on the i_gdquot to be accurate |
| 775 | * be accurate 100% all the time. It is just a hint, and this | 747 | * 100% all the time. It is just a hint, and this will |
| 776 | * will succeed in general. | 748 | * succeed in general. |
| 777 | */ | ||
| 778 | if (ip->i_udquot->q_gdquot == ip->i_gdquot) | ||
| 779 | goto done; | ||
| 780 | /* | ||
| 781 | * Attach i_gdquot to the gdquot hint inside the i_udquot. | ||
| 782 | */ | 749 | */ |
| 783 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); | 750 | if (ip->i_udquot->q_gdquot != ip->i_gdquot) |
| 751 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); | ||
| 784 | } | 752 | } |
| 785 | 753 | ||
| 786 | done: | 754 | done: |
