aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans_ail.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2008-04-22 07:34:25 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2008-04-22 07:34:25 -0400
commitf838bad1b3be8ca0c785ee0e0c570dfda74cf377 (patch)
tree5a842a8056a708cfad55a20fa8ab733dd94b0903 /fs/xfs/xfs_trans_ail.c
parentdd919660aacdf4adfcd279556aa03e595f7f0fc2 (diff)
parent807501475fce0ebe68baedf87f202c3e4ee0d12c (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/xfs/xfs_trans_ail.c')
-rw-r--r--fs/xfs/xfs_trans_ail.c168
1 files changed, 71 insertions, 97 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 4d6330eddc8d..1f77c00af566 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -28,13 +28,13 @@
28#include "xfs_trans_priv.h" 28#include "xfs_trans_priv.h"
29#include "xfs_error.h" 29#include "xfs_error.h"
30 30
31STATIC void xfs_ail_insert(xfs_ail_entry_t *, xfs_log_item_t *); 31STATIC void xfs_ail_insert(xfs_ail_t *, xfs_log_item_t *);
32STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_entry_t *, xfs_log_item_t *); 32STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_t *, xfs_log_item_t *);
33STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_entry_t *); 33STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_t *);
34STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_entry_t *, xfs_log_item_t *); 34STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_t *, xfs_log_item_t *);
35 35
36#ifdef DEBUG 36#ifdef DEBUG
37STATIC void xfs_ail_check(xfs_ail_entry_t *, xfs_log_item_t *); 37STATIC void xfs_ail_check(xfs_ail_t *, xfs_log_item_t *);
38#else 38#else
39#define xfs_ail_check(a,l) 39#define xfs_ail_check(a,l)
40#endif /* DEBUG */ 40#endif /* DEBUG */
@@ -57,7 +57,7 @@ xfs_trans_tail_ail(
57 xfs_log_item_t *lip; 57 xfs_log_item_t *lip;
58 58
59 spin_lock(&mp->m_ail_lock); 59 spin_lock(&mp->m_ail_lock);
60 lip = xfs_ail_min(&(mp->m_ail.xa_ail)); 60 lip = xfs_ail_min(&mp->m_ail);
61 if (lip == NULL) { 61 if (lip == NULL) {
62 lsn = (xfs_lsn_t)0; 62 lsn = (xfs_lsn_t)0;
63 } else { 63 } else {
@@ -91,7 +91,7 @@ xfs_trans_push_ail(
91{ 91{
92 xfs_log_item_t *lip; 92 xfs_log_item_t *lip;
93 93
94 lip = xfs_ail_min(&mp->m_ail.xa_ail); 94 lip = xfs_ail_min(&mp->m_ail);
95 if (lip && !XFS_FORCED_SHUTDOWN(mp)) { 95 if (lip && !XFS_FORCED_SHUTDOWN(mp)) {
96 if (XFS_LSN_CMP(threshold_lsn, mp->m_ail.xa_target) > 0) 96 if (XFS_LSN_CMP(threshold_lsn, mp->m_ail.xa_target) > 0)
97 xfsaild_wakeup(mp, threshold_lsn); 97 xfsaild_wakeup(mp, threshold_lsn);
@@ -111,15 +111,17 @@ xfs_trans_first_push_ail(
111{ 111{
112 xfs_log_item_t *lip; 112 xfs_log_item_t *lip;
113 113
114 lip = xfs_ail_min(&(mp->m_ail.xa_ail)); 114 lip = xfs_ail_min(&mp->m_ail);
115 *gen = (int)mp->m_ail.xa_gen; 115 *gen = (int)mp->m_ail.xa_gen;
116 if (lsn == 0) 116 if (lsn == 0)
117 return lip; 117 return lip;
118 118
119 while (lip && (XFS_LSN_CMP(lip->li_lsn, lsn) < 0)) 119 list_for_each_entry(lip, &mp->m_ail.xa_ail, li_ail) {
120 lip = lip->li_ail.ail_forw; 120 if (XFS_LSN_CMP(lip->li_lsn, lsn) >= 0)
121 return lip;
122 }
121 123
122 return lip; 124 return NULL;
123} 125}
124 126
125/* 127/*
@@ -261,16 +263,19 @@ xfsaild_push(
261 xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE); 263 xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
262 } 264 }
263 265
264 /* 266 if (!count) {
265 * We reached the target so wait a bit longer for I/O to complete and 267 /* We're past our target or empty, so idle */
266 * remove pushed items from the AIL before we start the next scan from 268 tout = 1000;
267 * the start of the AIL. 269 } else if (XFS_LSN_CMP(lsn, target) >= 0) {
268 */ 270 /*
269 if ((XFS_LSN_CMP(lsn, target) >= 0)) { 271 * We reached the target so wait a bit longer for I/O to
272 * complete and remove pushed items from the AIL before we
273 * start the next scan from the start of the AIL.
274 */
270 tout += 20; 275 tout += 20;
271 last_pushed_lsn = 0; 276 last_pushed_lsn = 0;
272 } else if ((restarts > XFS_TRANS_PUSH_AIL_RESTARTS) || 277 } else if ((restarts > XFS_TRANS_PUSH_AIL_RESTARTS) ||
273 (count && ((stuck * 100) / count > 90))) { 278 ((stuck * 100) / count > 90)) {
274 /* 279 /*
275 * Either there is a lot of contention on the AIL or we 280 * Either there is a lot of contention on the AIL or we
276 * are stuck due to operations in progress. "Stuck" in this 281 * are stuck due to operations in progress. "Stuck" in this
@@ -326,7 +331,7 @@ xfs_trans_unlocked_item(
326 * the call to xfs_log_move_tail() doesn't do anything if there's 331 * the call to xfs_log_move_tail() doesn't do anything if there's
327 * not enough free space to wake people up so we're safe calling it. 332 * not enough free space to wake people up so we're safe calling it.
328 */ 333 */
329 min_lip = xfs_ail_min(&mp->m_ail.xa_ail); 334 min_lip = xfs_ail_min(&mp->m_ail);
330 335
331 if (min_lip == lip) 336 if (min_lip == lip)
332 xfs_log_move_tail(mp, 1); 337 xfs_log_move_tail(mp, 1);
@@ -354,15 +359,13 @@ xfs_trans_update_ail(
354 xfs_log_item_t *lip, 359 xfs_log_item_t *lip,
355 xfs_lsn_t lsn) __releases(mp->m_ail_lock) 360 xfs_lsn_t lsn) __releases(mp->m_ail_lock)
356{ 361{
357 xfs_ail_entry_t *ailp;
358 xfs_log_item_t *dlip=NULL; 362 xfs_log_item_t *dlip=NULL;
359 xfs_log_item_t *mlip; /* ptr to minimum lip */ 363 xfs_log_item_t *mlip; /* ptr to minimum lip */
360 364
361 ailp = &(mp->m_ail.xa_ail); 365 mlip = xfs_ail_min(&mp->m_ail);
362 mlip = xfs_ail_min(ailp);
363 366
364 if (lip->li_flags & XFS_LI_IN_AIL) { 367 if (lip->li_flags & XFS_LI_IN_AIL) {
365 dlip = xfs_ail_delete(ailp, lip); 368 dlip = xfs_ail_delete(&mp->m_ail, lip);
366 ASSERT(dlip == lip); 369 ASSERT(dlip == lip);
367 } else { 370 } else {
368 lip->li_flags |= XFS_LI_IN_AIL; 371 lip->li_flags |= XFS_LI_IN_AIL;
@@ -370,11 +373,11 @@ xfs_trans_update_ail(
370 373
371 lip->li_lsn = lsn; 374 lip->li_lsn = lsn;
372 375
373 xfs_ail_insert(ailp, lip); 376 xfs_ail_insert(&mp->m_ail, lip);
374 mp->m_ail.xa_gen++; 377 mp->m_ail.xa_gen++;
375 378
376 if (mlip == dlip) { 379 if (mlip == dlip) {
377 mlip = xfs_ail_min(&(mp->m_ail.xa_ail)); 380 mlip = xfs_ail_min(&mp->m_ail);
378 spin_unlock(&mp->m_ail_lock); 381 spin_unlock(&mp->m_ail_lock);
379 xfs_log_move_tail(mp, mlip->li_lsn); 382 xfs_log_move_tail(mp, mlip->li_lsn);
380 } else { 383 } else {
@@ -404,14 +407,12 @@ xfs_trans_delete_ail(
404 xfs_mount_t *mp, 407 xfs_mount_t *mp,
405 xfs_log_item_t *lip) __releases(mp->m_ail_lock) 408 xfs_log_item_t *lip) __releases(mp->m_ail_lock)
406{ 409{
407 xfs_ail_entry_t *ailp;
408 xfs_log_item_t *dlip; 410 xfs_log_item_t *dlip;
409 xfs_log_item_t *mlip; 411 xfs_log_item_t *mlip;
410 412
411 if (lip->li_flags & XFS_LI_IN_AIL) { 413 if (lip->li_flags & XFS_LI_IN_AIL) {
412 ailp = &(mp->m_ail.xa_ail); 414 mlip = xfs_ail_min(&mp->m_ail);
413 mlip = xfs_ail_min(ailp); 415 dlip = xfs_ail_delete(&mp->m_ail, lip);
414 dlip = xfs_ail_delete(ailp, lip);
415 ASSERT(dlip == lip); 416 ASSERT(dlip == lip);
416 417
417 418
@@ -420,7 +421,7 @@ xfs_trans_delete_ail(
420 mp->m_ail.xa_gen++; 421 mp->m_ail.xa_gen++;
421 422
422 if (mlip == dlip) { 423 if (mlip == dlip) {
423 mlip = xfs_ail_min(&(mp->m_ail.xa_ail)); 424 mlip = xfs_ail_min(&mp->m_ail);
424 spin_unlock(&mp->m_ail_lock); 425 spin_unlock(&mp->m_ail_lock);
425 xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0)); 426 xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0));
426 } else { 427 } else {
@@ -437,7 +438,7 @@ xfs_trans_delete_ail(
437 else { 438 else {
438 xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, 439 xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
439 "%s: attempting to delete a log item that is not in the AIL", 440 "%s: attempting to delete a log item that is not in the AIL",
440 __FUNCTION__); 441 __func__);
441 spin_unlock(&mp->m_ail_lock); 442 spin_unlock(&mp->m_ail_lock);
442 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 443 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
443 } 444 }
@@ -458,7 +459,7 @@ xfs_trans_first_ail(
458{ 459{
459 xfs_log_item_t *lip; 460 xfs_log_item_t *lip;
460 461
461 lip = xfs_ail_min(&(mp->m_ail.xa_ail)); 462 lip = xfs_ail_min(&mp->m_ail);
462 *gen = (int)mp->m_ail.xa_gen; 463 *gen = (int)mp->m_ail.xa_gen;
463 464
464 return lip; 465 return lip;
@@ -482,9 +483,9 @@ xfs_trans_next_ail(
482 483
483 ASSERT(mp && lip && gen); 484 ASSERT(mp && lip && gen);
484 if (mp->m_ail.xa_gen == *gen) { 485 if (mp->m_ail.xa_gen == *gen) {
485 nlip = xfs_ail_next(&(mp->m_ail.xa_ail), lip); 486 nlip = xfs_ail_next(&mp->m_ail, lip);
486 } else { 487 } else {
487 nlip = xfs_ail_min(&(mp->m_ail).xa_ail); 488 nlip = xfs_ail_min(&mp->m_ail);
488 *gen = (int)mp->m_ail.xa_gen; 489 *gen = (int)mp->m_ail.xa_gen;
489 if (restarts != NULL) { 490 if (restarts != NULL) {
490 XFS_STATS_INC(xs_push_ail_restarts); 491 XFS_STATS_INC(xs_push_ail_restarts);
@@ -514,8 +515,7 @@ int
514xfs_trans_ail_init( 515xfs_trans_ail_init(
515 xfs_mount_t *mp) 516 xfs_mount_t *mp)
516{ 517{
517 mp->m_ail.xa_ail.ail_forw = (xfs_log_item_t*)&mp->m_ail.xa_ail; 518 INIT_LIST_HEAD(&mp->m_ail.xa_ail);
518 mp->m_ail.xa_ail.ail_back = (xfs_log_item_t*)&mp->m_ail.xa_ail;
519 return xfsaild_start(mp); 519 return xfsaild_start(mp);
520} 520}
521 521
@@ -534,7 +534,7 @@ xfs_trans_ail_destroy(
534 */ 534 */
535STATIC void 535STATIC void
536xfs_ail_insert( 536xfs_ail_insert(
537 xfs_ail_entry_t *base, 537 xfs_ail_t *ailp,
538 xfs_log_item_t *lip) 538 xfs_log_item_t *lip)
539/* ARGSUSED */ 539/* ARGSUSED */
540{ 540{
@@ -543,27 +543,22 @@ xfs_ail_insert(
543 /* 543 /*
544 * If the list is empty, just insert the item. 544 * If the list is empty, just insert the item.
545 */ 545 */
546 if (base->ail_back == (xfs_log_item_t*)base) { 546 if (list_empty(&ailp->xa_ail)) {
547 base->ail_forw = lip; 547 list_add(&lip->li_ail, &ailp->xa_ail);
548 base->ail_back = lip;
549 lip->li_ail.ail_forw = (xfs_log_item_t*)base;
550 lip->li_ail.ail_back = (xfs_log_item_t*)base;
551 return; 548 return;
552 } 549 }
553 550
554 next_lip = base->ail_back; 551 list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
555 while ((next_lip != (xfs_log_item_t*)base) && 552 if (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0)
556 (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) > 0)) { 553 break;
557 next_lip = next_lip->li_ail.ail_back;
558 } 554 }
559 ASSERT((next_lip == (xfs_log_item_t*)base) || 555
556 ASSERT((&next_lip->li_ail == &ailp->xa_ail) ||
560 (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0)); 557 (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0));
561 lip->li_ail.ail_forw = next_lip->li_ail.ail_forw;
562 lip->li_ail.ail_back = next_lip;
563 next_lip->li_ail.ail_forw = lip;
564 lip->li_ail.ail_forw->li_ail.ail_back = lip;
565 558
566 xfs_ail_check(base, lip); 559 list_add(&lip->li_ail, &next_lip->li_ail);
560
561 xfs_ail_check(ailp, lip);
567 return; 562 return;
568} 563}
569 564
@@ -573,15 +568,13 @@ xfs_ail_insert(
573/*ARGSUSED*/ 568/*ARGSUSED*/
574STATIC xfs_log_item_t * 569STATIC xfs_log_item_t *
575xfs_ail_delete( 570xfs_ail_delete(
576 xfs_ail_entry_t *base, 571 xfs_ail_t *ailp,
577 xfs_log_item_t *lip) 572 xfs_log_item_t *lip)
578/* ARGSUSED */ 573/* ARGSUSED */
579{ 574{
580 xfs_ail_check(base, lip); 575 xfs_ail_check(ailp, lip);
581 lip->li_ail.ail_forw->li_ail.ail_back = lip->li_ail.ail_back; 576
582 lip->li_ail.ail_back->li_ail.ail_forw = lip->li_ail.ail_forw; 577 list_del(&lip->li_ail);
583 lip->li_ail.ail_forw = NULL;
584 lip->li_ail.ail_back = NULL;
585 578
586 return lip; 579 return lip;
587} 580}
@@ -592,14 +585,13 @@ xfs_ail_delete(
592 */ 585 */
593STATIC xfs_log_item_t * 586STATIC xfs_log_item_t *
594xfs_ail_min( 587xfs_ail_min(
595 xfs_ail_entry_t *base) 588 xfs_ail_t *ailp)
596/* ARGSUSED */ 589/* ARGSUSED */
597{ 590{
598 register xfs_log_item_t *forw = base->ail_forw; 591 if (list_empty(&ailp->xa_ail))
599 if (forw == (xfs_log_item_t*)base) {
600 return NULL; 592 return NULL;
601 } 593
602 return forw; 594 return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
603} 595}
604 596
605/* 597/*
@@ -609,15 +601,14 @@ xfs_ail_min(
609 */ 601 */
610STATIC xfs_log_item_t * 602STATIC xfs_log_item_t *
611xfs_ail_next( 603xfs_ail_next(
612 xfs_ail_entry_t *base, 604 xfs_ail_t *ailp,
613 xfs_log_item_t *lip) 605 xfs_log_item_t *lip)
614/* ARGSUSED */ 606/* ARGSUSED */
615{ 607{
616 if (lip->li_ail.ail_forw == (xfs_log_item_t*)base) { 608 if (lip->li_ail.next == &ailp->xa_ail)
617 return NULL; 609 return NULL;
618 }
619 return lip->li_ail.ail_forw;
620 610
611 return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
621} 612}
622 613
623#ifdef DEBUG 614#ifdef DEBUG
@@ -626,57 +617,40 @@ xfs_ail_next(
626 */ 617 */
627STATIC void 618STATIC void
628xfs_ail_check( 619xfs_ail_check(
629 xfs_ail_entry_t *base, 620 xfs_ail_t *ailp,
630 xfs_log_item_t *lip) 621 xfs_log_item_t *lip)
631{ 622{
632 xfs_log_item_t *prev_lip; 623 xfs_log_item_t *prev_lip;
633 624
634 prev_lip = base->ail_forw; 625 if (list_empty(&ailp->xa_ail))
635 if (prev_lip == (xfs_log_item_t*)base) {
636 /*
637 * Make sure the pointers are correct when the list
638 * is empty.
639 */
640 ASSERT(base->ail_back == (xfs_log_item_t*)base);
641 return; 626 return;
642 }
643 627
644 /* 628 /*
645 * Check the next and previous entries are valid. 629 * Check the next and previous entries are valid.
646 */ 630 */
647 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); 631 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
648 prev_lip = lip->li_ail.ail_back; 632 prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
649 if (prev_lip != (xfs_log_item_t*)base) { 633 if (&prev_lip->li_ail != &ailp->xa_ail)
650 ASSERT(prev_lip->li_ail.ail_forw == lip);
651 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0); 634 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
652 } 635
653 prev_lip = lip->li_ail.ail_forw; 636 prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
654 if (prev_lip != (xfs_log_item_t*)base) { 637 if (&prev_lip->li_ail != &ailp->xa_ail)
655 ASSERT(prev_lip->li_ail.ail_back == lip);
656 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0); 638 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
657 }
658 639
659 640
660#ifdef XFS_TRANS_DEBUG 641#ifdef XFS_TRANS_DEBUG
661 /* 642 /*
662 * Walk the list checking forward and backward pointers, 643 * Walk the list checking lsn ordering, and that every entry has the
663 * lsn ordering, and that every entry has the XFS_LI_IN_AIL 644 * XFS_LI_IN_AIL flag set. This is really expensive, so only do it
664 * flag set. This is really expensive, so only do it when 645 * when specifically debugging the transaction subsystem.
665 * specifically debugging the transaction subsystem.
666 */ 646 */
667 prev_lip = (xfs_log_item_t*)base; 647 prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
668 while (lip != (xfs_log_item_t*)base) { 648 list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
669 if (prev_lip != (xfs_log_item_t*)base) { 649 if (&prev_lip->li_ail != &ailp->xa_ail)
670 ASSERT(prev_lip->li_ail.ail_forw == lip);
671 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0); 650 ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
672 }
673 ASSERT(lip->li_ail.ail_back == prev_lip);
674 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); 651 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
675 prev_lip = lip; 652 prev_lip = lip;
676 lip = lip->li_ail.ail_forw;
677 } 653 }
678 ASSERT(lip == (xfs_log_item_t*)base);
679 ASSERT(base->ail_back == prev_lip);
680#endif /* XFS_TRANS_DEBUG */ 654#endif /* XFS_TRANS_DEBUG */
681} 655}
682#endif /* DEBUG */ 656#endif /* DEBUG */