diff options
Diffstat (limited to 'fs/xfs/quota')
-rw-r--r-- | fs/xfs/quota/xfs_dquot.c | 39 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_dquot.h | 4 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_dquot_item.c | 45 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 57 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.h | 3 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm_bhv.c | 5 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm_syscalls.c | 151 |
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 | */ |
93 | STATIC void | 92 | STATIC void |
94 | xfs_qm_dquot_logitem_pin( | 93 | xfs_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 */ |
112 | STATIC void | 109 | STATIC 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 | */ |
399 | int | 398 | void |
400 | xfs_qm_unmount_quotas( | 399 | xfs_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 | } | ||
453 | out: | ||
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 | |||
998 | int | 965 | int |
999 | xfs_qm_sync( | 966 | xfs_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 { | |||
106 | typedef struct xfs_quotainfo { | 106 | typedef 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 *); | |||
168 | extern void xfs_qm_mount_quotas(xfs_mount_t *); | 167 | extern void xfs_qm_mount_quotas(xfs_mount_t *); |
169 | extern int xfs_qm_quotacheck(xfs_mount_t *); | 168 | extern int xfs_qm_quotacheck(xfs_mount_t *); |
170 | extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); | 169 | extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); |
171 | extern int xfs_qm_unmount_quotas(xfs_mount_t *); | 170 | extern void xfs_qm_unmount_quotas(xfs_mount_t *); |
172 | extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); | 171 | extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); |
173 | extern int xfs_qm_sync(xfs_mount_t *, int); | 172 | extern 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 | ||
52 | STATIC void | 51 | STATIC void |
53 | xfs_fill_statvfs_from_dquot( | 52 | xfs_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( | |||
88 | STATIC void | 87 | STATIC void |
89 | xfs_qm_statvfs( | 88 | xfs_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 | */ |
1030 | void | 1027 | STATIC void |
1031 | xfs_qm_dqrele_all_inodes( | 1028 | xfs_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); | ||
1043 | again: | ||
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. | 1110 | void |
1111 | */ | 1111 | xfs_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 | /*------------------------------------------------------------------------*/ |