diff options
-rw-r--r-- | fs/xfs/xfs_log.c | 103 | ||||
-rw-r--r-- | fs/xfs/xfs_log_priv.h | 23 |
2 files changed, 49 insertions, 77 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 6fcc9d0af524..0bf24b11d0c4 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -81,7 +81,6 @@ STATIC void xlog_ungrant_log_space(xlog_t *log, | |||
81 | 81 | ||
82 | #if defined(DEBUG) | 82 | #if defined(DEBUG) |
83 | STATIC void xlog_verify_dest_ptr(xlog_t *log, char *ptr); | 83 | STATIC void xlog_verify_dest_ptr(xlog_t *log, char *ptr); |
84 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); | ||
85 | STATIC void xlog_verify_grant_tail(struct log *log); | 84 | STATIC void xlog_verify_grant_tail(struct log *log); |
86 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, | 85 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, |
87 | int count, boolean_t syncing); | 86 | int count, boolean_t syncing); |
@@ -89,7 +88,6 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, | |||
89 | xfs_lsn_t tail_lsn); | 88 | xfs_lsn_t tail_lsn); |
90 | #else | 89 | #else |
91 | #define xlog_verify_dest_ptr(a,b) | 90 | #define xlog_verify_dest_ptr(a,b) |
92 | #define xlog_verify_grant_head(a,b) | ||
93 | #define xlog_verify_grant_tail(a) | 91 | #define xlog_verify_grant_tail(a) |
94 | #define xlog_verify_iclog(a,b,c,d) | 92 | #define xlog_verify_iclog(a,b,c,d) |
95 | #define xlog_verify_tail_lsn(a,b,c) | 93 | #define xlog_verify_tail_lsn(a,b,c) |
@@ -103,17 +101,24 @@ xlog_grant_sub_space( | |||
103 | atomic64_t *head, | 101 | atomic64_t *head, |
104 | int bytes) | 102 | int bytes) |
105 | { | 103 | { |
106 | int cycle, space; | 104 | int64_t head_val = atomic64_read(head); |
105 | int64_t new, old; | ||
107 | 106 | ||
108 | xlog_crack_grant_head(head, &cycle, &space); | 107 | do { |
108 | int cycle, space; | ||
109 | 109 | ||
110 | space -= bytes; | 110 | xlog_crack_grant_head_val(head_val, &cycle, &space); |
111 | if (space < 0) { | ||
112 | space += log->l_logsize; | ||
113 | cycle--; | ||
114 | } | ||
115 | 111 | ||
116 | xlog_assign_grant_head(head, cycle, space); | 112 | space -= bytes; |
113 | if (space < 0) { | ||
114 | space += log->l_logsize; | ||
115 | cycle--; | ||
116 | } | ||
117 | |||
118 | old = head_val; | ||
119 | new = xlog_assign_grant_head_val(cycle, space); | ||
120 | head_val = atomic64_cmpxchg(head, old, new); | ||
121 | } while (head_val != old); | ||
117 | } | 122 | } |
118 | 123 | ||
119 | static void | 124 | static void |
@@ -122,20 +127,27 @@ xlog_grant_add_space( | |||
122 | atomic64_t *head, | 127 | atomic64_t *head, |
123 | int bytes) | 128 | int bytes) |
124 | { | 129 | { |
125 | int tmp; | 130 | int64_t head_val = atomic64_read(head); |
126 | int cycle, space; | 131 | int64_t new, old; |
127 | 132 | ||
128 | xlog_crack_grant_head(head, &cycle, &space); | 133 | do { |
134 | int tmp; | ||
135 | int cycle, space; | ||
129 | 136 | ||
130 | tmp = log->l_logsize - space; | 137 | xlog_crack_grant_head_val(head_val, &cycle, &space); |
131 | if (tmp > bytes) | ||
132 | space += bytes; | ||
133 | else { | ||
134 | space = bytes - tmp; | ||
135 | cycle++; | ||
136 | } | ||
137 | 138 | ||
138 | xlog_assign_grant_head(head, cycle, space); | 139 | tmp = log->l_logsize - space; |
140 | if (tmp > bytes) | ||
141 | space += bytes; | ||
142 | else { | ||
143 | space = bytes - tmp; | ||
144 | cycle++; | ||
145 | } | ||
146 | |||
147 | old = head_val; | ||
148 | new = xlog_assign_grant_head_val(cycle, space); | ||
149 | head_val = atomic64_cmpxchg(head, old, new); | ||
150 | } while (head_val != old); | ||
139 | } | 151 | } |
140 | 152 | ||
141 | static void | 153 | static void |
@@ -318,9 +330,7 @@ xfs_log_reserve( | |||
318 | 330 | ||
319 | trace_xfs_log_reserve(log, internal_ticket); | 331 | trace_xfs_log_reserve(log, internal_ticket); |
320 | 332 | ||
321 | spin_lock(&log->l_grant_lock); | ||
322 | xlog_grant_push_ail(log, internal_ticket->t_unit_res); | 333 | xlog_grant_push_ail(log, internal_ticket->t_unit_res); |
323 | spin_unlock(&log->l_grant_lock); | ||
324 | retval = xlog_regrant_write_log_space(log, internal_ticket); | 334 | retval = xlog_regrant_write_log_space(log, internal_ticket); |
325 | } else { | 335 | } else { |
326 | /* may sleep if need to allocate more tickets */ | 336 | /* may sleep if need to allocate more tickets */ |
@@ -334,11 +344,9 @@ xfs_log_reserve( | |||
334 | 344 | ||
335 | trace_xfs_log_reserve(log, internal_ticket); | 345 | trace_xfs_log_reserve(log, internal_ticket); |
336 | 346 | ||
337 | spin_lock(&log->l_grant_lock); | ||
338 | xlog_grant_push_ail(log, | 347 | xlog_grant_push_ail(log, |
339 | (internal_ticket->t_unit_res * | 348 | (internal_ticket->t_unit_res * |
340 | internal_ticket->t_cnt)); | 349 | internal_ticket->t_cnt)); |
341 | spin_unlock(&log->l_grant_lock); | ||
342 | retval = xlog_grant_log_space(log, internal_ticket); | 350 | retval = xlog_grant_log_space(log, internal_ticket); |
343 | } | 351 | } |
344 | 352 | ||
@@ -1057,7 +1065,6 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1057 | log->l_xbuf = bp; | 1065 | log->l_xbuf = bp; |
1058 | 1066 | ||
1059 | spin_lock_init(&log->l_icloglock); | 1067 | spin_lock_init(&log->l_icloglock); |
1060 | spin_lock_init(&log->l_grant_lock); | ||
1061 | init_waitqueue_head(&log->l_flush_wait); | 1068 | init_waitqueue_head(&log->l_flush_wait); |
1062 | 1069 | ||
1063 | /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ | 1070 | /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ |
@@ -1135,7 +1142,6 @@ out_free_iclog: | |||
1135 | kmem_free(iclog); | 1142 | kmem_free(iclog); |
1136 | } | 1143 | } |
1137 | spinlock_destroy(&log->l_icloglock); | 1144 | spinlock_destroy(&log->l_icloglock); |
1138 | spinlock_destroy(&log->l_grant_lock); | ||
1139 | xfs_buf_free(log->l_xbuf); | 1145 | xfs_buf_free(log->l_xbuf); |
1140 | out_free_log: | 1146 | out_free_log: |
1141 | kmem_free(log); | 1147 | kmem_free(log); |
@@ -1331,10 +1337,8 @@ xlog_sync(xlog_t *log, | |||
1331 | roundoff < BBTOB(1))); | 1337 | roundoff < BBTOB(1))); |
1332 | 1338 | ||
1333 | /* move grant heads by roundoff in sync */ | 1339 | /* move grant heads by roundoff in sync */ |
1334 | spin_lock(&log->l_grant_lock); | ||
1335 | xlog_grant_add_space(log, &log->l_grant_reserve_head, roundoff); | 1340 | xlog_grant_add_space(log, &log->l_grant_reserve_head, roundoff); |
1336 | xlog_grant_add_space(log, &log->l_grant_write_head, roundoff); | 1341 | xlog_grant_add_space(log, &log->l_grant_write_head, roundoff); |
1337 | spin_unlock(&log->l_grant_lock); | ||
1338 | 1342 | ||
1339 | /* put cycle number in every block */ | 1343 | /* put cycle number in every block */ |
1340 | xlog_pack_data(log, iclog, roundoff); | 1344 | xlog_pack_data(log, iclog, roundoff); |
@@ -1455,7 +1459,6 @@ xlog_dealloc_log(xlog_t *log) | |||
1455 | iclog = next_iclog; | 1459 | iclog = next_iclog; |
1456 | } | 1460 | } |
1457 | spinlock_destroy(&log->l_icloglock); | 1461 | spinlock_destroy(&log->l_icloglock); |
1458 | spinlock_destroy(&log->l_grant_lock); | ||
1459 | 1462 | ||
1460 | xfs_buf_free(log->l_xbuf); | 1463 | xfs_buf_free(log->l_xbuf); |
1461 | log->l_mp->m_log = NULL; | 1464 | log->l_mp->m_log = NULL; |
@@ -2574,13 +2577,10 @@ redo: | |||
2574 | } | 2577 | } |
2575 | 2578 | ||
2576 | /* we've got enough space */ | 2579 | /* we've got enough space */ |
2577 | spin_lock(&log->l_grant_lock); | ||
2578 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); | 2580 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); |
2579 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | 2581 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); |
2580 | trace_xfs_log_grant_exit(log, tic); | 2582 | trace_xfs_log_grant_exit(log, tic); |
2581 | xlog_verify_grant_head(log, 1); | ||
2582 | xlog_verify_grant_tail(log); | 2583 | xlog_verify_grant_tail(log); |
2583 | spin_unlock(&log->l_grant_lock); | ||
2584 | return 0; | 2584 | return 0; |
2585 | 2585 | ||
2586 | error_return_unlocked: | 2586 | error_return_unlocked: |
@@ -2694,12 +2694,9 @@ redo: | |||
2694 | } | 2694 | } |
2695 | 2695 | ||
2696 | /* we've got enough space */ | 2696 | /* we've got enough space */ |
2697 | spin_lock(&log->l_grant_lock); | ||
2698 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | 2697 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); |
2699 | trace_xfs_log_regrant_write_exit(log, tic); | 2698 | trace_xfs_log_regrant_write_exit(log, tic); |
2700 | xlog_verify_grant_head(log, 1); | ||
2701 | xlog_verify_grant_tail(log); | 2699 | xlog_verify_grant_tail(log); |
2702 | spin_unlock(&log->l_grant_lock); | ||
2703 | return 0; | 2700 | return 0; |
2704 | 2701 | ||
2705 | 2702 | ||
@@ -2737,7 +2734,6 @@ xlog_regrant_reserve_log_space(xlog_t *log, | |||
2737 | if (ticket->t_cnt > 0) | 2734 | if (ticket->t_cnt > 0) |
2738 | ticket->t_cnt--; | 2735 | ticket->t_cnt--; |
2739 | 2736 | ||
2740 | spin_lock(&log->l_grant_lock); | ||
2741 | xlog_grant_sub_space(log, &log->l_grant_reserve_head, | 2737 | xlog_grant_sub_space(log, &log->l_grant_reserve_head, |
2742 | ticket->t_curr_res); | 2738 | ticket->t_curr_res); |
2743 | xlog_grant_sub_space(log, &log->l_grant_write_head, | 2739 | xlog_grant_sub_space(log, &log->l_grant_write_head, |
@@ -2747,21 +2743,15 @@ xlog_regrant_reserve_log_space(xlog_t *log, | |||
2747 | 2743 | ||
2748 | trace_xfs_log_regrant_reserve_sub(log, ticket); | 2744 | trace_xfs_log_regrant_reserve_sub(log, ticket); |
2749 | 2745 | ||
2750 | xlog_verify_grant_head(log, 1); | ||
2751 | |||
2752 | /* just return if we still have some of the pre-reserved space */ | 2746 | /* just return if we still have some of the pre-reserved space */ |
2753 | if (ticket->t_cnt > 0) { | 2747 | if (ticket->t_cnt > 0) |
2754 | spin_unlock(&log->l_grant_lock); | ||
2755 | return; | 2748 | return; |
2756 | } | ||
2757 | 2749 | ||
2758 | xlog_grant_add_space(log, &log->l_grant_reserve_head, | 2750 | xlog_grant_add_space(log, &log->l_grant_reserve_head, |
2759 | ticket->t_unit_res); | 2751 | ticket->t_unit_res); |
2760 | 2752 | ||
2761 | trace_xfs_log_regrant_reserve_exit(log, ticket); | 2753 | trace_xfs_log_regrant_reserve_exit(log, ticket); |
2762 | 2754 | ||
2763 | xlog_verify_grant_head(log, 0); | ||
2764 | spin_unlock(&log->l_grant_lock); | ||
2765 | ticket->t_curr_res = ticket->t_unit_res; | 2755 | ticket->t_curr_res = ticket->t_unit_res; |
2766 | xlog_tic_reset_res(ticket); | 2756 | xlog_tic_reset_res(ticket); |
2767 | } /* xlog_regrant_reserve_log_space */ | 2757 | } /* xlog_regrant_reserve_log_space */ |
@@ -2790,7 +2780,6 @@ xlog_ungrant_log_space(xlog_t *log, | |||
2790 | if (ticket->t_cnt > 0) | 2780 | if (ticket->t_cnt > 0) |
2791 | ticket->t_cnt--; | 2781 | ticket->t_cnt--; |
2792 | 2782 | ||
2793 | spin_lock(&log->l_grant_lock); | ||
2794 | trace_xfs_log_ungrant_enter(log, ticket); | 2783 | trace_xfs_log_ungrant_enter(log, ticket); |
2795 | trace_xfs_log_ungrant_sub(log, ticket); | 2784 | trace_xfs_log_ungrant_sub(log, ticket); |
2796 | 2785 | ||
@@ -2809,8 +2798,6 @@ xlog_ungrant_log_space(xlog_t *log, | |||
2809 | 2798 | ||
2810 | trace_xfs_log_ungrant_exit(log, ticket); | 2799 | trace_xfs_log_ungrant_exit(log, ticket); |
2811 | 2800 | ||
2812 | xlog_verify_grant_head(log, 1); | ||
2813 | spin_unlock(&log->l_grant_lock); | ||
2814 | xfs_log_move_tail(log->l_mp, 1); | 2801 | xfs_log_move_tail(log->l_mp, 1); |
2815 | } /* xlog_ungrant_log_space */ | 2802 | } /* xlog_ungrant_log_space */ |
2816 | 2803 | ||
@@ -3429,28 +3416,6 @@ xlog_verify_dest_ptr( | |||
3429 | } | 3416 | } |
3430 | 3417 | ||
3431 | STATIC void | 3418 | STATIC void |
3432 | xlog_verify_grant_head(xlog_t *log, int equals) | ||
3433 | { | ||
3434 | int reserve_cycle, reserve_space; | ||
3435 | int write_cycle, write_space; | ||
3436 | |||
3437 | xlog_crack_grant_head(&log->l_grant_reserve_head, | ||
3438 | &reserve_cycle, &reserve_space); | ||
3439 | xlog_crack_grant_head(&log->l_grant_write_head, | ||
3440 | &write_cycle, &write_space); | ||
3441 | |||
3442 | if (reserve_cycle == write_cycle) { | ||
3443 | if (equals) | ||
3444 | ASSERT(reserve_space >= write_space); | ||
3445 | else | ||
3446 | ASSERT(reserve_space > write_space); | ||
3447 | } else { | ||
3448 | ASSERT(reserve_cycle - 1 == write_cycle); | ||
3449 | ASSERT(write_space >= reserve_space); | ||
3450 | } | ||
3451 | } | ||
3452 | |||
3453 | STATIC void | ||
3454 | xlog_verify_grant_tail( | 3419 | xlog_verify_grant_tail( |
3455 | struct log *log) | 3420 | struct log *log) |
3456 | { | 3421 | { |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index befb2fc5b027..d5f8be8f4bf6 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -510,9 +510,6 @@ typedef struct log { | |||
510 | int l_curr_block; /* current logical log block */ | 510 | int l_curr_block; /* current logical log block */ |
511 | int l_prev_block; /* previous logical log block */ | 511 | int l_prev_block; /* previous logical log block */ |
512 | 512 | ||
513 | /* The following block of fields are changed while holding grant_lock */ | ||
514 | spinlock_t l_grant_lock ____cacheline_aligned_in_smp; | ||
515 | |||
516 | /* | 513 | /* |
517 | * l_last_sync_lsn and l_tail_lsn are atomics so they can be set and | 514 | * l_last_sync_lsn and l_tail_lsn are atomics so they can be set and |
518 | * read without needing to hold specific locks. To avoid operations | 515 | * read without needing to hold specific locks. To avoid operations |
@@ -599,23 +596,33 @@ xlog_assign_atomic_lsn(atomic64_t *lsn, uint cycle, uint block) | |||
599 | } | 596 | } |
600 | 597 | ||
601 | /* | 598 | /* |
602 | * When we crack the grrant head, we sample it first so that the value will not | 599 | * When we crack the grant head, we sample it first so that the value will not |
603 | * change while we are cracking it into the component values. This means we | 600 | * change while we are cracking it into the component values. This means we |
604 | * will always get consistent component values to work from. | 601 | * will always get consistent component values to work from. |
605 | */ | 602 | */ |
606 | static inline void | 603 | static inline void |
607 | xlog_crack_grant_head(atomic64_t *head, int *cycle, int *space) | 604 | xlog_crack_grant_head_val(int64_t val, int *cycle, int *space) |
608 | { | 605 | { |
609 | int64_t val = atomic64_read(head); | ||
610 | |||
611 | *cycle = val >> 32; | 606 | *cycle = val >> 32; |
612 | *space = val & 0xffffffff; | 607 | *space = val & 0xffffffff; |
613 | } | 608 | } |
614 | 609 | ||
615 | static inline void | 610 | static inline void |
611 | xlog_crack_grant_head(atomic64_t *head, int *cycle, int *space) | ||
612 | { | ||
613 | xlog_crack_grant_head_val(atomic64_read(head), cycle, space); | ||
614 | } | ||
615 | |||
616 | static inline int64_t | ||
617 | xlog_assign_grant_head_val(int cycle, int space) | ||
618 | { | ||
619 | return ((int64_t)cycle << 32) | space; | ||
620 | } | ||
621 | |||
622 | static inline void | ||
616 | xlog_assign_grant_head(atomic64_t *head, int cycle, int space) | 623 | xlog_assign_grant_head(atomic64_t *head, int cycle, int space) |
617 | { | 624 | { |
618 | atomic64_set(head, ((int64_t)cycle << 32) | space); | 625 | atomic64_set(head, xlog_assign_grant_head_val(cycle, space)); |
619 | } | 626 | } |
620 | 627 | ||
621 | /* | 628 | /* |