aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/quota
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/quota')
-rw-r--r--fs/xfs/quota/xfs_dquot.c39
-rw-r--r--fs/xfs/quota/xfs_dquot.h4
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c45
-rw-r--r--fs/xfs/quota/xfs_qm.c57
-rw-r--r--fs/xfs/quota/xfs_qm.h3
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c5
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c151
7 files changed, 126 insertions, 178 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index f2705f2fd43c..591ca6602bfb 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -101,7 +101,7 @@ xfs_qm_dqinit(
101 if (brandnewdquot) { 101 if (brandnewdquot) {
102 dqp->dq_flnext = dqp->dq_flprev = dqp; 102 dqp->dq_flnext = dqp->dq_flprev = dqp;
103 mutex_init(&dqp->q_qlock); 103 mutex_init(&dqp->q_qlock);
104 sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq"); 104 init_waitqueue_head(&dqp->q_pinwait);
105 105
106 /* 106 /*
107 * Because we want to use a counting completion, complete 107 * Because we want to use a counting completion, complete
@@ -131,7 +131,7 @@ xfs_qm_dqinit(
131 dqp->q_res_bcount = 0; 131 dqp->q_res_bcount = 0;
132 dqp->q_res_icount = 0; 132 dqp->q_res_icount = 0;
133 dqp->q_res_rtbcount = 0; 133 dqp->q_res_rtbcount = 0;
134 dqp->q_pincount = 0; 134 atomic_set(&dqp->q_pincount, 0);
135 dqp->q_hash = NULL; 135 dqp->q_hash = NULL;
136 ASSERT(dqp->dq_flnext == dqp->dq_flprev); 136 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
137 137
@@ -1221,16 +1221,14 @@ xfs_qm_dqflush(
1221 xfs_dqtrace_entry(dqp, "DQFLUSH"); 1221 xfs_dqtrace_entry(dqp, "DQFLUSH");
1222 1222
1223 /* 1223 /*
1224 * If not dirty, nada. 1224 * If not dirty, or it's pinned and we are not supposed to
1225 * block, nada.
1225 */ 1226 */
1226 if (!XFS_DQ_IS_DIRTY(dqp)) { 1227 if (!XFS_DQ_IS_DIRTY(dqp) ||
1228 (!(flags & XFS_QMOPT_SYNC) && atomic_read(&dqp->q_pincount) > 0)) {
1227 xfs_dqfunlock(dqp); 1229 xfs_dqfunlock(dqp);
1228 return (0); 1230 return 0;
1229 } 1231 }
1230
1231 /*
1232 * Cant flush a pinned dquot. Wait for it.
1233 */
1234 xfs_qm_dqunpin_wait(dqp); 1232 xfs_qm_dqunpin_wait(dqp);
1235 1233
1236 /* 1234 /*
@@ -1274,10 +1272,8 @@ xfs_qm_dqflush(
1274 dqp->dq_flags &= ~(XFS_DQ_DIRTY); 1272 dqp->dq_flags &= ~(XFS_DQ_DIRTY);
1275 mp = dqp->q_mount; 1273 mp = dqp->q_mount;
1276 1274
1277 /* lsn is 64 bits */ 1275 xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn,
1278 spin_lock(&mp->m_ail_lock); 1276 &dqp->q_logitem.qli_item.li_lsn);
1279 dqp->q_logitem.qli_flush_lsn = dqp->q_logitem.qli_item.li_lsn;
1280 spin_unlock(&mp->m_ail_lock);
1281 1277
1282 /* 1278 /*
1283 * Attach an iodone routine so that we can remove this dquot from the 1279 * Attach an iodone routine so that we can remove this dquot from the
@@ -1323,8 +1319,10 @@ xfs_qm_dqflush_done(
1323 xfs_dq_logitem_t *qip) 1319 xfs_dq_logitem_t *qip)
1324{ 1320{
1325 xfs_dquot_t *dqp; 1321 xfs_dquot_t *dqp;
1322 struct xfs_ail *ailp;
1326 1323
1327 dqp = qip->qli_dquot; 1324 dqp = qip->qli_dquot;
1325 ailp = qip->qli_item.li_ailp;
1328 1326
1329 /* 1327 /*
1330 * We only want to pull the item from the AIL if its 1328 * We only want to pull the item from the AIL if its
@@ -1337,15 +1335,12 @@ xfs_qm_dqflush_done(
1337 if ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && 1335 if ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
1338 qip->qli_item.li_lsn == qip->qli_flush_lsn) { 1336 qip->qli_item.li_lsn == qip->qli_flush_lsn) {
1339 1337
1340 spin_lock(&dqp->q_mount->m_ail_lock); 1338 /* xfs_trans_ail_delete() drops the AIL lock. */
1341 /* 1339 spin_lock(&ailp->xa_lock);
1342 * xfs_trans_delete_ail() drops the AIL lock.
1343 */
1344 if (qip->qli_item.li_lsn == qip->qli_flush_lsn) 1340 if (qip->qli_item.li_lsn == qip->qli_flush_lsn)
1345 xfs_trans_delete_ail(dqp->q_mount, 1341 xfs_trans_ail_delete(ailp, (xfs_log_item_t*)qip);
1346 (xfs_log_item_t*)qip);
1347 else 1342 else
1348 spin_unlock(&dqp->q_mount->m_ail_lock); 1343 spin_unlock(&ailp->xa_lock);
1349 } 1344 }
1350 1345
1351 /* 1346 /*
@@ -1375,7 +1370,7 @@ xfs_dqunlock(
1375 mutex_unlock(&(dqp->q_qlock)); 1370 mutex_unlock(&(dqp->q_qlock));
1376 if (dqp->q_logitem.qli_dquot == dqp) { 1371 if (dqp->q_logitem.qli_dquot == dqp) {
1377 /* Once was dqp->q_mount, but might just have been cleared */ 1372 /* Once was dqp->q_mount, but might just have been cleared */
1378 xfs_trans_unlocked_item(dqp->q_logitem.qli_item.li_mountp, 1373 xfs_trans_unlocked_item(dqp->q_logitem.qli_item.li_ailp,
1379 (xfs_log_item_t*)&(dqp->q_logitem)); 1374 (xfs_log_item_t*)&(dqp->q_logitem));
1380 } 1375 }
1381} 1376}
@@ -1489,7 +1484,7 @@ xfs_qm_dqpurge(
1489 "xfs_qm_dqpurge: dquot %p flush failed", dqp); 1484 "xfs_qm_dqpurge: dquot %p flush failed", dqp);
1490 xfs_dqflock(dqp); 1485 xfs_dqflock(dqp);
1491 } 1486 }
1492 ASSERT(dqp->q_pincount == 0); 1487 ASSERT(atomic_read(&dqp->q_pincount) == 0);
1493 ASSERT(XFS_FORCED_SHUTDOWN(mp) || 1488 ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
1494 !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL)); 1489 !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
1495 1490
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 8958d0faf8d3..7e455337e2ba 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -83,8 +83,8 @@ typedef struct xfs_dquot {
83 xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ 83 xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
84 mutex_t q_qlock; /* quota lock */ 84 mutex_t q_qlock; /* quota lock */
85 struct completion q_flush; /* flush completion queue */ 85 struct completion q_flush; /* flush completion queue */
86 uint q_pincount; /* pin count for this dquot */ 86 atomic_t q_pincount; /* dquot pin count */
87 sv_t q_pinwait; /* sync var for pinning */ 87 wait_queue_head_t q_pinwait; /* dquot pinning wait queue */
88#ifdef XFS_DQUOT_TRACE 88#ifdef XFS_DQUOT_TRACE
89 struct ktrace *q_trace; /* trace header structure */ 89 struct ktrace *q_trace; /* trace header structure */
90#endif 90#endif
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index f028644caa5e..1728f6a7c4f5 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -88,25 +88,22 @@ xfs_qm_dquot_logitem_format(
88 88
89/* 89/*
90 * Increment the pin count of the given dquot. 90 * Increment the pin count of the given dquot.
91 * This value is protected by pinlock spinlock in the xQM structure.
92 */ 91 */
93STATIC void 92STATIC void
94xfs_qm_dquot_logitem_pin( 93xfs_qm_dquot_logitem_pin(
95 xfs_dq_logitem_t *logitem) 94 xfs_dq_logitem_t *logitem)
96{ 95{
97 xfs_dquot_t *dqp; 96 xfs_dquot_t *dqp = logitem->qli_dquot;
98 97
99 dqp = logitem->qli_dquot;
100 ASSERT(XFS_DQ_IS_LOCKED(dqp)); 98 ASSERT(XFS_DQ_IS_LOCKED(dqp));
101 spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); 99 atomic_inc(&dqp->q_pincount);
102 dqp->q_pincount++;
103 spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
104} 100}
105 101
106/* 102/*
107 * Decrement the pin count of the given dquot, and wake up 103 * Decrement the pin count of the given dquot, and wake up
108 * anyone in xfs_dqwait_unpin() if the count goes to 0. The 104 * anyone in xfs_dqwait_unpin() if the count goes to 0. The
109 * dquot must have been previously pinned with a call to xfs_dqpin(). 105 * dquot must have been previously pinned with a call to
106 * xfs_qm_dquot_logitem_pin().
110 */ 107 */
111/* ARGSUSED */ 108/* ARGSUSED */
112STATIC void 109STATIC void
@@ -114,16 +111,11 @@ xfs_qm_dquot_logitem_unpin(
114 xfs_dq_logitem_t *logitem, 111 xfs_dq_logitem_t *logitem,
115 int stale) 112 int stale)
116{ 113{
117 xfs_dquot_t *dqp; 114 xfs_dquot_t *dqp = logitem->qli_dquot;
118 115
119 dqp = logitem->qli_dquot; 116 ASSERT(atomic_read(&dqp->q_pincount) > 0);
120 ASSERT(dqp->q_pincount > 0); 117 if (atomic_dec_and_test(&dqp->q_pincount))
121 spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); 118 wake_up(&dqp->q_pinwait);
122 dqp->q_pincount--;
123 if (dqp->q_pincount == 0) {
124 sv_broadcast(&dqp->q_pinwait);
125 }
126 spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
127} 119}
128 120
129/* ARGSUSED */ 121/* ARGSUSED */
@@ -193,21 +185,14 @@ xfs_qm_dqunpin_wait(
193 xfs_dquot_t *dqp) 185 xfs_dquot_t *dqp)
194{ 186{
195 ASSERT(XFS_DQ_IS_LOCKED(dqp)); 187 ASSERT(XFS_DQ_IS_LOCKED(dqp));
196 if (dqp->q_pincount == 0) { 188 if (atomic_read(&dqp->q_pincount) == 0)
197 return; 189 return;
198 }
199 190
200 /* 191 /*
201 * Give the log a push so we don't wait here too long. 192 * Give the log a push so we don't wait here too long.
202 */ 193 */
203 xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE); 194 xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE);
204 spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); 195 wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
205 if (dqp->q_pincount == 0) {
206 spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
207 return;
208 }
209 sv_wait(&(dqp->q_pinwait), PINOD,
210 &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s);
211} 196}
212 197
213/* 198/*
@@ -310,7 +295,7 @@ xfs_qm_dquot_logitem_trylock(
310 uint retval; 295 uint retval;
311 296
312 dqp = qip->qli_dquot; 297 dqp = qip->qli_dquot;
313 if (dqp->q_pincount > 0) 298 if (atomic_read(&dqp->q_pincount) > 0)
314 return (XFS_ITEM_PINNED); 299 return (XFS_ITEM_PINNED);
315 300
316 if (! xfs_qm_dqlock_nowait(dqp)) 301 if (! xfs_qm_dqlock_nowait(dqp))
@@ -568,14 +553,16 @@ xfs_qm_qoffend_logitem_committed(
568 xfs_lsn_t lsn) 553 xfs_lsn_t lsn)
569{ 554{
570 xfs_qoff_logitem_t *qfs; 555 xfs_qoff_logitem_t *qfs;
556 struct xfs_ail *ailp;
571 557
572 qfs = qfe->qql_start_lip; 558 qfs = qfe->qql_start_lip;
573 spin_lock(&qfs->qql_item.li_mountp->m_ail_lock); 559 ailp = qfs->qql_item.li_ailp;
560 spin_lock(&ailp->xa_lock);
574 /* 561 /*
575 * Delete the qoff-start logitem from the AIL. 562 * Delete the qoff-start logitem from the AIL.
576 * xfs_trans_delete_ail() drops the AIL lock. 563 * xfs_trans_ail_delete() drops the AIL lock.
577 */ 564 */
578 xfs_trans_delete_ail(qfs->qql_item.li_mountp, (xfs_log_item_t *)qfs); 565 xfs_trans_ail_delete(ailp, (xfs_log_item_t *)qfs);
579 kmem_free(qfs); 566 kmem_free(qfs);
580 kmem_free(qfe); 567 kmem_free(qfe);
581 return (xfs_lsn_t)-1; 568 return (xfs_lsn_t)-1;
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index df0ffef9775a..6b13960cf318 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -20,7 +20,6 @@
20#include "xfs_bit.h" 20#include "xfs_bit.h"
21#include "xfs_log.h" 21#include "xfs_log.h"
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_clnt.h"
24#include "xfs_trans.h" 23#include "xfs_trans.h"
25#include "xfs_sb.h" 24#include "xfs_sb.h"
26#include "xfs_ag.h" 25#include "xfs_ag.h"
@@ -396,13 +395,10 @@ xfs_qm_mount_quotas(
396/* 395/*
397 * Called from the vfsops layer. 396 * Called from the vfsops layer.
398 */ 397 */
399int 398void
400xfs_qm_unmount_quotas( 399xfs_qm_unmount_quotas(
401 xfs_mount_t *mp) 400 xfs_mount_t *mp)
402{ 401{
403 xfs_inode_t *uqp, *gqp;
404 int error = 0;
405
406 /* 402 /*
407 * Release the dquots that root inode, et al might be holding, 403 * Release the dquots that root inode, et al might be holding,
408 * before we flush quotas and blow away the quotainfo structure. 404 * before we flush quotas and blow away the quotainfo structure.
@@ -415,43 +411,18 @@ xfs_qm_unmount_quotas(
415 xfs_qm_dqdetach(mp->m_rsumip); 411 xfs_qm_dqdetach(mp->m_rsumip);
416 412
417 /* 413 /*
418 * Flush out the quota inodes. 414 * Release the quota inodes.
419 */ 415 */
420 uqp = gqp = NULL;
421 if (mp->m_quotainfo) { 416 if (mp->m_quotainfo) {
422 if ((uqp = mp->m_quotainfo->qi_uquotaip) != NULL) { 417 if (mp->m_quotainfo->qi_uquotaip) {
423 xfs_ilock(uqp, XFS_ILOCK_EXCL); 418 IRELE(mp->m_quotainfo->qi_uquotaip);
424 xfs_iflock(uqp); 419 mp->m_quotainfo->qi_uquotaip = NULL;
425 error = xfs_iflush(uqp, XFS_IFLUSH_SYNC);
426 xfs_iunlock(uqp, XFS_ILOCK_EXCL);
427 if (unlikely(error == EFSCORRUPTED)) {
428 XFS_ERROR_REPORT("xfs_qm_unmount_quotas(1)",
429 XFS_ERRLEVEL_LOW, mp);
430 goto out;
431 }
432 } 420 }
433 if ((gqp = mp->m_quotainfo->qi_gquotaip) != NULL) { 421 if (mp->m_quotainfo->qi_gquotaip) {
434 xfs_ilock(gqp, XFS_ILOCK_EXCL); 422 IRELE(mp->m_quotainfo->qi_gquotaip);
435 xfs_iflock(gqp); 423 mp->m_quotainfo->qi_gquotaip = NULL;
436 error = xfs_iflush(gqp, XFS_IFLUSH_SYNC);
437 xfs_iunlock(gqp, XFS_ILOCK_EXCL);
438 if (unlikely(error == EFSCORRUPTED)) {
439 XFS_ERROR_REPORT("xfs_qm_unmount_quotas(2)",
440 XFS_ERRLEVEL_LOW, mp);
441 goto out;
442 }
443 } 424 }
444 } 425 }
445 if (uqp) {
446 IRELE(uqp);
447 mp->m_quotainfo->qi_uquotaip = NULL;
448 }
449 if (gqp) {
450 IRELE(gqp);
451 mp->m_quotainfo->qi_gquotaip = NULL;
452 }
453out:
454 return XFS_ERROR(error);
455} 426}
456 427
457/* 428/*
@@ -987,14 +958,10 @@ xfs_qm_dqdetach(
987} 958}
988 959
989/* 960/*
990 * This is called by VFS_SYNC and flags arg determines the caller, 961 * This is called to sync quotas. We can be told to use non-blocking
991 * and its motives, as done in xfs_sync. 962 * semantics by either the SYNC_BDFLUSH flag or the absence of the
992 * 963 * SYNC_WAIT flag.
993 * vfs_sync: SYNC_FSDATA|SYNC_ATTR|SYNC_BDFLUSH 0x31
994 * syscall sync: SYNC_FSDATA|SYNC_ATTR|SYNC_DELWRI 0x25
995 * umountroot : SYNC_WAIT | SYNC_CLOSE | SYNC_ATTR | SYNC_FSDATA
996 */ 964 */
997
998int 965int
999xfs_qm_sync( 966xfs_qm_sync(
1000 xfs_mount_t *mp, 967 xfs_mount_t *mp,
@@ -1137,7 +1104,6 @@ xfs_qm_init_quotainfo(
1137 return error; 1104 return error;
1138 } 1105 }
1139 1106
1140 spin_lock_init(&qinf->qi_pinlock);
1141 xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0); 1107 xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0);
1142 qinf->qi_dqreclaims = 0; 1108 qinf->qi_dqreclaims = 0;
1143 1109
@@ -1234,7 +1200,6 @@ xfs_qm_destroy_quotainfo(
1234 */ 1200 */
1235 xfs_qm_rele_quotafs_ref(mp); 1201 xfs_qm_rele_quotafs_ref(mp);
1236 1202
1237 spinlock_destroy(&qi->qi_pinlock);
1238 xfs_qm_list_destroy(&qi->qi_dqlist); 1203 xfs_qm_list_destroy(&qi->qi_dqlist);
1239 1204
1240 if (qi->qi_uquotaip) { 1205 if (qi->qi_uquotaip) {
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 44f25349e478..ddf09166387c 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -106,7 +106,6 @@ 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 spinlock_t qi_pinlock; /* dquot pinning lock */
110 xfs_dqlist_t qi_dqlist; /* all dquots in filesys */ 109 xfs_dqlist_t qi_dqlist; /* all dquots in filesys */
111 int qi_dqreclaims; /* a change here indicates 110 int qi_dqreclaims; /* a change here indicates
112 a removal in the dqlist */ 111 a removal in the dqlist */
@@ -168,7 +167,7 @@ extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
168extern void xfs_qm_mount_quotas(xfs_mount_t *); 167extern void xfs_qm_mount_quotas(xfs_mount_t *);
169extern int xfs_qm_quotacheck(xfs_mount_t *); 168extern int xfs_qm_quotacheck(xfs_mount_t *);
170extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); 169extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *);
171extern int xfs_qm_unmount_quotas(xfs_mount_t *); 170extern void xfs_qm_unmount_quotas(xfs_mount_t *);
172extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); 171extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
173extern int xfs_qm_sync(xfs_mount_t *, int); 172extern int xfs_qm_sync(xfs_mount_t *, int);
174 173
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index eea2e60b456b..bc6c5cca3e12 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -20,7 +20,6 @@
20#include "xfs_bit.h" 20#include "xfs_bit.h"
21#include "xfs_log.h" 21#include "xfs_log.h"
22#include "xfs_inum.h" 22#include "xfs_inum.h"
23#include "xfs_clnt.h"
24#include "xfs_trans.h" 23#include "xfs_trans.h"
25#include "xfs_sb.h" 24#include "xfs_sb.h"
26#include "xfs_ag.h" 25#include "xfs_ag.h"
@@ -51,7 +50,7 @@
51 50
52STATIC void 51STATIC void
53xfs_fill_statvfs_from_dquot( 52xfs_fill_statvfs_from_dquot(
54 bhv_statvfs_t *statp, 53 struct kstatfs *statp,
55 xfs_disk_dquot_t *dp) 54 xfs_disk_dquot_t *dp)
56{ 55{
57 __uint64_t limit; 56 __uint64_t limit;
@@ -88,7 +87,7 @@ xfs_fill_statvfs_from_dquot(
88STATIC void 87STATIC void
89xfs_qm_statvfs( 88xfs_qm_statvfs(
90 xfs_inode_t *ip, 89 xfs_inode_t *ip,
91 bhv_statvfs_t *statp) 90 struct kstatfs *statp)
92{ 91{
93 xfs_mount_t *mp = ip->i_mount; 92 xfs_mount_t *mp = ip->i_mount;
94 xfs_dquot_t *dqp; 93 xfs_dquot_t *dqp;
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 1a3b803dfa55..68139b38aede 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -127,7 +127,7 @@ xfs_qm_quotactl(
127 break; 127 break;
128 128
129 case Q_XQUOTASYNC: 129 case Q_XQUOTASYNC:
130 return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL)); 130 return xfs_sync_inodes(mp, SYNC_DELWRI);
131 131
132 default: 132 default:
133 break; 133 break;
@@ -1022,101 +1022,104 @@ xfs_qm_export_flags(
1022 1022
1023 1023
1024/* 1024/*
1025 * Go thru all the inodes in the file system, releasing their dquots. 1025 * Release all the dquots on the inodes in an AG.
1026 * Note that the mount structure gets modified to indicate that quotas are off
1027 * AFTER this, in the case of quotaoff. This also gets called from
1028 * xfs_rootumount.
1029 */ 1026 */
1030void 1027STATIC void
1031xfs_qm_dqrele_all_inodes( 1028xfs_qm_dqrele_inodes_ag(
1032 struct xfs_mount *mp, 1029 xfs_mount_t *mp,
1033 uint flags) 1030 int ag,
1031 uint flags)
1034{ 1032{
1035 xfs_inode_t *ip, *topino; 1033 xfs_inode_t *ip = NULL;
1036 uint ireclaims; 1034 xfs_perag_t *pag = &mp->m_perag[ag];
1037 struct inode *vp; 1035 int first_index = 0;
1038 boolean_t vnode_refd; 1036 int nr_found;
1039 1037
1040 ASSERT(mp->m_quotainfo);
1041
1042 XFS_MOUNT_ILOCK(mp);
1043again:
1044 ip = mp->m_inodes;
1045 if (ip == NULL) {
1046 XFS_MOUNT_IUNLOCK(mp);
1047 return;
1048 }
1049 do { 1038 do {
1050 /* Skip markers inserted by xfs_sync */ 1039 /*
1051 if (ip->i_mount == NULL) { 1040 * use a gang lookup to find the next inode in the tree
1052 ip = ip->i_mnext; 1041 * as the tree is sparse and a gang lookup walks to find
1053 continue; 1042 * the number of objects requested.
1043 */
1044 read_lock(&pag->pag_ici_lock);
1045 nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
1046 (void**)&ip, first_index, 1);
1047
1048 if (!nr_found) {
1049 read_unlock(&pag->pag_ici_lock);
1050 break;
1054 } 1051 }
1055 /* Root inode, rbmip and rsumip have associated blocks */ 1052
1053 /*
1054 * Update the index for the next lookup. Catch overflows
1055 * into the next AG range which can occur if we have inodes
1056 * in the last block of the AG and we are currently
1057 * pointing to the last inode.
1058 */
1059 first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
1060 if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino)) {
1061 read_unlock(&pag->pag_ici_lock);
1062 break;
1063 }
1064
1065 /* skip quota inodes */
1056 if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) { 1066 if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) {
1057 ASSERT(ip->i_udquot == NULL); 1067 ASSERT(ip->i_udquot == NULL);
1058 ASSERT(ip->i_gdquot == NULL); 1068 ASSERT(ip->i_gdquot == NULL);
1059 ip = ip->i_mnext; 1069 read_unlock(&pag->pag_ici_lock);
1060 continue; 1070 continue;
1061 } 1071 }
1062 vp = VFS_I(ip); 1072
1063 if (!vp) { 1073 /*
1064 ASSERT(ip->i_udquot == NULL); 1074 * If we can't get a reference on the inode, it must be
1065 ASSERT(ip->i_gdquot == NULL); 1075 * in reclaim. Leave it for the reclaim code to flush.
1066 ip = ip->i_mnext; 1076 */
1077 if (!igrab(VFS_I(ip))) {
1078 read_unlock(&pag->pag_ici_lock);
1067 continue; 1079 continue;
1068 } 1080 }
1069 vnode_refd = B_FALSE; 1081 read_unlock(&pag->pag_ici_lock);
1070 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) { 1082
1071 ireclaims = mp->m_ireclaims; 1083 /* avoid new inodes though we shouldn't find any here */
1072 topino = mp->m_inodes; 1084 if (xfs_iflags_test(ip, XFS_INEW)) {
1073 vp = vn_grab(vp); 1085 IRELE(ip);
1074 if (!vp) 1086 continue;
1075 goto again;
1076
1077 XFS_MOUNT_IUNLOCK(mp);
1078 /* XXX restart limit ? */
1079 xfs_ilock(ip, XFS_ILOCK_EXCL);
1080 vnode_refd = B_TRUE;
1081 } else {
1082 ireclaims = mp->m_ireclaims;
1083 topino = mp->m_inodes;
1084 XFS_MOUNT_IUNLOCK(mp);
1085 } 1087 }
1086 1088
1087 /* 1089 xfs_ilock(ip, XFS_ILOCK_EXCL);
1088 * We don't keep the mountlock across the dqrele() call,
1089 * since it can take a while..
1090 */
1091 if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) { 1090 if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
1092 xfs_qm_dqrele(ip->i_udquot); 1091 xfs_qm_dqrele(ip->i_udquot);
1093 ip->i_udquot = NULL; 1092 ip->i_udquot = NULL;
1094 } 1093 }
1095 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { 1094 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) &&
1095 ip->i_gdquot) {
1096 xfs_qm_dqrele(ip->i_gdquot); 1096 xfs_qm_dqrele(ip->i_gdquot);
1097 ip->i_gdquot = NULL; 1097 ip->i_gdquot = NULL;
1098 } 1098 }
1099 xfs_iunlock(ip, XFS_ILOCK_EXCL); 1099 xfs_iput(ip, XFS_ILOCK_EXCL);
1100 /* 1100
1101 * Wait until we've dropped the ilock and mountlock to 1101 } while (nr_found);
1102 * do the vn_rele. Or be condemned to an eternity in the 1102}
1103 * inactive code in hell. 1103
1104 */ 1104/*
1105 if (vnode_refd) 1105 * Go thru all the inodes in the file system, releasing their dquots.
1106 IRELE(ip); 1106 * Note that the mount structure gets modified to indicate that quotas are off
1107 XFS_MOUNT_ILOCK(mp); 1107 * AFTER this, in the case of quotaoff. This also gets called from
1108 /* 1108 * xfs_rootumount.
1109 * If an inode was inserted or removed, we gotta 1109 */
1110 * start over again. 1110void
1111 */ 1111xfs_qm_dqrele_all_inodes(
1112 if (topino != mp->m_inodes || mp->m_ireclaims != ireclaims) { 1112 struct xfs_mount *mp,
1113 /* XXX use a sentinel */ 1113 uint flags)
1114 goto again; 1114{
1115 } 1115 int i;
1116 ip = ip->i_mnext;
1117 } while (ip != mp->m_inodes);
1118 1116
1119 XFS_MOUNT_IUNLOCK(mp); 1117 ASSERT(mp->m_quotainfo);
1118 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
1119 if (!mp->m_perag[i].pag_ici_init)
1120 continue;
1121 xfs_qm_dqrele_inodes_ag(mp, i, flags);
1122 }
1120} 1123}
1121 1124
1122/*------------------------------------------------------------------------*/ 1125/*------------------------------------------------------------------------*/