aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-04-13 01:06:48 -0400
committerAlex Elder <aelder@sgi.com>2010-05-19 10:58:10 -0400
commit3a25404b3fccd41d36b2fda18d86011201608c38 (patch)
tree28979d8581760327c16a3389a2eb8752ed3f0665 /fs/xfs
parent9abbc539bf7f299819ad0a235064a1b643ab6407 (diff)
xfs: convert the per-mount dquot list to use list heads
Convert the dquot list on the filesytesm to use listhead infrastructure rather than the roll-your-own in the quota code. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/quota/xfs_dquot.c21
-rw-r--r--fs/xfs/quota/xfs_dquot.h2
-rw-r--r--fs/xfs/quota/xfs_qm.c155
-rw-r--r--fs/xfs/quota/xfs_qm.h4
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c2
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h25
6 files changed, 97 insertions, 112 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 5f79dd78626b..838289b92bb9 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -121,8 +121,9 @@ xfs_qm_dqinit(
121 */ 121 */
122 dqp->q_nrefs = 0; 122 dqp->q_nrefs = 0;
123 dqp->q_blkno = 0; 123 dqp->q_blkno = 0;
124 dqp->MPL_NEXT = dqp->HL_NEXT = NULL; 124 INIT_LIST_HEAD(&dqp->q_mplist);
125 dqp->HL_PREVP = dqp->MPL_PREVP = NULL; 125 dqp->HL_NEXT = NULL;
126 dqp->HL_PREVP = NULL;
126 dqp->q_bufoffset = 0; 127 dqp->q_bufoffset = 0;
127 dqp->q_fileoffset = 0; 128 dqp->q_fileoffset = 0;
128 dqp->q_transp = NULL; 129 dqp->q_transp = NULL;
@@ -772,7 +773,7 @@ xfs_qm_dqlookup(
772 /* 773 /*
773 * All in core dquots must be on the dqlist of mp 774 * All in core dquots must be on the dqlist of mp
774 */ 775 */
775 ASSERT(dqp->MPL_PREVP != NULL); 776 ASSERT(!list_empty(&dqp->q_mplist));
776 777
777 xfs_dqlock(dqp); 778 xfs_dqlock(dqp);
778 if (dqp->q_nrefs == 0) { 779 if (dqp->q_nrefs == 0) {
@@ -1039,7 +1040,7 @@ xfs_qm_dqget(
1039 * Attach this dquot to this filesystem's list of all dquots, 1040 * Attach this dquot to this filesystem's list of all dquots,
1040 * kept inside the mount structure in m_quotainfo field 1041 * kept inside the mount structure in m_quotainfo field
1041 */ 1042 */
1042 xfs_qm_mplist_lock(mp); 1043 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
1043 1044
1044 /* 1045 /*
1045 * We return a locked dquot to the caller, with a reference taken 1046 * We return a locked dquot to the caller, with a reference taken
@@ -1047,9 +1048,9 @@ xfs_qm_dqget(
1047 xfs_dqlock(dqp); 1048 xfs_dqlock(dqp);
1048 dqp->q_nrefs = 1; 1049 dqp->q_nrefs = 1;
1049 1050
1050 XQM_MPLIST_INSERT(&(XFS_QI_MPL_LIST(mp)), dqp); 1051 list_add(&dqp->q_mplist, &mp->m_quotainfo->qi_dqlist);
1051 1052 mp->m_quotainfo->qi_dquots++;
1052 xfs_qm_mplist_unlock(mp); 1053 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
1053 mutex_unlock(&h->qh_lock); 1054 mutex_unlock(&h->qh_lock);
1054 dqret: 1055 dqret:
1055 ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL)); 1056 ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -1389,7 +1390,7 @@ xfs_qm_dqpurge(
1389 xfs_dqhash_t *thishash; 1390 xfs_dqhash_t *thishash;
1390 xfs_mount_t *mp = dqp->q_mount; 1391 xfs_mount_t *mp = dqp->q_mount;
1391 1392
1392 ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp)); 1393 ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
1393 ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock)); 1394 ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock));
1394 1395
1395 xfs_dqlock(dqp); 1396 xfs_dqlock(dqp);
@@ -1454,7 +1455,9 @@ xfs_qm_dqpurge(
1454 1455
1455 thishash = dqp->q_hash; 1456 thishash = dqp->q_hash;
1456 XQM_HASHLIST_REMOVE(thishash, dqp); 1457 XQM_HASHLIST_REMOVE(thishash, dqp);
1457 XQM_MPLIST_REMOVE(&(XFS_QI_MPL_LIST(mp)), dqp); 1458 list_del_init(&dqp->q_mplist);
1459 mp->m_quotainfo->qi_dqreclaims++;
1460 mp->m_quotainfo->qi_dquots--;
1458 /* 1461 /*
1459 * XXX Move this to the front of the freelist, if we can get the 1462 * XXX Move this to the front of the freelist, if we can get the
1460 * freelist lock. 1463 * freelist lock.
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index a0f7da586d1b..6992a67c165a 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -57,7 +57,6 @@ struct xfs_trans;
57typedef struct xfs_dqmarker { 57typedef struct xfs_dqmarker {
58 struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */ 58 struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
59 struct xfs_dquot*dqm_flprev; 59 struct xfs_dquot*dqm_flprev;
60 xfs_dqlink_t dqm_mplist; /* link to mount's list of dquots */
61 xfs_dqlink_t dqm_hashlist; /* link to the hash chain */ 60 xfs_dqlink_t dqm_hashlist; /* link to the hash chain */
62 uint dqm_flags; /* various flags (XFS_DQ_*) */ 61 uint dqm_flags; /* various flags (XFS_DQ_*) */
63} xfs_dqmarker_t; 62} xfs_dqmarker_t;
@@ -67,6 +66,7 @@ typedef struct xfs_dqmarker {
67 */ 66 */
68typedef struct xfs_dquot { 67typedef struct xfs_dquot {
69 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */ 68 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */
69 struct list_head q_mplist; /* mount's list of dquots */
70 xfs_dqhash_t *q_hash; /* the hashchain header */ 70 xfs_dqhash_t *q_hash; /* the hashchain header */
71 struct xfs_mount*q_mount; /* filesystem this relates to */ 71 struct xfs_mount*q_mount; /* filesystem this relates to */
72 struct xfs_trans*q_transp; /* trans this belongs to currently */ 72 struct xfs_trans*q_transp; /* trans this belongs to currently */
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 417e61e3d9dd..855827320ff6 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -84,21 +84,25 @@ extern struct mutex qcheck_lock;
84#endif 84#endif
85 85
86#ifdef QUOTADEBUG 86#ifdef QUOTADEBUG
87#define XQM_LIST_PRINT(l, NXT, title) \ 87static void
88{ \ 88xfs_qm_dquot_list_print(
89 xfs_dquot_t *dqp; int i = 0; \ 89 struct xfs_mount *mp)
90 cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ 90{
91 for (dqp = (l)->qh_next; dqp != NULL; dqp = dqp->NXT) { \ 91 xfs_dquot_t *dqp;
92 cmn_err(CE_DEBUG, " %d. \"%d (%s)\" " \ 92 int i = 0;
93 "bcnt = %d, icnt = %d, refs = %d", \ 93
94 ++i, (int) be32_to_cpu(dqp->q_core.d_id), \ 94 list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) {
95 DQFLAGTO_TYPESTR(dqp), \ 95 cmn_err(CE_DEBUG, " %d. \"%d (%s)\" "
96 (int) be64_to_cpu(dqp->q_core.d_bcount), \ 96 "bcnt = %lld, icnt = %lld, refs = %d",
97 (int) be64_to_cpu(dqp->q_core.d_icount), \ 97 i++, be32_to_cpu(dqp->q_core.d_id),
98 (int) dqp->q_nrefs); } \ 98 DQFLAGTO_TYPESTR(dqp),
99 (long long)be64_to_cpu(dqp->q_core.d_bcount),
100 (long long)be64_to_cpu(dqp->q_core.d_icount),
101 dqp->q_nrefs);
102 }
99} 103}
100#else 104#else
101#define XQM_LIST_PRINT(l, NXT, title) do { } while (0) 105static void xfs_qm_dquot_list_print(struct xfs_mount *mp) { }
102#endif 106#endif
103 107
104/* 108/*
@@ -274,7 +278,7 @@ xfs_qm_rele_quotafs_ref(
274 ASSERT(dqp->q_mount == NULL); 278 ASSERT(dqp->q_mount == NULL);
275 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 279 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
276 ASSERT(dqp->HL_PREVP == NULL); 280 ASSERT(dqp->HL_PREVP == NULL);
277 ASSERT(dqp->MPL_PREVP == NULL); 281 ASSERT(list_empty(&dqp->q_mplist));
278 XQM_FREELIST_REMOVE(dqp); 282 XQM_FREELIST_REMOVE(dqp);
279 xfs_dqunlock(dqp); 283 xfs_dqunlock(dqp);
280 xfs_qm_dqdestroy(dqp); 284 xfs_qm_dqdestroy(dqp);
@@ -461,8 +465,8 @@ xfs_qm_dqflush_all(
461 return 0; 465 return 0;
462 niters = 0; 466 niters = 0;
463again: 467again:
464 xfs_qm_mplist_lock(mp); 468 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
465 FOREACH_DQUOT_IN_MP(dqp, mp) { 469 list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist, q_mplist) {
466 xfs_dqlock(dqp); 470 xfs_dqlock(dqp);
467 if (! XFS_DQ_IS_DIRTY(dqp)) { 471 if (! XFS_DQ_IS_DIRTY(dqp)) {
468 xfs_dqunlock(dqp); 472 xfs_dqunlock(dqp);
@@ -470,7 +474,7 @@ again:
470 } 474 }
471 475
472 /* XXX a sentinel would be better */ 476 /* XXX a sentinel would be better */
473 recl = XFS_QI_MPLRECLAIMS(mp); 477 recl = mp->m_quotainfo->qi_dqreclaims;
474 if (!xfs_dqflock_nowait(dqp)) { 478 if (!xfs_dqflock_nowait(dqp)) {
475 /* 479 /*
476 * If we can't grab the flush lock then check 480 * If we can't grab the flush lock then check
@@ -485,21 +489,21 @@ again:
485 * Let go of the mplist lock. We don't want to hold it 489 * Let go of the mplist lock. We don't want to hold it
486 * across a disk write. 490 * across a disk write.
487 */ 491 */
488 xfs_qm_mplist_unlock(mp); 492 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
489 error = xfs_qm_dqflush(dqp, sync_mode); 493 error = xfs_qm_dqflush(dqp, sync_mode);
490 xfs_dqunlock(dqp); 494 xfs_dqunlock(dqp);
491 if (error) 495 if (error)
492 return error; 496 return error;
493 497
494 xfs_qm_mplist_lock(mp); 498 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
495 if (recl != XFS_QI_MPLRECLAIMS(mp)) { 499 if (recl != mp->m_quotainfo->qi_dqreclaims) {
496 xfs_qm_mplist_unlock(mp); 500 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
497 /* XXX restart limit */ 501 /* XXX restart limit */
498 goto again; 502 goto again;
499 } 503 }
500 } 504 }
501 505
502 xfs_qm_mplist_unlock(mp); 506 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
503 /* return ! busy */ 507 /* return ! busy */
504 return 0; 508 return 0;
505} 509}
@@ -515,9 +519,8 @@ xfs_qm_detach_gdquots(
515 int nrecl; 519 int nrecl;
516 520
517 again: 521 again:
518 ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp)); 522 ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
519 dqp = XFS_QI_MPLNEXT(mp); 523 list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist, q_mplist) {
520 while (dqp) {
521 xfs_dqlock(dqp); 524 xfs_dqlock(dqp);
522 if ((gdqp = dqp->q_gdquot)) { 525 if ((gdqp = dqp->q_gdquot)) {
523 xfs_dqlock(gdqp); 526 xfs_dqlock(gdqp);
@@ -530,15 +533,14 @@ xfs_qm_detach_gdquots(
530 * Can't hold the mplist lock across a dqput. 533 * Can't hold the mplist lock across a dqput.
531 * XXXmust convert to marker based iterations here. 534 * XXXmust convert to marker based iterations here.
532 */ 535 */
533 nrecl = XFS_QI_MPLRECLAIMS(mp); 536 nrecl = mp->m_quotainfo->qi_dqreclaims;
534 xfs_qm_mplist_unlock(mp); 537 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
535 xfs_qm_dqput(gdqp); 538 xfs_qm_dqput(gdqp);
536 539
537 xfs_qm_mplist_lock(mp); 540 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
538 if (nrecl != XFS_QI_MPLRECLAIMS(mp)) 541 if (nrecl != mp->m_quotainfo->qi_dqreclaims)
539 goto again; 542 goto again;
540 } 543 }
541 dqp = dqp->MPL_NEXT;
542 } 544 }
543} 545}
544 546
@@ -553,10 +555,9 @@ xfs_qm_dqpurge_int(
553 xfs_mount_t *mp, 555 xfs_mount_t *mp,
554 uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */ 556 uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
555{ 557{
556 xfs_dquot_t *dqp; 558 xfs_dquot_t *dqp, *n;
557 uint dqtype; 559 uint dqtype;
558 int nrecl; 560 int nrecl;
559 xfs_dquot_t *nextdqp;
560 int nmisses; 561 int nmisses;
561 562
562 if (mp->m_quotainfo == NULL) 563 if (mp->m_quotainfo == NULL)
@@ -566,7 +567,7 @@ xfs_qm_dqpurge_int(
566 dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0; 567 dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
567 dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0; 568 dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
568 569
569 xfs_qm_mplist_lock(mp); 570 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
570 571
571 /* 572 /*
572 * In the first pass through all incore dquots of this filesystem, 573 * In the first pass through all incore dquots of this filesystem,
@@ -578,28 +579,25 @@ xfs_qm_dqpurge_int(
578 579
579 again: 580 again:
580 nmisses = 0; 581 nmisses = 0;
581 ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp)); 582 ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
582 /* 583 /*
583 * Try to get rid of all of the unwanted dquots. The idea is to 584 * Try to get rid of all of the unwanted dquots. The idea is to
584 * get them off mplist and hashlist, but leave them on freelist. 585 * get them off mplist and hashlist, but leave them on freelist.
585 */ 586 */
586 dqp = XFS_QI_MPLNEXT(mp); 587 list_for_each_entry_safe(dqp, n, &mp->m_quotainfo->qi_dqlist, q_mplist) {
587 while (dqp) {
588 /* 588 /*
589 * It's OK to look at the type without taking dqlock here. 589 * It's OK to look at the type without taking dqlock here.
590 * We're holding the mplist lock here, and that's needed for 590 * We're holding the mplist lock here, and that's needed for
591 * a dqreclaim. 591 * a dqreclaim.
592 */ 592 */
593 if ((dqp->dq_flags & dqtype) == 0) { 593 if ((dqp->dq_flags & dqtype) == 0)
594 dqp = dqp->MPL_NEXT;
595 continue; 594 continue;
596 }
597 595
598 if (!mutex_trylock(&dqp->q_hash->qh_lock)) { 596 if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
599 nrecl = XFS_QI_MPLRECLAIMS(mp); 597 nrecl = mp->m_quotainfo->qi_dqreclaims;
600 xfs_qm_mplist_unlock(mp); 598 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
601 mutex_lock(&dqp->q_hash->qh_lock); 599 mutex_lock(&dqp->q_hash->qh_lock);
602 xfs_qm_mplist_lock(mp); 600 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
603 601
604 /* 602 /*
605 * XXXTheoretically, we can get into a very long 603 * XXXTheoretically, we can get into a very long
@@ -607,7 +605,7 @@ xfs_qm_dqpurge_int(
607 * No one can be adding dquots to the mplist at 605 * No one can be adding dquots to the mplist at
608 * this point, but somebody might be taking things off. 606 * this point, but somebody might be taking things off.
609 */ 607 */
610 if (nrecl != XFS_QI_MPLRECLAIMS(mp)) { 608 if (nrecl != mp->m_quotainfo->qi_dqreclaims) {
611 mutex_unlock(&dqp->q_hash->qh_lock); 609 mutex_unlock(&dqp->q_hash->qh_lock);
612 goto again; 610 goto again;
613 } 611 }
@@ -617,11 +615,9 @@ xfs_qm_dqpurge_int(
617 * Take the dquot off the mplist and hashlist. It may remain on 615 * Take the dquot off the mplist and hashlist. It may remain on
618 * freelist in INACTIVE state. 616 * freelist in INACTIVE state.
619 */ 617 */
620 nextdqp = dqp->MPL_NEXT;
621 nmisses += xfs_qm_dqpurge(dqp); 618 nmisses += xfs_qm_dqpurge(dqp);
622 dqp = nextdqp;
623 } 619 }
624 xfs_qm_mplist_unlock(mp); 620 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
625 return nmisses; 621 return nmisses;
626} 622}
627 623
@@ -934,18 +930,19 @@ xfs_qm_sync(
934 restarts = 0; 930 restarts = 0;
935 931
936 again: 932 again:
937 xfs_qm_mplist_lock(mp); 933 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
938 /* 934 /*
939 * dqpurge_all() also takes the mplist lock and iterate thru all dquots 935 * dqpurge_all() also takes the mplist lock and iterate thru all dquots
940 * in quotaoff. However, if the QUOTA_ACTIVE bits are not cleared 936 * in quotaoff. However, if the QUOTA_ACTIVE bits are not cleared
941 * when we have the mplist lock, we know that dquots will be consistent 937 * when we have the mplist lock, we know that dquots will be consistent
942 * as long as we have it locked. 938 * as long as we have it locked.
943 */ 939 */
944 if (! XFS_IS_QUOTA_ON(mp)) { 940 if (!XFS_IS_QUOTA_ON(mp)) {
945 xfs_qm_mplist_unlock(mp); 941 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
946 return 0; 942 return 0;
947 } 943 }
948 FOREACH_DQUOT_IN_MP(dqp, mp) { 944 ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
945 list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist, q_mplist) {
949 /* 946 /*
950 * If this is vfs_sync calling, then skip the dquots that 947 * If this is vfs_sync calling, then skip the dquots that
951 * don't 'seem' to be dirty. ie. don't acquire dqlock. 948 * don't 'seem' to be dirty. ie. don't acquire dqlock.
@@ -969,7 +966,7 @@ xfs_qm_sync(
969 } 966 }
970 967
971 /* XXX a sentinel would be better */ 968 /* XXX a sentinel would be better */
972 recl = XFS_QI_MPLRECLAIMS(mp); 969 recl = mp->m_quotainfo->qi_dqreclaims;
973 if (!xfs_dqflock_nowait(dqp)) { 970 if (!xfs_dqflock_nowait(dqp)) {
974 if (flags & SYNC_TRYLOCK) { 971 if (flags & SYNC_TRYLOCK) {
975 xfs_dqunlock(dqp); 972 xfs_dqunlock(dqp);
@@ -989,7 +986,7 @@ xfs_qm_sync(
989 * Let go of the mplist lock. We don't want to hold it 986 * Let go of the mplist lock. We don't want to hold it
990 * across a disk write 987 * across a disk write
991 */ 988 */
992 xfs_qm_mplist_unlock(mp); 989 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
993 error = xfs_qm_dqflush(dqp, flags); 990 error = xfs_qm_dqflush(dqp, flags);
994 xfs_dqunlock(dqp); 991 xfs_dqunlock(dqp);
995 if (error && XFS_FORCED_SHUTDOWN(mp)) 992 if (error && XFS_FORCED_SHUTDOWN(mp))
@@ -997,17 +994,17 @@ xfs_qm_sync(
997 else if (error) 994 else if (error)
998 return error; 995 return error;
999 996
1000 xfs_qm_mplist_lock(mp); 997 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
1001 if (recl != XFS_QI_MPLRECLAIMS(mp)) { 998 if (recl != mp->m_quotainfo->qi_dqreclaims) {
1002 if (++restarts >= XFS_QM_SYNC_MAX_RESTARTS) 999 if (++restarts >= XFS_QM_SYNC_MAX_RESTARTS)
1003 break; 1000 break;
1004 1001
1005 xfs_qm_mplist_unlock(mp); 1002 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
1006 goto again; 1003 goto again;
1007 } 1004 }
1008 } 1005 }
1009 1006
1010 xfs_qm_mplist_unlock(mp); 1007 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
1011 return 0; 1008 return 0;
1012} 1009}
1013 1010
@@ -1052,8 +1049,9 @@ xfs_qm_init_quotainfo(
1052 return error; 1049 return error;
1053 } 1050 }
1054 1051
1055 xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0); 1052 INIT_LIST_HEAD(&qinf->qi_dqlist);
1056 lockdep_set_class(&qinf->qi_dqlist.qh_lock, &xfs_quota_mplist_class); 1053 mutex_init(&qinf->qi_dqlist_lock);
1054 lockdep_set_class(&qinf->qi_dqlist_lock, &xfs_quota_mplist_class);
1057 1055
1058 qinf->qi_dqreclaims = 0; 1056 qinf->qi_dqreclaims = 0;
1059 1057
@@ -1150,7 +1148,8 @@ xfs_qm_destroy_quotainfo(
1150 */ 1148 */
1151 xfs_qm_rele_quotafs_ref(mp); 1149 xfs_qm_rele_quotafs_ref(mp);
1152 1150
1153 xfs_qm_list_destroy(&qi->qi_dqlist); 1151 ASSERT(list_empty(&qi->qi_dqlist));
1152 mutex_destroy(&qi->qi_dqlist_lock);
1154 1153
1155 if (qi->qi_uquotaip) { 1154 if (qi->qi_uquotaip) {
1156 IRELE(qi->qi_uquotaip); 1155 IRELE(qi->qi_uquotaip);
@@ -1754,7 +1753,7 @@ xfs_qm_quotacheck(
1754 * There should be no cached dquots. The (simplistic) quotacheck 1753 * There should be no cached dquots. The (simplistic) quotacheck
1755 * algorithm doesn't like that. 1754 * algorithm doesn't like that.
1756 */ 1755 */
1757 ASSERT(XFS_QI_MPLNDQUOTS(mp) == 0); 1756 ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist));
1758 1757
1759 cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); 1758 cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
1760 1759
@@ -1825,7 +1824,7 @@ xfs_qm_quotacheck(
1825 mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD); 1824 mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
1826 mp->m_qflags |= flags; 1825 mp->m_qflags |= flags;
1827 1826
1828 XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++"); 1827 xfs_qm_dquot_list_print(mp);
1829 1828
1830 error_return: 1829 error_return:
1831 if (error) { 1830 if (error) {
@@ -1960,6 +1959,7 @@ xfs_qm_shake_freelist(
1960 for (dqp = xfs_Gqm->qm_dqfreelist.qh_next; 1959 for (dqp = xfs_Gqm->qm_dqfreelist.qh_next;
1961 ((dqp != (xfs_dquot_t *) &xfs_Gqm->qm_dqfreelist) && 1960 ((dqp != (xfs_dquot_t *) &xfs_Gqm->qm_dqfreelist) &&
1962 nreclaimed < howmany); ) { 1961 nreclaimed < howmany); ) {
1962 struct xfs_mount *mp = dqp->q_mount;
1963 xfs_dqlock(dqp); 1963 xfs_dqlock(dqp);
1964 1964
1965 /* 1965 /*
@@ -1981,16 +1981,16 @@ xfs_qm_shake_freelist(
1981 * life easier. 1981 * life easier.
1982 */ 1982 */
1983 if (dqp->dq_flags & XFS_DQ_INACTIVE) { 1983 if (dqp->dq_flags & XFS_DQ_INACTIVE) {
1984 ASSERT(dqp->q_mount == NULL); 1984 ASSERT(mp == NULL);
1985 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 1985 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
1986 ASSERT(dqp->HL_PREVP == NULL); 1986 ASSERT(dqp->HL_PREVP == NULL);
1987 ASSERT(dqp->MPL_PREVP == NULL); 1987 ASSERT(list_empty(&dqp->q_mplist));
1988 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); 1988 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
1989 nextdqp = dqp->dq_flnext; 1989 nextdqp = dqp->dq_flnext;
1990 goto off_freelist; 1990 goto off_freelist;
1991 } 1991 }
1992 1992
1993 ASSERT(dqp->MPL_PREVP); 1993 ASSERT(!list_empty(&dqp->q_mplist));
1994 /* 1994 /*
1995 * Try to grab the flush lock. If this dquot is in the process of 1995 * Try to grab the flush lock. If this dquot is in the process of
1996 * getting flushed to disk, we don't want to reclaim it. 1996 * getting flushed to disk, we don't want to reclaim it.
@@ -2018,7 +2018,7 @@ xfs_qm_shake_freelist(
2018 */ 2018 */
2019 error = xfs_qm_dqflush(dqp, 0); 2019 error = xfs_qm_dqflush(dqp, 0);
2020 if (error) { 2020 if (error) {
2021 xfs_fs_cmn_err(CE_WARN, dqp->q_mount, 2021 xfs_fs_cmn_err(CE_WARN, mp,
2022 "xfs_qm_dqflush_all: dquot %p flush failed", dqp); 2022 "xfs_qm_dqflush_all: dquot %p flush failed", dqp);
2023 } 2023 }
2024 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */ 2024 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
@@ -2045,7 +2045,7 @@ xfs_qm_shake_freelist(
2045 */ 2045 */
2046 hash = dqp->q_hash; 2046 hash = dqp->q_hash;
2047 ASSERT(hash); 2047 ASSERT(hash);
2048 if (! xfs_qm_mplist_nowait(dqp->q_mount)) { 2048 if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) {
2049 /* XXX put a sentinel so that we can come back here */ 2049 /* XXX put a sentinel so that we can come back here */
2050 xfs_dqfunlock(dqp); 2050 xfs_dqfunlock(dqp);
2051 xfs_dqunlock(dqp); 2051 xfs_dqunlock(dqp);
@@ -2064,10 +2064,12 @@ xfs_qm_shake_freelist(
2064#endif 2064#endif
2065 ASSERT(dqp->q_nrefs == 0); 2065 ASSERT(dqp->q_nrefs == 0);
2066 nextdqp = dqp->dq_flnext; 2066 nextdqp = dqp->dq_flnext;
2067 XQM_MPLIST_REMOVE(&(XFS_QI_MPL_LIST(dqp->q_mount)), dqp);
2068 XQM_HASHLIST_REMOVE(hash, dqp); 2067 XQM_HASHLIST_REMOVE(hash, dqp);
2068 list_del_init(&dqp->q_mplist);
2069 mp->m_quotainfo->qi_dquots--;
2070 mp->m_quotainfo->qi_dqreclaims++;
2069 xfs_dqfunlock(dqp); 2071 xfs_dqfunlock(dqp);
2070 xfs_qm_mplist_unlock(dqp->q_mount); 2072 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
2071 mutex_unlock(&hash->qh_lock); 2073 mutex_unlock(&hash->qh_lock);
2072 2074
2073 off_freelist: 2075 off_freelist:
@@ -2134,6 +2136,7 @@ xfs_qm_dqreclaim_one(void)
2134 xfs_qm_freelist_lock(xfs_Gqm); 2136 xfs_qm_freelist_lock(xfs_Gqm);
2135 2137
2136 FOREACH_DQUOT_IN_FREELIST(dqp, &(xfs_Gqm->qm_dqfreelist)) { 2138 FOREACH_DQUOT_IN_FREELIST(dqp, &(xfs_Gqm->qm_dqfreelist)) {
2139 struct xfs_mount *mp = dqp->q_mount;
2137 xfs_dqlock(dqp); 2140 xfs_dqlock(dqp);
2138 2141
2139 /* 2142 /*
@@ -2161,10 +2164,10 @@ xfs_qm_dqreclaim_one(void)
2161 * life easier. 2164 * life easier.
2162 */ 2165 */
2163 if (dqp->dq_flags & XFS_DQ_INACTIVE) { 2166 if (dqp->dq_flags & XFS_DQ_INACTIVE) {
2164 ASSERT(dqp->q_mount == NULL); 2167 ASSERT(mp == NULL);
2165 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 2168 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
2166 ASSERT(dqp->HL_PREVP == NULL); 2169 ASSERT(dqp->HL_PREVP == NULL);
2167 ASSERT(dqp->MPL_PREVP == NULL); 2170 ASSERT(list_empty(&dqp->q_mplist));
2168 XQM_FREELIST_REMOVE(dqp); 2171 XQM_FREELIST_REMOVE(dqp);
2169 xfs_dqunlock(dqp); 2172 xfs_dqunlock(dqp);
2170 dqpout = dqp; 2173 dqpout = dqp;
@@ -2173,7 +2176,7 @@ xfs_qm_dqreclaim_one(void)
2173 } 2176 }
2174 2177
2175 ASSERT(dqp->q_hash); 2178 ASSERT(dqp->q_hash);
2176 ASSERT(dqp->MPL_PREVP); 2179 ASSERT(!list_empty(&dqp->q_mplist));
2177 2180
2178 /* 2181 /*
2179 * Try to grab the flush lock. If this dquot is in the process of 2182 * Try to grab the flush lock. If this dquot is in the process of
@@ -2201,14 +2204,14 @@ xfs_qm_dqreclaim_one(void)
2201 */ 2204 */
2202 error = xfs_qm_dqflush(dqp, 0); 2205 error = xfs_qm_dqflush(dqp, 0);
2203 if (error) { 2206 if (error) {
2204 xfs_fs_cmn_err(CE_WARN, dqp->q_mount, 2207 xfs_fs_cmn_err(CE_WARN, mp,
2205 "xfs_qm_dqreclaim: dquot %p flush failed", dqp); 2208 "xfs_qm_dqreclaim: dquot %p flush failed", dqp);
2206 } 2209 }
2207 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */ 2210 xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
2208 continue; 2211 continue;
2209 } 2212 }
2210 2213
2211 if (! xfs_qm_mplist_nowait(dqp->q_mount)) { 2214 if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) {
2212 xfs_dqfunlock(dqp); 2215 xfs_dqfunlock(dqp);
2213 xfs_dqunlock(dqp); 2216 xfs_dqunlock(dqp);
2214 continue; 2217 continue;
@@ -2220,13 +2223,15 @@ xfs_qm_dqreclaim_one(void)
2220 trace_xfs_dqreclaim_unlink(dqp); 2223 trace_xfs_dqreclaim_unlink(dqp);
2221 2224
2222 ASSERT(dqp->q_nrefs == 0); 2225 ASSERT(dqp->q_nrefs == 0);
2223 XQM_MPLIST_REMOVE(&(XFS_QI_MPL_LIST(dqp->q_mount)), dqp); 2226 list_del_init(&dqp->q_mplist);
2227 mp->m_quotainfo->qi_dquots--;
2228 mp->m_quotainfo->qi_dqreclaims++;
2224 XQM_HASHLIST_REMOVE(dqp->q_hash, dqp); 2229 XQM_HASHLIST_REMOVE(dqp->q_hash, dqp);
2225 XQM_FREELIST_REMOVE(dqp); 2230 XQM_FREELIST_REMOVE(dqp);
2226 dqpout = dqp; 2231 dqpout = dqp;
2227 mutex_unlock(&dqp->q_hash->qh_lock); 2232 mutex_unlock(&dqp->q_hash->qh_lock);
2228 mplistunlock: 2233 mplistunlock:
2229 xfs_qm_mplist_unlock(dqp->q_mount); 2234 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
2230 xfs_dqfunlock(dqp); 2235 xfs_dqfunlock(dqp);
2231 xfs_dqunlock(dqp); 2236 xfs_dqunlock(dqp);
2232 if (dqpout) 2237 if (dqpout)
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 495564b8af38..91bd053e90ba 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -106,7 +106,9 @@ typedef struct xfs_qm {
106typedef struct xfs_quotainfo { 106typedef struct xfs_quotainfo {
107 xfs_inode_t *qi_uquotaip; /* user quota inode */ 107 xfs_inode_t *qi_uquotaip; /* user quota inode */
108 xfs_inode_t *qi_gquotaip; /* group quota inode */ 108 xfs_inode_t *qi_gquotaip; /* group quota inode */
109 xfs_dqlist_t qi_dqlist; /* all dquots in filesys */ 109 struct list_head qi_dqlist; /* all dquots in filesys */
110 struct mutex qi_dqlist_lock;
111 int qi_dquots;
110 int qi_dqreclaims; /* a change here indicates 112 int qi_dqreclaims; /* a change here indicates
111 a removal in the dqlist */ 113 a removal in the dqlist */
112 time_t qi_btimelimit; /* limit for blks timer */ 114 time_t qi_btimelimit; /* limit for blks timer */
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 50bee07d6b0e..c54fa7790bd8 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -442,7 +442,7 @@ xfs_qm_scall_getqstat(
442 IRELE(gip); 442 IRELE(gip);
443 } 443 }
444 if (mp->m_quotainfo) { 444 if (mp->m_quotainfo) {
445 out->qs_incoredqs = XFS_QI_MPLNDQUOTS(mp); 445 out->qs_incoredqs = mp->m_quotainfo->qi_dquots;
446 out->qs_btimelimit = XFS_QI_BTIMELIMIT(mp); 446 out->qs_btimelimit = XFS_QI_BTIMELIMIT(mp);
447 out->qs_itimelimit = XFS_QI_ITIMELIMIT(mp); 447 out->qs_itimelimit = XFS_QI_ITIMELIMIT(mp);
448 out->qs_rtbtimelimit = XFS_QI_RTBTIMELIMIT(mp); 448 out->qs_rtbtimelimit = XFS_QI_RTBTIMELIMIT(mp);
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 8286b2842b6b..6f4bbae51aca 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -29,7 +29,6 @@
29 29
30#define XFS_DQ_IS_ADDEDTO_TRX(t, d) ((d)->q_transp == (t)) 30#define XFS_DQ_IS_ADDEDTO_TRX(t, d) ((d)->q_transp == (t))
31 31
32#define XFS_QI_MPLRECLAIMS(mp) ((mp)->m_quotainfo->qi_dqreclaims)
33#define XFS_QI_UQIP(mp) ((mp)->m_quotainfo->qi_uquotaip) 32#define XFS_QI_UQIP(mp) ((mp)->m_quotainfo->qi_uquotaip)
34#define XFS_QI_GQIP(mp) ((mp)->m_quotainfo->qi_gquotaip) 33#define XFS_QI_GQIP(mp) ((mp)->m_quotainfo->qi_gquotaip)
35#define XFS_QI_DQCHUNKLEN(mp) ((mp)->m_quotainfo->qi_dqchunklen) 34#define XFS_QI_DQCHUNKLEN(mp) ((mp)->m_quotainfo->qi_dqchunklen)
@@ -41,19 +40,6 @@
41#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit) 40#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
42#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) 41#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
43 42
44#define XFS_QI_MPL_LIST(mp) ((mp)->m_quotainfo->qi_dqlist)
45#define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next)
46#define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems)
47
48#define xfs_qm_mplist_lock(mp) \
49 mutex_lock(&(XFS_QI_MPL_LIST(mp).qh_lock))
50#define xfs_qm_mplist_nowait(mp) \
51 mutex_trylock(&(XFS_QI_MPL_LIST(mp).qh_lock))
52#define xfs_qm_mplist_unlock(mp) \
53 mutex_unlock(&(XFS_QI_MPL_LIST(mp).qh_lock))
54#define XFS_QM_IS_MPLIST_LOCKED(mp) \
55 mutex_is_locked(&(XFS_QI_MPL_LIST(mp).qh_lock))
56
57#define xfs_qm_freelist_lock(qm) \ 43#define xfs_qm_freelist_lock(qm) \
58 mutex_lock(&((qm)->qm_dqfreelist.qh_lock)) 44 mutex_lock(&((qm)->qm_dqfreelist.qh_lock))
59#define xfs_qm_freelist_lock_nowait(qm) \ 45#define xfs_qm_freelist_lock_nowait(qm) \
@@ -88,8 +74,6 @@
88 74
89#define HL_PREVP dq_hashlist.ql_prevp 75#define HL_PREVP dq_hashlist.ql_prevp
90#define HL_NEXT dq_hashlist.ql_next 76#define HL_NEXT dq_hashlist.ql_next
91#define MPL_PREVP dq_mplist.ql_prevp
92#define MPL_NEXT dq_mplist.ql_next
93 77
94 78
95#define _LIST_REMOVE(h, dqp, PVP, NXT) \ 79#define _LIST_REMOVE(h, dqp, PVP, NXT) \
@@ -116,9 +100,6 @@
116 (h)->qh_nelems++; \ 100 (h)->qh_nelems++; \
117 } 101 }
118 102
119#define FOREACH_DQUOT_IN_MP(dqp, mp) \
120 for ((dqp) = XFS_QI_MPLNEXT(mp); (dqp) != NULL; (dqp) = (dqp)->MPL_NEXT)
121
122#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \ 103#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \
123for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \ 104for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
124 (dqp) = (dqp)->dq_flnext) 105 (dqp) = (dqp)->dq_flnext)
@@ -129,16 +110,10 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
129#define XQM_FREELIST_INSERT(h, dqp) \ 110#define XQM_FREELIST_INSERT(h, dqp) \
130 xfs_qm_freelist_append(h, dqp) 111 xfs_qm_freelist_append(h, dqp)
131 112
132#define XQM_MPLIST_INSERT(h, dqp) \
133 _LIST_INSERT(h, dqp, MPL_PREVP, MPL_NEXT)
134
135#define XQM_HASHLIST_REMOVE(h, dqp) \ 113#define XQM_HASHLIST_REMOVE(h, dqp) \
136 _LIST_REMOVE(h, dqp, HL_PREVP, HL_NEXT) 114 _LIST_REMOVE(h, dqp, HL_PREVP, HL_NEXT)
137#define XQM_FREELIST_REMOVE(dqp) \ 115#define XQM_FREELIST_REMOVE(dqp) \
138 xfs_qm_freelist_unlink(dqp) 116 xfs_qm_freelist_unlink(dqp)
139#define XQM_MPLIST_REMOVE(h, dqp) \
140 { _LIST_REMOVE(h, dqp, MPL_PREVP, MPL_NEXT); \
141 XFS_QI_MPLRECLAIMS((dqp)->q_mount)++; }
142 117
143#define XFS_DQ_IS_LOGITEM_INITD(dqp) ((dqp)->q_logitem.qli_dquot == (dqp)) 118#define XFS_DQ_IS_LOGITEM_INITD(dqp) ((dqp)->q_logitem.qli_dquot == (dqp))
144 119