diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_trace.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_log.c | 139 | ||||
-rw-r--r-- | fs/xfs/xfs_log_priv.h | 16 |
3 files changed, 97 insertions, 60 deletions
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h index b180e1bf8257..647af2a2e7aa 100644 --- a/fs/xfs/linux-2.6/xfs_trace.h +++ b/fs/xfs/linux-2.6/xfs_trace.h | |||
@@ -837,6 +837,7 @@ DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep1); | |||
837 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake1); | 837 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake1); |
838 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep2); | 838 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep2); |
839 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake2); | 839 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake2); |
840 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up); | ||
840 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); | 841 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); |
841 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); | 842 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); |
842 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); | 843 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); |
@@ -844,6 +845,7 @@ DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep1); | |||
844 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake1); | 845 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake1); |
845 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep2); | 846 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep2); |
846 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake2); | 847 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake2); |
848 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake_up); | ||
847 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); | 849 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); |
848 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); | 850 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); |
849 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_sub); | 851 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_sub); |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index a1d7d12fc51f..6fcc9d0af524 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -682,12 +682,12 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
682 | if (tail_lsn != 1) | 682 | if (tail_lsn != 1) |
683 | atomic64_set(&log->l_tail_lsn, tail_lsn); | 683 | atomic64_set(&log->l_tail_lsn, tail_lsn); |
684 | 684 | ||
685 | spin_lock(&log->l_grant_lock); | 685 | if (!list_empty_careful(&log->l_writeq)) { |
686 | if (!list_empty(&log->l_writeq)) { | ||
687 | #ifdef DEBUG | 686 | #ifdef DEBUG |
688 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | 687 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) |
689 | panic("Recovery problem"); | 688 | panic("Recovery problem"); |
690 | #endif | 689 | #endif |
690 | spin_lock(&log->l_grant_write_lock); | ||
691 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); | 691 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); |
692 | list_for_each_entry(tic, &log->l_writeq, t_queue) { | 692 | list_for_each_entry(tic, &log->l_writeq, t_queue) { |
693 | ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); | 693 | ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); |
@@ -696,15 +696,18 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
696 | break; | 696 | break; |
697 | tail_lsn = 0; | 697 | tail_lsn = 0; |
698 | free_bytes -= tic->t_unit_res; | 698 | free_bytes -= tic->t_unit_res; |
699 | trace_xfs_log_regrant_write_wake_up(log, tic); | ||
699 | wake_up(&tic->t_wait); | 700 | wake_up(&tic->t_wait); |
700 | } | 701 | } |
702 | spin_unlock(&log->l_grant_write_lock); | ||
701 | } | 703 | } |
702 | 704 | ||
703 | if (!list_empty(&log->l_reserveq)) { | 705 | if (!list_empty_careful(&log->l_reserveq)) { |
704 | #ifdef DEBUG | 706 | #ifdef DEBUG |
705 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | 707 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) |
706 | panic("Recovery problem"); | 708 | panic("Recovery problem"); |
707 | #endif | 709 | #endif |
710 | spin_lock(&log->l_grant_reserve_lock); | ||
708 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); | 711 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); |
709 | list_for_each_entry(tic, &log->l_reserveq, t_queue) { | 712 | list_for_each_entry(tic, &log->l_reserveq, t_queue) { |
710 | if (tic->t_flags & XLOG_TIC_PERM_RESERV) | 713 | if (tic->t_flags & XLOG_TIC_PERM_RESERV) |
@@ -715,11 +718,12 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
715 | break; | 718 | break; |
716 | tail_lsn = 0; | 719 | tail_lsn = 0; |
717 | free_bytes -= need_bytes; | 720 | free_bytes -= need_bytes; |
721 | trace_xfs_log_grant_wake_up(log, tic); | ||
718 | wake_up(&tic->t_wait); | 722 | wake_up(&tic->t_wait); |
719 | } | 723 | } |
724 | spin_unlock(&log->l_grant_reserve_lock); | ||
720 | } | 725 | } |
721 | spin_unlock(&log->l_grant_lock); | 726 | } |
722 | } /* xfs_log_move_tail */ | ||
723 | 727 | ||
724 | /* | 728 | /* |
725 | * Determine if we have a transaction that has gone to disk | 729 | * Determine if we have a transaction that has gone to disk |
@@ -1010,6 +1014,8 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1010 | xlog_assign_grant_head(&log->l_grant_write_head, 1, 0); | 1014 | xlog_assign_grant_head(&log->l_grant_write_head, 1, 0); |
1011 | INIT_LIST_HEAD(&log->l_reserveq); | 1015 | INIT_LIST_HEAD(&log->l_reserveq); |
1012 | INIT_LIST_HEAD(&log->l_writeq); | 1016 | INIT_LIST_HEAD(&log->l_writeq); |
1017 | spin_lock_init(&log->l_grant_reserve_lock); | ||
1018 | spin_lock_init(&log->l_grant_write_lock); | ||
1013 | 1019 | ||
1014 | error = EFSCORRUPTED; | 1020 | error = EFSCORRUPTED; |
1015 | if (xfs_sb_version_hassector(&mp->m_sb)) { | 1021 | if (xfs_sb_version_hassector(&mp->m_sb)) { |
@@ -2477,6 +2483,18 @@ restart: | |||
2477 | * | 2483 | * |
2478 | * Once a ticket gets put onto the reserveq, it will only return after | 2484 | * Once a ticket gets put onto the reserveq, it will only return after |
2479 | * the needed reservation is satisfied. | 2485 | * the needed reservation is satisfied. |
2486 | * | ||
2487 | * This function is structured so that it has a lock free fast path. This is | ||
2488 | * necessary because every new transaction reservation will come through this | ||
2489 | * path. Hence any lock will be globally hot if we take it unconditionally on | ||
2490 | * every pass. | ||
2491 | * | ||
2492 | * As tickets are only ever moved on and off the reserveq under the | ||
2493 | * l_grant_reserve_lock, we only need to take that lock if we are going | ||
2494 | * to add the ticket to the queue and sleep. We can avoid taking the lock if the | ||
2495 | * ticket was never added to the reserveq because the t_queue list head will be | ||
2496 | * empty and we hold the only reference to it so it can safely be checked | ||
2497 | * unlocked. | ||
2480 | */ | 2498 | */ |
2481 | STATIC int | 2499 | STATIC int |
2482 | xlog_grant_log_space(xlog_t *log, | 2500 | xlog_grant_log_space(xlog_t *log, |
@@ -2490,13 +2508,20 @@ xlog_grant_log_space(xlog_t *log, | |||
2490 | panic("grant Recovery problem"); | 2508 | panic("grant Recovery problem"); |
2491 | #endif | 2509 | #endif |
2492 | 2510 | ||
2493 | /* Is there space or do we need to sleep? */ | ||
2494 | spin_lock(&log->l_grant_lock); | ||
2495 | |||
2496 | trace_xfs_log_grant_enter(log, tic); | 2511 | trace_xfs_log_grant_enter(log, tic); |
2497 | 2512 | ||
2513 | need_bytes = tic->t_unit_res; | ||
2514 | if (tic->t_flags & XFS_LOG_PERM_RESERV) | ||
2515 | need_bytes *= tic->t_ocnt; | ||
2516 | |||
2498 | /* something is already sleeping; insert new transaction at end */ | 2517 | /* something is already sleeping; insert new transaction at end */ |
2499 | if (!list_empty(&log->l_reserveq)) { | 2518 | if (!list_empty_careful(&log->l_reserveq)) { |
2519 | spin_lock(&log->l_grant_reserve_lock); | ||
2520 | /* recheck the queue now we are locked */ | ||
2521 | if (list_empty(&log->l_reserveq)) { | ||
2522 | spin_unlock(&log->l_grant_reserve_lock); | ||
2523 | goto redo; | ||
2524 | } | ||
2500 | list_add_tail(&tic->t_queue, &log->l_reserveq); | 2525 | list_add_tail(&tic->t_queue, &log->l_reserveq); |
2501 | 2526 | ||
2502 | trace_xfs_log_grant_sleep1(log, tic); | 2527 | trace_xfs_log_grant_sleep1(log, tic); |
@@ -2509,48 +2534,47 @@ xlog_grant_log_space(xlog_t *log, | |||
2509 | goto error_return; | 2534 | goto error_return; |
2510 | 2535 | ||
2511 | XFS_STATS_INC(xs_sleep_logspace); | 2536 | XFS_STATS_INC(xs_sleep_logspace); |
2512 | xlog_wait(&tic->t_wait, &log->l_grant_lock); | 2537 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); |
2513 | 2538 | ||
2514 | /* | 2539 | /* |
2515 | * If we got an error, and the filesystem is shutting down, | 2540 | * If we got an error, and the filesystem is shutting down, |
2516 | * we'll catch it down below. So just continue... | 2541 | * we'll catch it down below. So just continue... |
2517 | */ | 2542 | */ |
2518 | trace_xfs_log_grant_wake1(log, tic); | 2543 | trace_xfs_log_grant_wake1(log, tic); |
2519 | spin_lock(&log->l_grant_lock); | ||
2520 | } | 2544 | } |
2521 | if (tic->t_flags & XFS_LOG_PERM_RESERV) | ||
2522 | need_bytes = tic->t_unit_res*tic->t_ocnt; | ||
2523 | else | ||
2524 | need_bytes = tic->t_unit_res; | ||
2525 | 2545 | ||
2526 | redo: | 2546 | redo: |
2527 | if (XLOG_FORCED_SHUTDOWN(log)) | 2547 | if (XLOG_FORCED_SHUTDOWN(log)) |
2528 | goto error_return; | 2548 | goto error_return_unlocked; |
2529 | 2549 | ||
2530 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); | 2550 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); |
2531 | if (free_bytes < need_bytes) { | 2551 | if (free_bytes < need_bytes) { |
2552 | spin_lock(&log->l_grant_reserve_lock); | ||
2532 | if (list_empty(&tic->t_queue)) | 2553 | if (list_empty(&tic->t_queue)) |
2533 | list_add_tail(&tic->t_queue, &log->l_reserveq); | 2554 | list_add_tail(&tic->t_queue, &log->l_reserveq); |
2534 | 2555 | ||
2535 | trace_xfs_log_grant_sleep2(log, tic); | 2556 | trace_xfs_log_grant_sleep2(log, tic); |
2536 | 2557 | ||
2558 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
2559 | goto error_return; | ||
2560 | |||
2537 | xlog_grant_push_ail(log, need_bytes); | 2561 | xlog_grant_push_ail(log, need_bytes); |
2538 | 2562 | ||
2539 | XFS_STATS_INC(xs_sleep_logspace); | 2563 | XFS_STATS_INC(xs_sleep_logspace); |
2540 | xlog_wait(&tic->t_wait, &log->l_grant_lock); | 2564 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); |
2541 | |||
2542 | spin_lock(&log->l_grant_lock); | ||
2543 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
2544 | goto error_return; | ||
2545 | 2565 | ||
2546 | trace_xfs_log_grant_wake2(log, tic); | 2566 | trace_xfs_log_grant_wake2(log, tic); |
2547 | |||
2548 | goto redo; | 2567 | goto redo; |
2549 | } | 2568 | } |
2550 | 2569 | ||
2551 | list_del_init(&tic->t_queue); | 2570 | if (!list_empty(&tic->t_queue)) { |
2571 | spin_lock(&log->l_grant_reserve_lock); | ||
2572 | list_del_init(&tic->t_queue); | ||
2573 | spin_unlock(&log->l_grant_reserve_lock); | ||
2574 | } | ||
2552 | 2575 | ||
2553 | /* we've got enough space */ | 2576 | /* we've got enough space */ |
2577 | spin_lock(&log->l_grant_lock); | ||
2554 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); | 2578 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); |
2555 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | 2579 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); |
2556 | trace_xfs_log_grant_exit(log, tic); | 2580 | trace_xfs_log_grant_exit(log, tic); |
@@ -2559,8 +2583,11 @@ redo: | |||
2559 | spin_unlock(&log->l_grant_lock); | 2583 | spin_unlock(&log->l_grant_lock); |
2560 | return 0; | 2584 | return 0; |
2561 | 2585 | ||
2562 | error_return: | 2586 | error_return_unlocked: |
2587 | spin_lock(&log->l_grant_reserve_lock); | ||
2588 | error_return: | ||
2563 | list_del_init(&tic->t_queue); | 2589 | list_del_init(&tic->t_queue); |
2590 | spin_unlock(&log->l_grant_reserve_lock); | ||
2564 | trace_xfs_log_grant_error(log, tic); | 2591 | trace_xfs_log_grant_error(log, tic); |
2565 | 2592 | ||
2566 | /* | 2593 | /* |
@@ -2570,7 +2597,6 @@ redo: | |||
2570 | */ | 2597 | */ |
2571 | tic->t_curr_res = 0; | 2598 | tic->t_curr_res = 0; |
2572 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ | 2599 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ |
2573 | spin_unlock(&log->l_grant_lock); | ||
2574 | return XFS_ERROR(EIO); | 2600 | return XFS_ERROR(EIO); |
2575 | } /* xlog_grant_log_space */ | 2601 | } /* xlog_grant_log_space */ |
2576 | 2602 | ||
@@ -2578,7 +2604,8 @@ redo: | |||
2578 | /* | 2604 | /* |
2579 | * Replenish the byte reservation required by moving the grant write head. | 2605 | * Replenish the byte reservation required by moving the grant write head. |
2580 | * | 2606 | * |
2581 | * | 2607 | * Similar to xlog_grant_log_space, the function is structured to have a lock |
2608 | * free fast path. | ||
2582 | */ | 2609 | */ |
2583 | STATIC int | 2610 | STATIC int |
2584 | xlog_regrant_write_log_space(xlog_t *log, | 2611 | xlog_regrant_write_log_space(xlog_t *log, |
@@ -2597,12 +2624,9 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2597 | panic("regrant Recovery problem"); | 2624 | panic("regrant Recovery problem"); |
2598 | #endif | 2625 | #endif |
2599 | 2626 | ||
2600 | spin_lock(&log->l_grant_lock); | ||
2601 | |||
2602 | trace_xfs_log_regrant_write_enter(log, tic); | 2627 | trace_xfs_log_regrant_write_enter(log, tic); |
2603 | |||
2604 | if (XLOG_FORCED_SHUTDOWN(log)) | 2628 | if (XLOG_FORCED_SHUTDOWN(log)) |
2605 | goto error_return; | 2629 | goto error_return_unlocked; |
2606 | 2630 | ||
2607 | /* If there are other waiters on the queue then give them a | 2631 | /* If there are other waiters on the queue then give them a |
2608 | * chance at logspace before us. Wake up the first waiters, | 2632 | * chance at logspace before us. Wake up the first waiters, |
@@ -2611,8 +2635,10 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2611 | * this transaction. | 2635 | * this transaction. |
2612 | */ | 2636 | */ |
2613 | need_bytes = tic->t_unit_res; | 2637 | need_bytes = tic->t_unit_res; |
2614 | if (!list_empty(&log->l_writeq)) { | 2638 | if (!list_empty_careful(&log->l_writeq)) { |
2615 | struct xlog_ticket *ntic; | 2639 | struct xlog_ticket *ntic; |
2640 | |||
2641 | spin_lock(&log->l_grant_write_lock); | ||
2616 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); | 2642 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); |
2617 | list_for_each_entry(ntic, &log->l_writeq, t_queue) { | 2643 | list_for_each_entry(ntic, &log->l_writeq, t_queue) { |
2618 | ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV); | 2644 | ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV); |
@@ -2627,50 +2653,48 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2627 | struct xlog_ticket, t_queue)) { | 2653 | struct xlog_ticket, t_queue)) { |
2628 | if (list_empty(&tic->t_queue)) | 2654 | if (list_empty(&tic->t_queue)) |
2629 | list_add_tail(&tic->t_queue, &log->l_writeq); | 2655 | list_add_tail(&tic->t_queue, &log->l_writeq); |
2630 | |||
2631 | trace_xfs_log_regrant_write_sleep1(log, tic); | 2656 | trace_xfs_log_regrant_write_sleep1(log, tic); |
2632 | 2657 | ||
2633 | xlog_grant_push_ail(log, need_bytes); | 2658 | xlog_grant_push_ail(log, need_bytes); |
2634 | 2659 | ||
2635 | XFS_STATS_INC(xs_sleep_logspace); | 2660 | XFS_STATS_INC(xs_sleep_logspace); |
2636 | xlog_wait(&tic->t_wait, &log->l_grant_lock); | 2661 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); |
2637 | |||
2638 | /* If we're shutting down, this tic is already | ||
2639 | * off the queue */ | ||
2640 | spin_lock(&log->l_grant_lock); | ||
2641 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
2642 | goto error_return; | ||
2643 | |||
2644 | trace_xfs_log_regrant_write_wake1(log, tic); | 2662 | trace_xfs_log_regrant_write_wake1(log, tic); |
2645 | } | 2663 | } else |
2664 | spin_unlock(&log->l_grant_write_lock); | ||
2646 | } | 2665 | } |
2647 | 2666 | ||
2648 | redo: | 2667 | redo: |
2649 | if (XLOG_FORCED_SHUTDOWN(log)) | 2668 | if (XLOG_FORCED_SHUTDOWN(log)) |
2650 | goto error_return; | 2669 | goto error_return_unlocked; |
2651 | 2670 | ||
2652 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); | 2671 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); |
2653 | if (free_bytes < need_bytes) { | 2672 | if (free_bytes < need_bytes) { |
2673 | spin_lock(&log->l_grant_write_lock); | ||
2654 | if (list_empty(&tic->t_queue)) | 2674 | if (list_empty(&tic->t_queue)) |
2655 | list_add_tail(&tic->t_queue, &log->l_writeq); | 2675 | list_add_tail(&tic->t_queue, &log->l_writeq); |
2676 | |||
2677 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
2678 | goto error_return; | ||
2679 | |||
2656 | xlog_grant_push_ail(log, need_bytes); | 2680 | xlog_grant_push_ail(log, need_bytes); |
2657 | 2681 | ||
2658 | XFS_STATS_INC(xs_sleep_logspace); | 2682 | XFS_STATS_INC(xs_sleep_logspace); |
2659 | trace_xfs_log_regrant_write_sleep2(log, tic); | 2683 | trace_xfs_log_regrant_write_sleep2(log, tic); |
2660 | xlog_wait(&tic->t_wait, &log->l_grant_lock); | 2684 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); |
2661 | |||
2662 | /* If we're shutting down, this tic is already off the queue */ | ||
2663 | spin_lock(&log->l_grant_lock); | ||
2664 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
2665 | goto error_return; | ||
2666 | 2685 | ||
2667 | trace_xfs_log_regrant_write_wake2(log, tic); | 2686 | trace_xfs_log_regrant_write_wake2(log, tic); |
2668 | goto redo; | 2687 | goto redo; |
2669 | } | 2688 | } |
2670 | 2689 | ||
2671 | list_del_init(&tic->t_queue); | 2690 | if (!list_empty(&tic->t_queue)) { |
2691 | spin_lock(&log->l_grant_write_lock); | ||
2692 | list_del_init(&tic->t_queue); | ||
2693 | spin_unlock(&log->l_grant_write_lock); | ||
2694 | } | ||
2672 | 2695 | ||
2673 | /* we've got enough space */ | 2696 | /* we've got enough space */ |
2697 | spin_lock(&log->l_grant_lock); | ||
2674 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | 2698 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); |
2675 | trace_xfs_log_regrant_write_exit(log, tic); | 2699 | trace_xfs_log_regrant_write_exit(log, tic); |
2676 | xlog_verify_grant_head(log, 1); | 2700 | xlog_verify_grant_head(log, 1); |
@@ -2679,8 +2703,11 @@ redo: | |||
2679 | return 0; | 2703 | return 0; |
2680 | 2704 | ||
2681 | 2705 | ||
2706 | error_return_unlocked: | ||
2707 | spin_lock(&log->l_grant_write_lock); | ||
2682 | error_return: | 2708 | error_return: |
2683 | list_del_init(&tic->t_queue); | 2709 | list_del_init(&tic->t_queue); |
2710 | spin_unlock(&log->l_grant_write_lock); | ||
2684 | trace_xfs_log_regrant_write_error(log, tic); | 2711 | trace_xfs_log_regrant_write_error(log, tic); |
2685 | 2712 | ||
2686 | /* | 2713 | /* |
@@ -2690,7 +2717,6 @@ redo: | |||
2690 | */ | 2717 | */ |
2691 | tic->t_curr_res = 0; | 2718 | tic->t_curr_res = 0; |
2692 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ | 2719 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ |
2693 | spin_unlock(&log->l_grant_lock); | ||
2694 | return XFS_ERROR(EIO); | 2720 | return XFS_ERROR(EIO); |
2695 | } /* xlog_regrant_write_log_space */ | 2721 | } /* xlog_regrant_write_log_space */ |
2696 | 2722 | ||
@@ -3664,12 +3690,10 @@ xfs_log_force_umount( | |||
3664 | xlog_cil_force(log); | 3690 | xlog_cil_force(log); |
3665 | 3691 | ||
3666 | /* | 3692 | /* |
3667 | * We must hold both the GRANT lock and the LOG lock, | 3693 | * mark the filesystem and the as in a shutdown state and wake |
3668 | * before we mark the filesystem SHUTDOWN and wake | 3694 | * everybody up to tell them the bad news. |
3669 | * everybody up to tell the bad news. | ||
3670 | */ | 3695 | */ |
3671 | spin_lock(&log->l_icloglock); | 3696 | spin_lock(&log->l_icloglock); |
3672 | spin_lock(&log->l_grant_lock); | ||
3673 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; | 3697 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; |
3674 | if (mp->m_sb_bp) | 3698 | if (mp->m_sb_bp) |
3675 | XFS_BUF_DONE(mp->m_sb_bp); | 3699 | XFS_BUF_DONE(mp->m_sb_bp); |
@@ -3694,14 +3718,17 @@ xfs_log_force_umount( | |||
3694 | * means we have to wake up everybody queued up on reserveq as well as | 3718 | * means we have to wake up everybody queued up on reserveq as well as |
3695 | * writeq. In addition, we make sure in xlog_{re}grant_log_space that | 3719 | * writeq. In addition, we make sure in xlog_{re}grant_log_space that |
3696 | * we don't enqueue anything once the SHUTDOWN flag is set, and this | 3720 | * we don't enqueue anything once the SHUTDOWN flag is set, and this |
3697 | * action is protected by the GRANTLOCK. | 3721 | * action is protected by the grant locks. |
3698 | */ | 3722 | */ |
3723 | spin_lock(&log->l_grant_reserve_lock); | ||
3699 | list_for_each_entry(tic, &log->l_reserveq, t_queue) | 3724 | list_for_each_entry(tic, &log->l_reserveq, t_queue) |
3700 | wake_up(&tic->t_wait); | 3725 | wake_up(&tic->t_wait); |
3726 | spin_unlock(&log->l_grant_reserve_lock); | ||
3701 | 3727 | ||
3728 | spin_lock(&log->l_grant_write_lock); | ||
3702 | list_for_each_entry(tic, &log->l_writeq, t_queue) | 3729 | list_for_each_entry(tic, &log->l_writeq, t_queue) |
3703 | wake_up(&tic->t_wait); | 3730 | wake_up(&tic->t_wait); |
3704 | spin_unlock(&log->l_grant_lock); | 3731 | spin_unlock(&log->l_grant_write_lock); |
3705 | 3732 | ||
3706 | if (!(log->l_iclog->ic_state & XLOG_STATE_IOERROR)) { | 3733 | if (!(log->l_iclog->ic_state & XLOG_STATE_IOERROR)) { |
3707 | ASSERT(!logerror); | 3734 | ASSERT(!logerror); |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 7619d6a02388..befb2fc5b027 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -512,10 +512,6 @@ typedef struct log { | |||
512 | 512 | ||
513 | /* The following block of fields are changed while holding grant_lock */ | 513 | /* The following block of fields are changed while holding grant_lock */ |
514 | spinlock_t l_grant_lock ____cacheline_aligned_in_smp; | 514 | spinlock_t l_grant_lock ____cacheline_aligned_in_smp; |
515 | struct list_head l_reserveq; | ||
516 | struct list_head l_writeq; | ||
517 | atomic64_t l_grant_reserve_head; | ||
518 | atomic64_t l_grant_write_head; | ||
519 | 515 | ||
520 | /* | 516 | /* |
521 | * l_last_sync_lsn and l_tail_lsn are atomics so they can be set and | 517 | * l_last_sync_lsn and l_tail_lsn are atomics so they can be set and |
@@ -528,6 +524,18 @@ typedef struct log { | |||
528 | /* lsn of 1st LR with unflushed * buffers */ | 524 | /* lsn of 1st LR with unflushed * buffers */ |
529 | atomic64_t l_tail_lsn ____cacheline_aligned_in_smp; | 525 | atomic64_t l_tail_lsn ____cacheline_aligned_in_smp; |
530 | 526 | ||
527 | /* | ||
528 | * ticket grant locks, queues and accounting have their own cachlines | ||
529 | * as these are quite hot and can be operated on concurrently. | ||
530 | */ | ||
531 | spinlock_t l_grant_reserve_lock ____cacheline_aligned_in_smp; | ||
532 | struct list_head l_reserveq; | ||
533 | atomic64_t l_grant_reserve_head; | ||
534 | |||
535 | spinlock_t l_grant_write_lock ____cacheline_aligned_in_smp; | ||
536 | struct list_head l_writeq; | ||
537 | atomic64_t l_grant_write_head; | ||
538 | |||
531 | /* The following field are used for debugging; need to hold icloglock */ | 539 | /* The following field are used for debugging; need to hold icloglock */ |
532 | #ifdef DEBUG | 540 | #ifdef DEBUG |
533 | char *l_iclog_bak[XLOG_MAX_ICLOGS]; | 541 | char *l_iclog_bak[XLOG_MAX_ICLOGS]; |