aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef 'Jeff' Sipek <jeffpc@josefsipek.net>2008-03-27 02:58:27 -0400
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-04-17 21:41:57 -0400
commit535f6b3735db6ef6026537bfe55ae00c3d9cc1ee (patch)
tree49be6c12a19332a0ce0288143f67b44e4b8538b8
parenta45c796867df8dabc8eed6e72898d7ba1609bd7e (diff)
[XFS] Replace custom AIL linked-list code with struct list_head
Replace the xfs_ail_entry_t with a struct list_head and clean the surrounding code up. Also fixes a livelock in xfs_trans_first_push_ail() by terminating the loop at the head of the list correctly. SGI-PV: 978682 SGI-Modid: xfs-linux-melb:xfs-kern:30636a Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_trans.h7
-rw-r--r--fs/xfs/xfs_trans_ail.c149
3 files changed, 62 insertions, 96 deletions
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 7b37fa009297..77b39f66cead 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -220,7 +220,7 @@ extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
220#endif 220#endif
221 221
222typedef struct xfs_ail { 222typedef struct xfs_ail {
223 xfs_ail_entry_t xa_ail; 223 struct list_head xa_ail;
224 uint xa_gen; 224 uint xa_gen;
225 struct task_struct *xa_task; 225 struct task_struct *xa_task;
226 xfs_lsn_t xa_target; 226 xfs_lsn_t xa_target;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index b5effce00089..0804207c7391 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -113,13 +113,8 @@ struct xfs_mount;
113struct xfs_trans; 113struct xfs_trans;
114struct xfs_dquot_acct; 114struct xfs_dquot_acct;
115 115
116typedef struct xfs_ail_entry {
117 struct xfs_log_item *ail_forw; /* AIL forw pointer */
118 struct xfs_log_item *ail_back; /* AIL back pointer */
119} xfs_ail_entry_t;
120
121typedef struct xfs_log_item { 116typedef struct xfs_log_item {
122 xfs_ail_entry_t li_ail; /* AIL pointers */ 117 struct list_head li_ail; /* AIL pointers */
123 xfs_lsn_t li_lsn; /* last on-disk lsn */ 118 xfs_lsn_t li_lsn; /* last on-disk lsn */
124 struct xfs_log_item_desc *li_desc; /* ptr to current desc*/ 119 struct xfs_log_item_desc *li_desc; /* ptr to current desc*/
125 struct xfs_mount *li_mountp; /* ptr to fs mount */ 120 struct xfs_mount *li_mountp; /* ptr to fs mount */
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 76d470d8a1e6..13235ae9a582 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/*
@@ -329,7 +331,7 @@ xfs_trans_unlocked_item(
329 * 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
330 * 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.
331 */ 333 */
332 min_lip = xfs_ail_min(&mp->m_ail.xa_ail); 334 min_lip = xfs_ail_min(&mp->m_ail);
333 335
334 if (min_lip == lip) 336 if (min_lip == lip)
335 xfs_log_move_tail(mp, 1); 337 xfs_log_move_tail(mp, 1);
@@ -357,15 +359,13 @@ xfs_trans_update_ail(
357 xfs_log_item_t *lip, 359 xfs_log_item_t *lip,
358 xfs_lsn_t lsn) __releases(mp->m_ail_lock) 360 xfs_lsn_t lsn) __releases(mp->m_ail_lock)
359{ 361{
360 xfs_ail_entry_t *ailp;
361 xfs_log_item_t *dlip=NULL; 362 xfs_log_item_t *dlip=NULL;
362 xfs_log_item_t *mlip; /* ptr to minimum lip */ 363 xfs_log_item_t *mlip; /* ptr to minimum lip */
363 364
364 ailp = &(mp->m_ail.xa_ail); 365 mlip = xfs_ail_min(&mp->m_ail);
365 mlip = xfs_ail_min(ailp);
366 366
367 if (lip->li_flags & XFS_LI_IN_AIL) { 367 if (lip->li_flags & XFS_LI_IN_AIL) {
368 dlip = xfs_ail_delete(ailp, lip); 368 dlip = xfs_ail_delete(&mp->m_ail, lip);
369 ASSERT(dlip == lip); 369 ASSERT(dlip == lip);
370 } else { 370 } else {
371 lip->li_flags |= XFS_LI_IN_AIL; 371 lip->li_flags |= XFS_LI_IN_AIL;
@@ -373,11 +373,11 @@ xfs_trans_update_ail(
373 373
374 lip->li_lsn = lsn; 374 lip->li_lsn = lsn;
375 375
376 xfs_ail_insert(ailp, lip); 376 xfs_ail_insert(&mp->m_ail, lip);
377 mp->m_ail.xa_gen++; 377 mp->m_ail.xa_gen++;
378 378
379 if (mlip == dlip) { 379 if (mlip == dlip) {
380 mlip = xfs_ail_min(&(mp->m_ail.xa_ail)); 380 mlip = xfs_ail_min(&mp->m_ail);
381 spin_unlock(&mp->m_ail_lock); 381 spin_unlock(&mp->m_ail_lock);
382 xfs_log_move_tail(mp, mlip->li_lsn); 382 xfs_log_move_tail(mp, mlip->li_lsn);
383 } else { 383 } else {
@@ -407,14 +407,12 @@ xfs_trans_delete_ail(
407 xfs_mount_t *mp, 407 xfs_mount_t *mp,
408 xfs_log_item_t *lip) __releases(mp->m_ail_lock) 408 xfs_log_item_t *lip) __releases(mp->m_ail_lock)
409{ 409{
410 xfs_ail_entry_t *ailp;
411 xfs_log_item_t *dlip; 410 xfs_log_item_t *dlip;
412 xfs_log_item_t *mlip; 411 xfs_log_item_t *mlip;
413 412
414 if (lip->li_flags & XFS_LI_IN_AIL) { 413 if (lip->li_flags & XFS_LI_IN_AIL) {
415 ailp = &(mp->m_ail.xa_ail); 414 mlip = xfs_ail_min(&mp->m_ail);
416 mlip = xfs_ail_min(ailp); 415 dlip = xfs_ail_delete(&mp->m_ail, lip);
417 dlip = xfs_ail_delete(ailp, lip);
418 ASSERT(dlip == lip); 416 ASSERT(dlip == lip);
419 417
420 418
@@ -423,7 +421,7 @@ xfs_trans_delete_ail(
423 mp->m_ail.xa_gen++; 421 mp->m_ail.xa_gen++;
424 422
425 if (mlip == dlip) { 423 if (mlip == dlip) {
426 mlip = xfs_ail_min(&(mp->m_ail.xa_ail)); 424 mlip = xfs_ail_min(&mp->m_ail);
427 spin_unlock(&mp->m_ail_lock); 425 spin_unlock(&mp->m_ail_lock);
428 xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0)); 426 xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0));
429 } else { 427 } else {
@@ -461,7 +459,7 @@ xfs_trans_first_ail(
461{ 459{
462 xfs_log_item_t *lip; 460 xfs_log_item_t *lip;
463 461
464 lip = xfs_ail_min(&(mp->m_ail.xa_ail)); 462 lip = xfs_ail_min(&mp->m_ail);
465 *gen = (int)mp->m_ail.xa_gen; 463 *gen = (int)mp->m_ail.xa_gen;
466 464
467 return lip; 465 return lip;
@@ -485,9 +483,9 @@ xfs_trans_next_ail(
485 483
486 ASSERT(mp && lip && gen); 484 ASSERT(mp && lip && gen);
487 if (mp->m_ail.xa_gen == *gen) { 485 if (mp->m_ail.xa_gen == *gen) {
488 nlip = xfs_ail_next(&(mp->m_ail.xa_ail), lip); 486 nlip = xfs_ail_next(&mp->m_ail, lip);
489 } else { 487 } else {
490 nlip = xfs_ail_min(&(mp->m_ail).xa_ail); 488 nlip = xfs_ail_min(&mp->m_ail);
491 *gen = (int)mp->m_ail.xa_gen; 489 *gen = (int)mp->m_ail.xa_gen;
492 if (restarts != NULL) { 490 if (restarts != NULL) {
493 XFS_STATS_INC(xs_push_ail_restarts); 491 XFS_STATS_INC(xs_push_ail_restarts);
@@ -517,8 +515,7 @@ int
517xfs_trans_ail_init( 515xfs_trans_ail_init(
518 xfs_mount_t *mp) 516 xfs_mount_t *mp)
519{ 517{
520 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);
521 mp->m_ail.xa_ail.ail_back = (xfs_log_item_t*)&mp->m_ail.xa_ail;
522 return xfsaild_start(mp); 519 return xfsaild_start(mp);
523} 520}
524 521
@@ -537,7 +534,7 @@ xfs_trans_ail_destroy(
537 */ 534 */
538STATIC void 535STATIC void
539xfs_ail_insert( 536xfs_ail_insert(
540 xfs_ail_entry_t *base, 537 xfs_ail_t *ailp,
541 xfs_log_item_t *lip) 538 xfs_log_item_t *lip)
542/* ARGSUSED */ 539/* ARGSUSED */
543{ 540{
@@ -546,27 +543,22 @@ xfs_ail_insert(
546 /* 543 /*
547 * If the list is empty, just insert the item. 544 * If the list is empty, just insert the item.
548 */ 545 */
549 if (base->ail_back == (xfs_log_item_t*)base) { 546 if (list_empty(&ailp->xa_ail)) {
550 base->ail_forw = lip; 547 list_add(&lip->li_ail, &ailp->xa_ail);
551 base->ail_back = lip;
552 lip->li_ail.ail_forw = (xfs_log_item_t*)base;
553 lip->li_ail.ail_back = (xfs_log_item_t*)base;
554 return; 548 return;
555 } 549 }
556 550
557 next_lip = base->ail_back; 551 list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
558 while ((next_lip != (xfs_log_item_t*)base) && 552 if (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0)
559 (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) > 0)) { 553 break;
560 next_lip = next_lip->li_ail.ail_back;
561 } 554 }
562 ASSERT((next_lip == (xfs_log_item_t*)base) || 555
556 ASSERT((&next_lip->li_ail == &ailp->xa_ail) ||
563 (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0)); 557 (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0));
564 lip->li_ail.ail_forw = next_lip->li_ail.ail_forw;
565 lip->li_ail.ail_back = next_lip;
566 next_lip->li_ail.ail_forw = lip;
567 lip->li_ail.ail_forw->li_ail.ail_back = lip;
568 558
569 xfs_ail_check(base, lip); 559 list_add(&lip->li_ail, &next_lip->li_ail);
560
561 xfs_ail_check(ailp, lip);
570 return; 562 return;
571} 563}
572 564
@@ -576,15 +568,13 @@ xfs_ail_insert(
576/*ARGSUSED*/ 568/*ARGSUSED*/
577STATIC xfs_log_item_t * 569STATIC xfs_log_item_t *
578xfs_ail_delete( 570xfs_ail_delete(
579 xfs_ail_entry_t *base, 571 xfs_ail_t *ailp,
580 xfs_log_item_t *lip) 572 xfs_log_item_t *lip)
581/* ARGSUSED */ 573/* ARGSUSED */
582{ 574{
583 xfs_ail_check(base, lip); 575 xfs_ail_check(ailp, lip);
584 lip->li_ail.ail_forw->li_ail.ail_back = lip->li_ail.ail_back; 576
585 lip->li_ail.ail_back->li_ail.ail_forw = lip->li_ail.ail_forw; 577 list_del(&lip->li_ail);
586 lip->li_ail.ail_forw = NULL;
587 lip->li_ail.ail_back = NULL;
588 578
589 return lip; 579 return lip;
590} 580}
@@ -595,14 +585,13 @@ xfs_ail_delete(
595 */ 585 */
596STATIC xfs_log_item_t * 586STATIC xfs_log_item_t *
597xfs_ail_min( 587xfs_ail_min(
598 xfs_ail_entry_t *base) 588 xfs_ail_t *ailp)
599/* ARGSUSED */ 589/* ARGSUSED */
600{ 590{
601 register xfs_log_item_t *forw = base->ail_forw; 591 if (list_empty(&ailp->xa_ail))
602 if (forw == (xfs_log_item_t*)base) {
603 return NULL; 592 return NULL;
604 } 593
605 return forw; 594 return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
606} 595}
607 596
608/* 597/*
@@ -612,15 +601,14 @@ xfs_ail_min(
612 */ 601 */
613STATIC xfs_log_item_t * 602STATIC xfs_log_item_t *
614xfs_ail_next( 603xfs_ail_next(
615 xfs_ail_entry_t *base, 604 xfs_ail_t *ailp,
616 xfs_log_item_t *lip) 605 xfs_log_item_t *lip)
617/* ARGSUSED */ 606/* ARGSUSED */
618{ 607{
619 if (lip->li_ail.ail_forw == (xfs_log_item_t*)base) { 608 if (lip->li_ail.next == &ailp->xa_ail)
620 return NULL; 609 return NULL;
621 }
622 return lip->li_ail.ail_forw;
623 610
611 return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
624} 612}
625 613
626#ifdef DEBUG 614#ifdef DEBUG
@@ -629,57 +617,40 @@ xfs_ail_next(
629 */ 617 */
630STATIC void 618STATIC void
631xfs_ail_check( 619xfs_ail_check(
632 xfs_ail_entry_t *base, 620 xfs_ail_t *ailp,
633 xfs_log_item_t *lip) 621 xfs_log_item_t *lip)
634{ 622{
635 xfs_log_item_t *prev_lip; 623 xfs_log_item_t *prev_lip;
636 624
637 prev_lip = base->ail_forw; 625 if (list_empty(&ailp->xa_ail))
638 if (prev_lip == (xfs_log_item_t*)base) {
639 /*
640 * Make sure the pointers are correct when the list
641 * is empty.
642 */
643 ASSERT(base->ail_back == (xfs_log_item_t*)base);
644 return; 626 return;
645 }
646 627
647 /* 628 /*
648 * Check the next and previous entries are valid. 629 * Check the next and previous entries are valid.
649 */ 630 */
650 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); 631 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
651 prev_lip = lip->li_ail.ail_back; 632 prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
652 if (prev_lip != (xfs_log_item_t*)base) { 633 if (&prev_lip->li_ail != &ailp->xa_ail)
653 ASSERT(prev_lip->li_ail.ail_forw == lip);
654 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);
655 } 635
656 prev_lip = lip->li_ail.ail_forw; 636 prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
657 if (prev_lip != (xfs_log_item_t*)base) { 637 if (&prev_lip->li_ail != &ailp->xa_ail)
658 ASSERT(prev_lip->li_ail.ail_back == lip);
659 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);
660 }
661 639
662 640
663#ifdef XFS_TRANS_DEBUG 641#ifdef XFS_TRANS_DEBUG
664 /* 642 /*
665 * Walk the list checking forward and backward pointers, 643 * Walk the list checking lsn ordering, and that every entry has the
666 * 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
667 * flag set. This is really expensive, so only do it when 645 * when specifically debugging the transaction subsystem.
668 * specifically debugging the transaction subsystem.
669 */ 646 */
670 prev_lip = (xfs_log_item_t*)base; 647 prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
671 while (lip != (xfs_log_item_t*)base) { 648 list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
672 if (prev_lip != (xfs_log_item_t*)base) { 649 if (&prev_lip->li_ail != &ailp->xa_ail)
673 ASSERT(prev_lip->li_ail.ail_forw == lip);
674 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);
675 }
676 ASSERT(lip->li_ail.ail_back == prev_lip);
677 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); 651 ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
678 prev_lip = lip; 652 prev_lip = lip;
679 lip = lip->li_ail.ail_forw;
680 } 653 }
681 ASSERT(lip == (xfs_log_item_t*)base);
682 ASSERT(base->ail_back == prev_lip);
683#endif /* XFS_TRANS_DEBUG */ 654#endif /* XFS_TRANS_DEBUG */
684} 655}
685#endif /* DEBUG */ 656#endif /* DEBUG */