diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-01-12 00:37:42 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-12 00:37:42 -0500 |
commit | 83eb95b852902f952ba594447a796ad8146b9462 (patch) | |
tree | 33c199aeeae58b69ad8d6d2a33c2d96ba2b98ddf /fs/xfs/xfs_log.c | |
parent | efb3e34b6176d30c4fe8635fa8e1beb6280cc2cd (diff) | |
parent | 9bbe7b984096ac45586da2adf26c14069ecb79b2 (diff) |
Merge branch 'sh/sdio' into sh-latest
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r-- | fs/xfs/xfs_log.c | 739 |
1 files changed, 335 insertions, 404 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index cee4ab9f8a9e..0bf24b11d0c4 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -47,7 +47,7 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, | |||
47 | xfs_buftarg_t *log_target, | 47 | xfs_buftarg_t *log_target, |
48 | xfs_daddr_t blk_offset, | 48 | xfs_daddr_t blk_offset, |
49 | int num_bblks); | 49 | int num_bblks); |
50 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); | 50 | STATIC int xlog_space_left(struct log *log, atomic64_t *head); |
51 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); | 51 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); |
52 | STATIC void xlog_dealloc_log(xlog_t *log); | 52 | STATIC void xlog_dealloc_log(xlog_t *log); |
53 | 53 | ||
@@ -70,7 +70,7 @@ STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog); | |||
70 | /* local functions to manipulate grant head */ | 70 | /* local functions to manipulate grant head */ |
71 | STATIC int xlog_grant_log_space(xlog_t *log, | 71 | STATIC int xlog_grant_log_space(xlog_t *log, |
72 | xlog_ticket_t *xtic); | 72 | xlog_ticket_t *xtic); |
73 | STATIC void xlog_grant_push_ail(xfs_mount_t *mp, | 73 | STATIC void xlog_grant_push_ail(struct log *log, |
74 | int need_bytes); | 74 | int need_bytes); |
75 | STATIC void xlog_regrant_reserve_log_space(xlog_t *log, | 75 | STATIC void xlog_regrant_reserve_log_space(xlog_t *log, |
76 | xlog_ticket_t *ticket); | 76 | xlog_ticket_t *ticket); |
@@ -81,98 +81,73 @@ 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); | 84 | STATIC void xlog_verify_grant_tail(struct log *log); |
85 | 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, |
86 | int count, boolean_t syncing); | 86 | int count, boolean_t syncing); |
87 | STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, | 87 | STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, |
88 | xfs_lsn_t tail_lsn); | 88 | xfs_lsn_t tail_lsn); |
89 | #else | 89 | #else |
90 | #define xlog_verify_dest_ptr(a,b) | 90 | #define xlog_verify_dest_ptr(a,b) |
91 | #define xlog_verify_grant_head(a,b) | 91 | #define xlog_verify_grant_tail(a) |
92 | #define xlog_verify_iclog(a,b,c,d) | 92 | #define xlog_verify_iclog(a,b,c,d) |
93 | #define xlog_verify_tail_lsn(a,b,c) | 93 | #define xlog_verify_tail_lsn(a,b,c) |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | STATIC int xlog_iclogs_empty(xlog_t *log); | 96 | STATIC int xlog_iclogs_empty(xlog_t *log); |
97 | 97 | ||
98 | |||
99 | static void | 98 | static void |
100 | xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic) | 99 | xlog_grant_sub_space( |
100 | struct log *log, | ||
101 | atomic64_t *head, | ||
102 | int bytes) | ||
101 | { | 103 | { |
102 | if (*qp) { | 104 | int64_t head_val = atomic64_read(head); |
103 | tic->t_next = (*qp); | 105 | int64_t new, old; |
104 | tic->t_prev = (*qp)->t_prev; | ||
105 | (*qp)->t_prev->t_next = tic; | ||
106 | (*qp)->t_prev = tic; | ||
107 | } else { | ||
108 | tic->t_prev = tic->t_next = tic; | ||
109 | *qp = tic; | ||
110 | } | ||
111 | 106 | ||
112 | tic->t_flags |= XLOG_TIC_IN_Q; | 107 | do { |
113 | } | 108 | int cycle, space; |
114 | 109 | ||
115 | static void | 110 | xlog_crack_grant_head_val(head_val, &cycle, &space); |
116 | xlog_del_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic) | ||
117 | { | ||
118 | if (tic == tic->t_next) { | ||
119 | *qp = NULL; | ||
120 | } else { | ||
121 | *qp = tic->t_next; | ||
122 | tic->t_next->t_prev = tic->t_prev; | ||
123 | tic->t_prev->t_next = tic->t_next; | ||
124 | } | ||
125 | 111 | ||
126 | tic->t_next = tic->t_prev = NULL; | 112 | space -= bytes; |
127 | tic->t_flags &= ~XLOG_TIC_IN_Q; | 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); | ||
128 | } | 122 | } |
129 | 123 | ||
130 | static void | 124 | static void |
131 | xlog_grant_sub_space(struct log *log, int bytes) | 125 | xlog_grant_add_space( |
126 | struct log *log, | ||
127 | atomic64_t *head, | ||
128 | int bytes) | ||
132 | { | 129 | { |
133 | log->l_grant_write_bytes -= bytes; | 130 | int64_t head_val = atomic64_read(head); |
134 | if (log->l_grant_write_bytes < 0) { | 131 | int64_t new, old; |
135 | log->l_grant_write_bytes += log->l_logsize; | ||
136 | log->l_grant_write_cycle--; | ||
137 | } | ||
138 | |||
139 | log->l_grant_reserve_bytes -= bytes; | ||
140 | if ((log)->l_grant_reserve_bytes < 0) { | ||
141 | log->l_grant_reserve_bytes += log->l_logsize; | ||
142 | log->l_grant_reserve_cycle--; | ||
143 | } | ||
144 | 132 | ||
145 | } | 133 | do { |
134 | int tmp; | ||
135 | int cycle, space; | ||
146 | 136 | ||
147 | static void | 137 | xlog_crack_grant_head_val(head_val, &cycle, &space); |
148 | xlog_grant_add_space_write(struct log *log, int bytes) | ||
149 | { | ||
150 | int tmp = log->l_logsize - log->l_grant_write_bytes; | ||
151 | if (tmp > bytes) | ||
152 | log->l_grant_write_bytes += bytes; | ||
153 | else { | ||
154 | log->l_grant_write_cycle++; | ||
155 | log->l_grant_write_bytes = bytes - tmp; | ||
156 | } | ||
157 | } | ||
158 | 138 | ||
159 | static void | 139 | tmp = log->l_logsize - space; |
160 | xlog_grant_add_space_reserve(struct log *log, int bytes) | 140 | if (tmp > bytes) |
161 | { | 141 | space += bytes; |
162 | int tmp = log->l_logsize - log->l_grant_reserve_bytes; | 142 | else { |
163 | if (tmp > bytes) | 143 | space = bytes - tmp; |
164 | log->l_grant_reserve_bytes += bytes; | 144 | cycle++; |
165 | else { | 145 | } |
166 | log->l_grant_reserve_cycle++; | ||
167 | log->l_grant_reserve_bytes = bytes - tmp; | ||
168 | } | ||
169 | } | ||
170 | 146 | ||
171 | static inline void | 147 | old = head_val; |
172 | xlog_grant_add_space(struct log *log, int bytes) | 148 | new = xlog_assign_grant_head_val(cycle, space); |
173 | { | 149 | head_val = atomic64_cmpxchg(head, old, new); |
174 | xlog_grant_add_space_write(log, bytes); | 150 | } while (head_val != old); |
175 | xlog_grant_add_space_reserve(log, bytes); | ||
176 | } | 151 | } |
177 | 152 | ||
178 | static void | 153 | static void |
@@ -355,7 +330,7 @@ xfs_log_reserve( | |||
355 | 330 | ||
356 | trace_xfs_log_reserve(log, internal_ticket); | 331 | trace_xfs_log_reserve(log, internal_ticket); |
357 | 332 | ||
358 | xlog_grant_push_ail(mp, internal_ticket->t_unit_res); | 333 | xlog_grant_push_ail(log, internal_ticket->t_unit_res); |
359 | retval = xlog_regrant_write_log_space(log, internal_ticket); | 334 | retval = xlog_regrant_write_log_space(log, internal_ticket); |
360 | } else { | 335 | } else { |
361 | /* may sleep if need to allocate more tickets */ | 336 | /* may sleep if need to allocate more tickets */ |
@@ -369,7 +344,7 @@ xfs_log_reserve( | |||
369 | 344 | ||
370 | trace_xfs_log_reserve(log, internal_ticket); | 345 | trace_xfs_log_reserve(log, internal_ticket); |
371 | 346 | ||
372 | xlog_grant_push_ail(mp, | 347 | xlog_grant_push_ail(log, |
373 | (internal_ticket->t_unit_res * | 348 | (internal_ticket->t_unit_res * |
374 | internal_ticket->t_cnt)); | 349 | internal_ticket->t_cnt)); |
375 | retval = xlog_grant_log_space(log, internal_ticket); | 350 | retval = xlog_grant_log_space(log, internal_ticket); |
@@ -584,8 +559,8 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
584 | if (!(iclog->ic_state == XLOG_STATE_ACTIVE || | 559 | if (!(iclog->ic_state == XLOG_STATE_ACTIVE || |
585 | iclog->ic_state == XLOG_STATE_DIRTY)) { | 560 | iclog->ic_state == XLOG_STATE_DIRTY)) { |
586 | if (!XLOG_FORCED_SHUTDOWN(log)) { | 561 | if (!XLOG_FORCED_SHUTDOWN(log)) { |
587 | sv_wait(&iclog->ic_force_wait, PMEM, | 562 | xlog_wait(&iclog->ic_force_wait, |
588 | &log->l_icloglock, s); | 563 | &log->l_icloglock); |
589 | } else { | 564 | } else { |
590 | spin_unlock(&log->l_icloglock); | 565 | spin_unlock(&log->l_icloglock); |
591 | } | 566 | } |
@@ -625,8 +600,8 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
625 | || iclog->ic_state == XLOG_STATE_DIRTY | 600 | || iclog->ic_state == XLOG_STATE_DIRTY |
626 | || iclog->ic_state == XLOG_STATE_IOERROR) ) { | 601 | || iclog->ic_state == XLOG_STATE_IOERROR) ) { |
627 | 602 | ||
628 | sv_wait(&iclog->ic_force_wait, PMEM, | 603 | xlog_wait(&iclog->ic_force_wait, |
629 | &log->l_icloglock, s); | 604 | &log->l_icloglock); |
630 | } else { | 605 | } else { |
631 | spin_unlock(&log->l_icloglock); | 606 | spin_unlock(&log->l_icloglock); |
632 | } | 607 | } |
@@ -703,55 +678,46 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
703 | { | 678 | { |
704 | xlog_ticket_t *tic; | 679 | xlog_ticket_t *tic; |
705 | xlog_t *log = mp->m_log; | 680 | xlog_t *log = mp->m_log; |
706 | int need_bytes, free_bytes, cycle, bytes; | 681 | int need_bytes, free_bytes; |
707 | 682 | ||
708 | if (XLOG_FORCED_SHUTDOWN(log)) | 683 | if (XLOG_FORCED_SHUTDOWN(log)) |
709 | return; | 684 | return; |
710 | 685 | ||
711 | if (tail_lsn == 0) { | 686 | if (tail_lsn == 0) |
712 | /* needed since sync_lsn is 64 bits */ | 687 | tail_lsn = atomic64_read(&log->l_last_sync_lsn); |
713 | spin_lock(&log->l_icloglock); | ||
714 | tail_lsn = log->l_last_sync_lsn; | ||
715 | spin_unlock(&log->l_icloglock); | ||
716 | } | ||
717 | |||
718 | spin_lock(&log->l_grant_lock); | ||
719 | 688 | ||
720 | /* Also an invalid lsn. 1 implies that we aren't passing in a valid | 689 | /* tail_lsn == 1 implies that we weren't passed a valid value. */ |
721 | * tail_lsn. | 690 | if (tail_lsn != 1) |
722 | */ | 691 | atomic64_set(&log->l_tail_lsn, tail_lsn); |
723 | if (tail_lsn != 1) { | ||
724 | log->l_tail_lsn = tail_lsn; | ||
725 | } | ||
726 | 692 | ||
727 | if ((tic = log->l_write_headq)) { | 693 | if (!list_empty_careful(&log->l_writeq)) { |
728 | #ifdef DEBUG | 694 | #ifdef DEBUG |
729 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | 695 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) |
730 | panic("Recovery problem"); | 696 | panic("Recovery problem"); |
731 | #endif | 697 | #endif |
732 | cycle = log->l_grant_write_cycle; | 698 | spin_lock(&log->l_grant_write_lock); |
733 | bytes = log->l_grant_write_bytes; | 699 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); |
734 | free_bytes = xlog_space_left(log, cycle, bytes); | 700 | list_for_each_entry(tic, &log->l_writeq, t_queue) { |
735 | do { | ||
736 | ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); | 701 | ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); |
737 | 702 | ||
738 | if (free_bytes < tic->t_unit_res && tail_lsn != 1) | 703 | if (free_bytes < tic->t_unit_res && tail_lsn != 1) |
739 | break; | 704 | break; |
740 | tail_lsn = 0; | 705 | tail_lsn = 0; |
741 | free_bytes -= tic->t_unit_res; | 706 | free_bytes -= tic->t_unit_res; |
742 | sv_signal(&tic->t_wait); | 707 | trace_xfs_log_regrant_write_wake_up(log, tic); |
743 | tic = tic->t_next; | 708 | wake_up(&tic->t_wait); |
744 | } while (tic != log->l_write_headq); | 709 | } |
710 | spin_unlock(&log->l_grant_write_lock); | ||
745 | } | 711 | } |
746 | if ((tic = log->l_reserve_headq)) { | 712 | |
713 | if (!list_empty_careful(&log->l_reserveq)) { | ||
747 | #ifdef DEBUG | 714 | #ifdef DEBUG |
748 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | 715 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) |
749 | panic("Recovery problem"); | 716 | panic("Recovery problem"); |
750 | #endif | 717 | #endif |
751 | cycle = log->l_grant_reserve_cycle; | 718 | spin_lock(&log->l_grant_reserve_lock); |
752 | bytes = log->l_grant_reserve_bytes; | 719 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); |
753 | free_bytes = xlog_space_left(log, cycle, bytes); | 720 | list_for_each_entry(tic, &log->l_reserveq, t_queue) { |
754 | do { | ||
755 | if (tic->t_flags & XLOG_TIC_PERM_RESERV) | 721 | if (tic->t_flags & XLOG_TIC_PERM_RESERV) |
756 | need_bytes = tic->t_unit_res*tic->t_cnt; | 722 | need_bytes = tic->t_unit_res*tic->t_cnt; |
757 | else | 723 | else |
@@ -760,12 +726,12 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
760 | break; | 726 | break; |
761 | tail_lsn = 0; | 727 | tail_lsn = 0; |
762 | free_bytes -= need_bytes; | 728 | free_bytes -= need_bytes; |
763 | sv_signal(&tic->t_wait); | 729 | trace_xfs_log_grant_wake_up(log, tic); |
764 | tic = tic->t_next; | 730 | wake_up(&tic->t_wait); |
765 | } while (tic != log->l_reserve_headq); | 731 | } |
732 | spin_unlock(&log->l_grant_reserve_lock); | ||
766 | } | 733 | } |
767 | spin_unlock(&log->l_grant_lock); | 734 | } |
768 | } /* xfs_log_move_tail */ | ||
769 | 735 | ||
770 | /* | 736 | /* |
771 | * Determine if we have a transaction that has gone to disk | 737 | * Determine if we have a transaction that has gone to disk |
@@ -831,23 +797,19 @@ xfs_log_need_covered(xfs_mount_t *mp) | |||
831 | * We may be holding the log iclog lock upon entering this routine. | 797 | * We may be holding the log iclog lock upon entering this routine. |
832 | */ | 798 | */ |
833 | xfs_lsn_t | 799 | xfs_lsn_t |
834 | xlog_assign_tail_lsn(xfs_mount_t *mp) | 800 | xlog_assign_tail_lsn( |
801 | struct xfs_mount *mp) | ||
835 | { | 802 | { |
836 | xfs_lsn_t tail_lsn; | 803 | xfs_lsn_t tail_lsn; |
837 | xlog_t *log = mp->m_log; | 804 | struct log *log = mp->m_log; |
838 | 805 | ||
839 | tail_lsn = xfs_trans_ail_tail(mp->m_ail); | 806 | tail_lsn = xfs_trans_ail_tail(mp->m_ail); |
840 | spin_lock(&log->l_grant_lock); | 807 | if (!tail_lsn) |
841 | if (tail_lsn != 0) { | 808 | tail_lsn = atomic64_read(&log->l_last_sync_lsn); |
842 | log->l_tail_lsn = tail_lsn; | ||
843 | } else { | ||
844 | tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn; | ||
845 | } | ||
846 | spin_unlock(&log->l_grant_lock); | ||
847 | 809 | ||
810 | atomic64_set(&log->l_tail_lsn, tail_lsn); | ||
848 | return tail_lsn; | 811 | return tail_lsn; |
849 | } /* xlog_assign_tail_lsn */ | 812 | } |
850 | |||
851 | 813 | ||
852 | /* | 814 | /* |
853 | * Return the space in the log between the tail and the head. The head | 815 | * Return the space in the log between the tail and the head. The head |
@@ -864,21 +826,26 @@ xlog_assign_tail_lsn(xfs_mount_t *mp) | |||
864 | * result is that we return the size of the log as the amount of space left. | 826 | * result is that we return the size of the log as the amount of space left. |
865 | */ | 827 | */ |
866 | STATIC int | 828 | STATIC int |
867 | xlog_space_left(xlog_t *log, int cycle, int bytes) | 829 | xlog_space_left( |
868 | { | 830 | struct log *log, |
869 | int free_bytes; | 831 | atomic64_t *head) |
870 | int tail_bytes; | 832 | { |
871 | int tail_cycle; | 833 | int free_bytes; |
872 | 834 | int tail_bytes; | |
873 | tail_bytes = BBTOB(BLOCK_LSN(log->l_tail_lsn)); | 835 | int tail_cycle; |
874 | tail_cycle = CYCLE_LSN(log->l_tail_lsn); | 836 | int head_cycle; |
875 | if ((tail_cycle == cycle) && (bytes >= tail_bytes)) { | 837 | int head_bytes; |
876 | free_bytes = log->l_logsize - (bytes - tail_bytes); | 838 | |
877 | } else if ((tail_cycle + 1) < cycle) { | 839 | xlog_crack_grant_head(head, &head_cycle, &head_bytes); |
840 | xlog_crack_atomic_lsn(&log->l_tail_lsn, &tail_cycle, &tail_bytes); | ||
841 | tail_bytes = BBTOB(tail_bytes); | ||
842 | if (tail_cycle == head_cycle && head_bytes >= tail_bytes) | ||
843 | free_bytes = log->l_logsize - (head_bytes - tail_bytes); | ||
844 | else if (tail_cycle + 1 < head_cycle) | ||
878 | return 0; | 845 | return 0; |
879 | } else if (tail_cycle < cycle) { | 846 | else if (tail_cycle < head_cycle) { |
880 | ASSERT(tail_cycle == (cycle - 1)); | 847 | ASSERT(tail_cycle == (head_cycle - 1)); |
881 | free_bytes = tail_bytes - bytes; | 848 | free_bytes = tail_bytes - head_bytes; |
882 | } else { | 849 | } else { |
883 | /* | 850 | /* |
884 | * The reservation head is behind the tail. | 851 | * The reservation head is behind the tail. |
@@ -889,12 +856,12 @@ xlog_space_left(xlog_t *log, int cycle, int bytes) | |||
889 | "xlog_space_left: head behind tail\n" | 856 | "xlog_space_left: head behind tail\n" |
890 | " tail_cycle = %d, tail_bytes = %d\n" | 857 | " tail_cycle = %d, tail_bytes = %d\n" |
891 | " GH cycle = %d, GH bytes = %d", | 858 | " GH cycle = %d, GH bytes = %d", |
892 | tail_cycle, tail_bytes, cycle, bytes); | 859 | tail_cycle, tail_bytes, head_cycle, head_bytes); |
893 | ASSERT(0); | 860 | ASSERT(0); |
894 | free_bytes = log->l_logsize; | 861 | free_bytes = log->l_logsize; |
895 | } | 862 | } |
896 | return free_bytes; | 863 | return free_bytes; |
897 | } /* xlog_space_left */ | 864 | } |
898 | 865 | ||
899 | 866 | ||
900 | /* | 867 | /* |
@@ -1047,12 +1014,16 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1047 | log->l_flags |= XLOG_ACTIVE_RECOVERY; | 1014 | log->l_flags |= XLOG_ACTIVE_RECOVERY; |
1048 | 1015 | ||
1049 | log->l_prev_block = -1; | 1016 | log->l_prev_block = -1; |
1050 | log->l_tail_lsn = xlog_assign_lsn(1, 0); | ||
1051 | /* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */ | 1017 | /* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */ |
1052 | log->l_last_sync_lsn = log->l_tail_lsn; | 1018 | xlog_assign_atomic_lsn(&log->l_tail_lsn, 1, 0); |
1019 | xlog_assign_atomic_lsn(&log->l_last_sync_lsn, 1, 0); | ||
1053 | log->l_curr_cycle = 1; /* 0 is bad since this is initial value */ | 1020 | log->l_curr_cycle = 1; /* 0 is bad since this is initial value */ |
1054 | log->l_grant_reserve_cycle = 1; | 1021 | xlog_assign_grant_head(&log->l_grant_reserve_head, 1, 0); |
1055 | log->l_grant_write_cycle = 1; | 1022 | xlog_assign_grant_head(&log->l_grant_write_head, 1, 0); |
1023 | INIT_LIST_HEAD(&log->l_reserveq); | ||
1024 | INIT_LIST_HEAD(&log->l_writeq); | ||
1025 | spin_lock_init(&log->l_grant_reserve_lock); | ||
1026 | spin_lock_init(&log->l_grant_write_lock); | ||
1056 | 1027 | ||
1057 | error = EFSCORRUPTED; | 1028 | error = EFSCORRUPTED; |
1058 | if (xfs_sb_version_hassector(&mp->m_sb)) { | 1029 | if (xfs_sb_version_hassector(&mp->m_sb)) { |
@@ -1094,8 +1065,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1094 | log->l_xbuf = bp; | 1065 | log->l_xbuf = bp; |
1095 | 1066 | ||
1096 | spin_lock_init(&log->l_icloglock); | 1067 | spin_lock_init(&log->l_icloglock); |
1097 | spin_lock_init(&log->l_grant_lock); | 1068 | init_waitqueue_head(&log->l_flush_wait); |
1098 | sv_init(&log->l_flush_wait, 0, "flush_wait"); | ||
1099 | 1069 | ||
1100 | /* 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 */ |
1101 | ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); | 1071 | ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); |
@@ -1151,8 +1121,8 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1151 | 1121 | ||
1152 | ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp)); | 1122 | ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp)); |
1153 | ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0); | 1123 | ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0); |
1154 | sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); | 1124 | init_waitqueue_head(&iclog->ic_force_wait); |
1155 | sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); | 1125 | init_waitqueue_head(&iclog->ic_write_wait); |
1156 | 1126 | ||
1157 | iclogp = &iclog->ic_next; | 1127 | iclogp = &iclog->ic_next; |
1158 | } | 1128 | } |
@@ -1167,15 +1137,11 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1167 | out_free_iclog: | 1137 | out_free_iclog: |
1168 | for (iclog = log->l_iclog; iclog; iclog = prev_iclog) { | 1138 | for (iclog = log->l_iclog; iclog; iclog = prev_iclog) { |
1169 | prev_iclog = iclog->ic_next; | 1139 | prev_iclog = iclog->ic_next; |
1170 | if (iclog->ic_bp) { | 1140 | if (iclog->ic_bp) |
1171 | sv_destroy(&iclog->ic_force_wait); | ||
1172 | sv_destroy(&iclog->ic_write_wait); | ||
1173 | xfs_buf_free(iclog->ic_bp); | 1141 | xfs_buf_free(iclog->ic_bp); |
1174 | } | ||
1175 | kmem_free(iclog); | 1142 | kmem_free(iclog); |
1176 | } | 1143 | } |
1177 | spinlock_destroy(&log->l_icloglock); | 1144 | spinlock_destroy(&log->l_icloglock); |
1178 | spinlock_destroy(&log->l_grant_lock); | ||
1179 | xfs_buf_free(log->l_xbuf); | 1145 | xfs_buf_free(log->l_xbuf); |
1180 | out_free_log: | 1146 | out_free_log: |
1181 | kmem_free(log); | 1147 | kmem_free(log); |
@@ -1223,61 +1189,60 @@ xlog_commit_record( | |||
1223 | * water mark. In this manner, we would be creating a low water mark. | 1189 | * water mark. In this manner, we would be creating a low water mark. |
1224 | */ | 1190 | */ |
1225 | STATIC void | 1191 | STATIC void |
1226 | xlog_grant_push_ail(xfs_mount_t *mp, | 1192 | xlog_grant_push_ail( |
1227 | int need_bytes) | 1193 | struct log *log, |
1194 | int need_bytes) | ||
1228 | { | 1195 | { |
1229 | xlog_t *log = mp->m_log; /* pointer to the log */ | 1196 | xfs_lsn_t threshold_lsn = 0; |
1230 | xfs_lsn_t tail_lsn; /* lsn of the log tail */ | 1197 | xfs_lsn_t last_sync_lsn; |
1231 | xfs_lsn_t threshold_lsn = 0; /* lsn we'd like to be at */ | 1198 | int free_blocks; |
1232 | int free_blocks; /* free blocks left to write to */ | 1199 | int free_bytes; |
1233 | int free_bytes; /* free bytes left to write to */ | 1200 | int threshold_block; |
1234 | int threshold_block; /* block in lsn we'd like to be at */ | 1201 | int threshold_cycle; |
1235 | int threshold_cycle; /* lsn cycle we'd like to be at */ | 1202 | int free_threshold; |
1236 | int free_threshold; | 1203 | |
1237 | 1204 | ASSERT(BTOBB(need_bytes) < log->l_logBBsize); | |
1238 | ASSERT(BTOBB(need_bytes) < log->l_logBBsize); | 1205 | |
1239 | 1206 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); | |
1240 | spin_lock(&log->l_grant_lock); | 1207 | free_blocks = BTOBBT(free_bytes); |
1241 | free_bytes = xlog_space_left(log, | 1208 | |
1242 | log->l_grant_reserve_cycle, | 1209 | /* |
1243 | log->l_grant_reserve_bytes); | 1210 | * Set the threshold for the minimum number of free blocks in the |
1244 | tail_lsn = log->l_tail_lsn; | 1211 | * log to the maximum of what the caller needs, one quarter of the |
1245 | free_blocks = BTOBBT(free_bytes); | 1212 | * log, and 256 blocks. |
1246 | 1213 | */ | |
1247 | /* | 1214 | free_threshold = BTOBB(need_bytes); |
1248 | * Set the threshold for the minimum number of free blocks in the | 1215 | free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2)); |
1249 | * log to the maximum of what the caller needs, one quarter of the | 1216 | free_threshold = MAX(free_threshold, 256); |
1250 | * log, and 256 blocks. | 1217 | if (free_blocks >= free_threshold) |
1251 | */ | 1218 | return; |
1252 | free_threshold = BTOBB(need_bytes); | 1219 | |
1253 | free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2)); | 1220 | xlog_crack_atomic_lsn(&log->l_tail_lsn, &threshold_cycle, |
1254 | free_threshold = MAX(free_threshold, 256); | 1221 | &threshold_block); |
1255 | if (free_blocks < free_threshold) { | 1222 | threshold_block += free_threshold; |
1256 | threshold_block = BLOCK_LSN(tail_lsn) + free_threshold; | ||
1257 | threshold_cycle = CYCLE_LSN(tail_lsn); | ||
1258 | if (threshold_block >= log->l_logBBsize) { | 1223 | if (threshold_block >= log->l_logBBsize) { |
1259 | threshold_block -= log->l_logBBsize; | 1224 | threshold_block -= log->l_logBBsize; |
1260 | threshold_cycle += 1; | 1225 | threshold_cycle += 1; |
1261 | } | 1226 | } |
1262 | threshold_lsn = xlog_assign_lsn(threshold_cycle, threshold_block); | 1227 | threshold_lsn = xlog_assign_lsn(threshold_cycle, |
1228 | threshold_block); | ||
1229 | /* | ||
1230 | * Don't pass in an lsn greater than the lsn of the last | ||
1231 | * log record known to be on disk. Use a snapshot of the last sync lsn | ||
1232 | * so that it doesn't change between the compare and the set. | ||
1233 | */ | ||
1234 | last_sync_lsn = atomic64_read(&log->l_last_sync_lsn); | ||
1235 | if (XFS_LSN_CMP(threshold_lsn, last_sync_lsn) > 0) | ||
1236 | threshold_lsn = last_sync_lsn; | ||
1263 | 1237 | ||
1264 | /* Don't pass in an lsn greater than the lsn of the last | 1238 | /* |
1265 | * log record known to be on disk. | 1239 | * Get the transaction layer to kick the dirty buffers out to |
1240 | * disk asynchronously. No point in trying to do this if | ||
1241 | * the filesystem is shutting down. | ||
1266 | */ | 1242 | */ |
1267 | if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0) | 1243 | if (!XLOG_FORCED_SHUTDOWN(log)) |
1268 | threshold_lsn = log->l_last_sync_lsn; | 1244 | xfs_trans_ail_push(log->l_ailp, threshold_lsn); |
1269 | } | 1245 | } |
1270 | spin_unlock(&log->l_grant_lock); | ||
1271 | |||
1272 | /* | ||
1273 | * Get the transaction layer to kick the dirty buffers out to | ||
1274 | * disk asynchronously. No point in trying to do this if | ||
1275 | * the filesystem is shutting down. | ||
1276 | */ | ||
1277 | if (threshold_lsn && | ||
1278 | !XLOG_FORCED_SHUTDOWN(log)) | ||
1279 | xfs_trans_ail_push(log->l_ailp, threshold_lsn); | ||
1280 | } /* xlog_grant_push_ail */ | ||
1281 | 1246 | ||
1282 | /* | 1247 | /* |
1283 | * The bdstrat callback function for log bufs. This gives us a central | 1248 | * The bdstrat callback function for log bufs. This gives us a central |
@@ -1372,9 +1337,8 @@ xlog_sync(xlog_t *log, | |||
1372 | roundoff < BBTOB(1))); | 1337 | roundoff < BBTOB(1))); |
1373 | 1338 | ||
1374 | /* move grant heads by roundoff in sync */ | 1339 | /* move grant heads by roundoff in sync */ |
1375 | spin_lock(&log->l_grant_lock); | 1340 | xlog_grant_add_space(log, &log->l_grant_reserve_head, roundoff); |
1376 | xlog_grant_add_space(log, roundoff); | 1341 | xlog_grant_add_space(log, &log->l_grant_write_head, roundoff); |
1377 | spin_unlock(&log->l_grant_lock); | ||
1378 | 1342 | ||
1379 | /* put cycle number in every block */ | 1343 | /* put cycle number in every block */ |
1380 | xlog_pack_data(log, iclog, roundoff); | 1344 | xlog_pack_data(log, iclog, roundoff); |
@@ -1489,15 +1453,12 @@ xlog_dealloc_log(xlog_t *log) | |||
1489 | 1453 | ||
1490 | iclog = log->l_iclog; | 1454 | iclog = log->l_iclog; |
1491 | for (i=0; i<log->l_iclog_bufs; i++) { | 1455 | for (i=0; i<log->l_iclog_bufs; i++) { |
1492 | sv_destroy(&iclog->ic_force_wait); | ||
1493 | sv_destroy(&iclog->ic_write_wait); | ||
1494 | xfs_buf_free(iclog->ic_bp); | 1456 | xfs_buf_free(iclog->ic_bp); |
1495 | next_iclog = iclog->ic_next; | 1457 | next_iclog = iclog->ic_next; |
1496 | kmem_free(iclog); | 1458 | kmem_free(iclog); |
1497 | iclog = next_iclog; | 1459 | iclog = next_iclog; |
1498 | } | 1460 | } |
1499 | spinlock_destroy(&log->l_icloglock); | 1461 | spinlock_destroy(&log->l_icloglock); |
1500 | spinlock_destroy(&log->l_grant_lock); | ||
1501 | 1462 | ||
1502 | xfs_buf_free(log->l_xbuf); | 1463 | xfs_buf_free(log->l_xbuf); |
1503 | log->l_mp->m_log = NULL; | 1464 | log->l_mp->m_log = NULL; |
@@ -2232,7 +2193,7 @@ xlog_state_do_callback( | |||
2232 | lowest_lsn = xlog_get_lowest_lsn(log); | 2193 | lowest_lsn = xlog_get_lowest_lsn(log); |
2233 | if (lowest_lsn && | 2194 | if (lowest_lsn && |
2234 | XFS_LSN_CMP(lowest_lsn, | 2195 | XFS_LSN_CMP(lowest_lsn, |
2235 | be64_to_cpu(iclog->ic_header.h_lsn)) < 0) { | 2196 | be64_to_cpu(iclog->ic_header.h_lsn)) < 0) { |
2236 | iclog = iclog->ic_next; | 2197 | iclog = iclog->ic_next; |
2237 | continue; /* Leave this iclog for | 2198 | continue; /* Leave this iclog for |
2238 | * another thread */ | 2199 | * another thread */ |
@@ -2240,23 +2201,21 @@ xlog_state_do_callback( | |||
2240 | 2201 | ||
2241 | iclog->ic_state = XLOG_STATE_CALLBACK; | 2202 | iclog->ic_state = XLOG_STATE_CALLBACK; |
2242 | 2203 | ||
2243 | spin_unlock(&log->l_icloglock); | ||
2244 | 2204 | ||
2245 | /* l_last_sync_lsn field protected by | 2205 | /* |
2246 | * l_grant_lock. Don't worry about iclog's lsn. | 2206 | * update the last_sync_lsn before we drop the |
2247 | * No one else can be here except us. | 2207 | * icloglock to ensure we are the only one that |
2208 | * can update it. | ||
2248 | */ | 2209 | */ |
2249 | spin_lock(&log->l_grant_lock); | 2210 | ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn), |
2250 | ASSERT(XFS_LSN_CMP(log->l_last_sync_lsn, | 2211 | be64_to_cpu(iclog->ic_header.h_lsn)) <= 0); |
2251 | be64_to_cpu(iclog->ic_header.h_lsn)) <= 0); | 2212 | atomic64_set(&log->l_last_sync_lsn, |
2252 | log->l_last_sync_lsn = | 2213 | be64_to_cpu(iclog->ic_header.h_lsn)); |
2253 | be64_to_cpu(iclog->ic_header.h_lsn); | ||
2254 | spin_unlock(&log->l_grant_lock); | ||
2255 | 2214 | ||
2256 | } else { | 2215 | } else |
2257 | spin_unlock(&log->l_icloglock); | ||
2258 | ioerrors++; | 2216 | ioerrors++; |
2259 | } | 2217 | |
2218 | spin_unlock(&log->l_icloglock); | ||
2260 | 2219 | ||
2261 | /* | 2220 | /* |
2262 | * Keep processing entries in the callback list until | 2221 | * Keep processing entries in the callback list until |
@@ -2297,7 +2256,7 @@ xlog_state_do_callback( | |||
2297 | xlog_state_clean_log(log); | 2256 | xlog_state_clean_log(log); |
2298 | 2257 | ||
2299 | /* wake up threads waiting in xfs_log_force() */ | 2258 | /* wake up threads waiting in xfs_log_force() */ |
2300 | sv_broadcast(&iclog->ic_force_wait); | 2259 | wake_up_all(&iclog->ic_force_wait); |
2301 | 2260 | ||
2302 | iclog = iclog->ic_next; | 2261 | iclog = iclog->ic_next; |
2303 | } while (first_iclog != iclog); | 2262 | } while (first_iclog != iclog); |
@@ -2344,7 +2303,7 @@ xlog_state_do_callback( | |||
2344 | spin_unlock(&log->l_icloglock); | 2303 | spin_unlock(&log->l_icloglock); |
2345 | 2304 | ||
2346 | if (wake) | 2305 | if (wake) |
2347 | sv_broadcast(&log->l_flush_wait); | 2306 | wake_up_all(&log->l_flush_wait); |
2348 | } | 2307 | } |
2349 | 2308 | ||
2350 | 2309 | ||
@@ -2395,7 +2354,7 @@ xlog_state_done_syncing( | |||
2395 | * iclog buffer, we wake them all, one will get to do the | 2354 | * iclog buffer, we wake them all, one will get to do the |
2396 | * I/O, the others get to wait for the result. | 2355 | * I/O, the others get to wait for the result. |
2397 | */ | 2356 | */ |
2398 | sv_broadcast(&iclog->ic_write_wait); | 2357 | wake_up_all(&iclog->ic_write_wait); |
2399 | spin_unlock(&log->l_icloglock); | 2358 | spin_unlock(&log->l_icloglock); |
2400 | xlog_state_do_callback(log, aborted, iclog); /* also cleans log */ | 2359 | xlog_state_do_callback(log, aborted, iclog); /* also cleans log */ |
2401 | } /* xlog_state_done_syncing */ | 2360 | } /* xlog_state_done_syncing */ |
@@ -2444,7 +2403,7 @@ restart: | |||
2444 | XFS_STATS_INC(xs_log_noiclogs); | 2403 | XFS_STATS_INC(xs_log_noiclogs); |
2445 | 2404 | ||
2446 | /* Wait for log writes to have flushed */ | 2405 | /* Wait for log writes to have flushed */ |
2447 | sv_wait(&log->l_flush_wait, 0, &log->l_icloglock, 0); | 2406 | xlog_wait(&log->l_flush_wait, &log->l_icloglock); |
2448 | goto restart; | 2407 | goto restart; |
2449 | } | 2408 | } |
2450 | 2409 | ||
@@ -2527,6 +2486,18 @@ restart: | |||
2527 | * | 2486 | * |
2528 | * Once a ticket gets put onto the reserveq, it will only return after | 2487 | * Once a ticket gets put onto the reserveq, it will only return after |
2529 | * the needed reservation is satisfied. | 2488 | * the needed reservation is satisfied. |
2489 | * | ||
2490 | * This function is structured so that it has a lock free fast path. This is | ||
2491 | * necessary because every new transaction reservation will come through this | ||
2492 | * path. Hence any lock will be globally hot if we take it unconditionally on | ||
2493 | * every pass. | ||
2494 | * | ||
2495 | * As tickets are only ever moved on and off the reserveq under the | ||
2496 | * l_grant_reserve_lock, we only need to take that lock if we are going | ||
2497 | * to add the ticket to the queue and sleep. We can avoid taking the lock if the | ||
2498 | * ticket was never added to the reserveq because the t_queue list head will be | ||
2499 | * empty and we hold the only reference to it so it can safely be checked | ||
2500 | * unlocked. | ||
2530 | */ | 2501 | */ |
2531 | STATIC int | 2502 | STATIC int |
2532 | xlog_grant_log_space(xlog_t *log, | 2503 | xlog_grant_log_space(xlog_t *log, |
@@ -2534,24 +2505,27 @@ xlog_grant_log_space(xlog_t *log, | |||
2534 | { | 2505 | { |
2535 | int free_bytes; | 2506 | int free_bytes; |
2536 | int need_bytes; | 2507 | int need_bytes; |
2537 | #ifdef DEBUG | ||
2538 | xfs_lsn_t tail_lsn; | ||
2539 | #endif | ||
2540 | |||
2541 | 2508 | ||
2542 | #ifdef DEBUG | 2509 | #ifdef DEBUG |
2543 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | 2510 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) |
2544 | panic("grant Recovery problem"); | 2511 | panic("grant Recovery problem"); |
2545 | #endif | 2512 | #endif |
2546 | 2513 | ||
2547 | /* Is there space or do we need to sleep? */ | ||
2548 | spin_lock(&log->l_grant_lock); | ||
2549 | |||
2550 | trace_xfs_log_grant_enter(log, tic); | 2514 | trace_xfs_log_grant_enter(log, tic); |
2551 | 2515 | ||
2516 | need_bytes = tic->t_unit_res; | ||
2517 | if (tic->t_flags & XFS_LOG_PERM_RESERV) | ||
2518 | need_bytes *= tic->t_ocnt; | ||
2519 | |||
2552 | /* something is already sleeping; insert new transaction at end */ | 2520 | /* something is already sleeping; insert new transaction at end */ |
2553 | if (log->l_reserve_headq) { | 2521 | if (!list_empty_careful(&log->l_reserveq)) { |
2554 | xlog_ins_ticketq(&log->l_reserve_headq, tic); | 2522 | spin_lock(&log->l_grant_reserve_lock); |
2523 | /* recheck the queue now we are locked */ | ||
2524 | if (list_empty(&log->l_reserveq)) { | ||
2525 | spin_unlock(&log->l_grant_reserve_lock); | ||
2526 | goto redo; | ||
2527 | } | ||
2528 | list_add_tail(&tic->t_queue, &log->l_reserveq); | ||
2555 | 2529 | ||
2556 | trace_xfs_log_grant_sleep1(log, tic); | 2530 | trace_xfs_log_grant_sleep1(log, tic); |
2557 | 2531 | ||
@@ -2563,72 +2537,57 @@ xlog_grant_log_space(xlog_t *log, | |||
2563 | goto error_return; | 2537 | goto error_return; |
2564 | 2538 | ||
2565 | XFS_STATS_INC(xs_sleep_logspace); | 2539 | XFS_STATS_INC(xs_sleep_logspace); |
2566 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | 2540 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); |
2541 | |||
2567 | /* | 2542 | /* |
2568 | * If we got an error, and the filesystem is shutting down, | 2543 | * If we got an error, and the filesystem is shutting down, |
2569 | * we'll catch it down below. So just continue... | 2544 | * we'll catch it down below. So just continue... |
2570 | */ | 2545 | */ |
2571 | trace_xfs_log_grant_wake1(log, tic); | 2546 | trace_xfs_log_grant_wake1(log, tic); |
2572 | spin_lock(&log->l_grant_lock); | ||
2573 | } | 2547 | } |
2574 | if (tic->t_flags & XFS_LOG_PERM_RESERV) | ||
2575 | need_bytes = tic->t_unit_res*tic->t_ocnt; | ||
2576 | else | ||
2577 | need_bytes = tic->t_unit_res; | ||
2578 | 2548 | ||
2579 | redo: | 2549 | redo: |
2580 | if (XLOG_FORCED_SHUTDOWN(log)) | 2550 | if (XLOG_FORCED_SHUTDOWN(log)) |
2581 | goto error_return; | 2551 | goto error_return_unlocked; |
2582 | 2552 | ||
2583 | free_bytes = xlog_space_left(log, log->l_grant_reserve_cycle, | 2553 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); |
2584 | log->l_grant_reserve_bytes); | ||
2585 | if (free_bytes < need_bytes) { | 2554 | if (free_bytes < need_bytes) { |
2586 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) | 2555 | spin_lock(&log->l_grant_reserve_lock); |
2587 | xlog_ins_ticketq(&log->l_reserve_headq, tic); | 2556 | if (list_empty(&tic->t_queue)) |
2557 | list_add_tail(&tic->t_queue, &log->l_reserveq); | ||
2588 | 2558 | ||
2589 | trace_xfs_log_grant_sleep2(log, tic); | 2559 | trace_xfs_log_grant_sleep2(log, tic); |
2590 | 2560 | ||
2591 | spin_unlock(&log->l_grant_lock); | ||
2592 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2593 | spin_lock(&log->l_grant_lock); | ||
2594 | |||
2595 | XFS_STATS_INC(xs_sleep_logspace); | ||
2596 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | ||
2597 | |||
2598 | spin_lock(&log->l_grant_lock); | ||
2599 | if (XLOG_FORCED_SHUTDOWN(log)) | 2561 | if (XLOG_FORCED_SHUTDOWN(log)) |
2600 | goto error_return; | 2562 | goto error_return; |
2601 | 2563 | ||
2602 | trace_xfs_log_grant_wake2(log, tic); | 2564 | xlog_grant_push_ail(log, need_bytes); |
2565 | |||
2566 | XFS_STATS_INC(xs_sleep_logspace); | ||
2567 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); | ||
2603 | 2568 | ||
2569 | trace_xfs_log_grant_wake2(log, tic); | ||
2604 | goto redo; | 2570 | goto redo; |
2605 | } else if (tic->t_flags & XLOG_TIC_IN_Q) | 2571 | } |
2606 | xlog_del_ticketq(&log->l_reserve_headq, tic); | ||
2607 | 2572 | ||
2608 | /* we've got enough space */ | 2573 | if (!list_empty(&tic->t_queue)) { |
2609 | xlog_grant_add_space(log, need_bytes); | 2574 | spin_lock(&log->l_grant_reserve_lock); |
2610 | #ifdef DEBUG | 2575 | list_del_init(&tic->t_queue); |
2611 | tail_lsn = log->l_tail_lsn; | 2576 | spin_unlock(&log->l_grant_reserve_lock); |
2612 | /* | ||
2613 | * Check to make sure the grant write head didn't just over lap the | ||
2614 | * tail. If the cycles are the same, we can't be overlapping. | ||
2615 | * Otherwise, make sure that the cycles differ by exactly one and | ||
2616 | * check the byte count. | ||
2617 | */ | ||
2618 | if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) { | ||
2619 | ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn)); | ||
2620 | ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn))); | ||
2621 | } | 2577 | } |
2622 | #endif | 2578 | |
2579 | /* we've got enough space */ | ||
2580 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); | ||
2581 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | ||
2623 | trace_xfs_log_grant_exit(log, tic); | 2582 | trace_xfs_log_grant_exit(log, tic); |
2624 | xlog_verify_grant_head(log, 1); | 2583 | xlog_verify_grant_tail(log); |
2625 | spin_unlock(&log->l_grant_lock); | ||
2626 | return 0; | 2584 | return 0; |
2627 | 2585 | ||
2628 | error_return: | 2586 | error_return_unlocked: |
2629 | if (tic->t_flags & XLOG_TIC_IN_Q) | 2587 | spin_lock(&log->l_grant_reserve_lock); |
2630 | xlog_del_ticketq(&log->l_reserve_headq, tic); | 2588 | error_return: |
2631 | 2589 | list_del_init(&tic->t_queue); | |
2590 | spin_unlock(&log->l_grant_reserve_lock); | ||
2632 | trace_xfs_log_grant_error(log, tic); | 2591 | trace_xfs_log_grant_error(log, tic); |
2633 | 2592 | ||
2634 | /* | 2593 | /* |
@@ -2638,7 +2597,6 @@ redo: | |||
2638 | */ | 2597 | */ |
2639 | tic->t_curr_res = 0; | 2598 | tic->t_curr_res = 0; |
2640 | 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. */ |
2641 | spin_unlock(&log->l_grant_lock); | ||
2642 | return XFS_ERROR(EIO); | 2600 | return XFS_ERROR(EIO); |
2643 | } /* xlog_grant_log_space */ | 2601 | } /* xlog_grant_log_space */ |
2644 | 2602 | ||
@@ -2646,17 +2604,14 @@ redo: | |||
2646 | /* | 2604 | /* |
2647 | * Replenish the byte reservation required by moving the grant write head. | 2605 | * Replenish the byte reservation required by moving the grant write head. |
2648 | * | 2606 | * |
2649 | * | 2607 | * Similar to xlog_grant_log_space, the function is structured to have a lock |
2608 | * free fast path. | ||
2650 | */ | 2609 | */ |
2651 | STATIC int | 2610 | STATIC int |
2652 | xlog_regrant_write_log_space(xlog_t *log, | 2611 | xlog_regrant_write_log_space(xlog_t *log, |
2653 | xlog_ticket_t *tic) | 2612 | xlog_ticket_t *tic) |
2654 | { | 2613 | { |
2655 | int free_bytes, need_bytes; | 2614 | int free_bytes, need_bytes; |
2656 | xlog_ticket_t *ntic; | ||
2657 | #ifdef DEBUG | ||
2658 | xfs_lsn_t tail_lsn; | ||
2659 | #endif | ||
2660 | 2615 | ||
2661 | tic->t_curr_res = tic->t_unit_res; | 2616 | tic->t_curr_res = tic->t_unit_res; |
2662 | xlog_tic_reset_res(tic); | 2617 | xlog_tic_reset_res(tic); |
@@ -2669,12 +2624,9 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2669 | panic("regrant Recovery problem"); | 2624 | panic("regrant Recovery problem"); |
2670 | #endif | 2625 | #endif |
2671 | 2626 | ||
2672 | spin_lock(&log->l_grant_lock); | ||
2673 | |||
2674 | trace_xfs_log_regrant_write_enter(log, tic); | 2627 | trace_xfs_log_regrant_write_enter(log, tic); |
2675 | |||
2676 | if (XLOG_FORCED_SHUTDOWN(log)) | 2628 | if (XLOG_FORCED_SHUTDOWN(log)) |
2677 | goto error_return; | 2629 | goto error_return_unlocked; |
2678 | 2630 | ||
2679 | /* 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 |
2680 | * chance at logspace before us. Wake up the first waiters, | 2632 | * chance at logspace before us. Wake up the first waiters, |
@@ -2683,92 +2635,76 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
2683 | * this transaction. | 2635 | * this transaction. |
2684 | */ | 2636 | */ |
2685 | need_bytes = tic->t_unit_res; | 2637 | need_bytes = tic->t_unit_res; |
2686 | if ((ntic = log->l_write_headq)) { | 2638 | if (!list_empty_careful(&log->l_writeq)) { |
2687 | free_bytes = xlog_space_left(log, log->l_grant_write_cycle, | 2639 | struct xlog_ticket *ntic; |
2688 | log->l_grant_write_bytes); | 2640 | |
2689 | do { | 2641 | spin_lock(&log->l_grant_write_lock); |
2642 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); | ||
2643 | list_for_each_entry(ntic, &log->l_writeq, t_queue) { | ||
2690 | ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV); | 2644 | ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV); |
2691 | 2645 | ||
2692 | if (free_bytes < ntic->t_unit_res) | 2646 | if (free_bytes < ntic->t_unit_res) |
2693 | break; | 2647 | break; |
2694 | free_bytes -= ntic->t_unit_res; | 2648 | free_bytes -= ntic->t_unit_res; |
2695 | sv_signal(&ntic->t_wait); | 2649 | wake_up(&ntic->t_wait); |
2696 | ntic = ntic->t_next; | 2650 | } |
2697 | } while (ntic != log->l_write_headq); | ||
2698 | |||
2699 | if (ntic != log->l_write_headq) { | ||
2700 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) | ||
2701 | xlog_ins_ticketq(&log->l_write_headq, tic); | ||
2702 | 2651 | ||
2652 | if (ntic != list_first_entry(&log->l_writeq, | ||
2653 | struct xlog_ticket, t_queue)) { | ||
2654 | if (list_empty(&tic->t_queue)) | ||
2655 | list_add_tail(&tic->t_queue, &log->l_writeq); | ||
2703 | trace_xfs_log_regrant_write_sleep1(log, tic); | 2656 | trace_xfs_log_regrant_write_sleep1(log, tic); |
2704 | 2657 | ||
2705 | spin_unlock(&log->l_grant_lock); | 2658 | xlog_grant_push_ail(log, need_bytes); |
2706 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2707 | spin_lock(&log->l_grant_lock); | ||
2708 | 2659 | ||
2709 | XFS_STATS_INC(xs_sleep_logspace); | 2660 | XFS_STATS_INC(xs_sleep_logspace); |
2710 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, | 2661 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); |
2711 | &log->l_grant_lock, s); | ||
2712 | |||
2713 | /* If we're shutting down, this tic is already | ||
2714 | * off the queue */ | ||
2715 | spin_lock(&log->l_grant_lock); | ||
2716 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
2717 | goto error_return; | ||
2718 | |||
2719 | trace_xfs_log_regrant_write_wake1(log, tic); | 2662 | trace_xfs_log_regrant_write_wake1(log, tic); |
2720 | } | 2663 | } else |
2664 | spin_unlock(&log->l_grant_write_lock); | ||
2721 | } | 2665 | } |
2722 | 2666 | ||
2723 | redo: | 2667 | redo: |
2724 | if (XLOG_FORCED_SHUTDOWN(log)) | 2668 | if (XLOG_FORCED_SHUTDOWN(log)) |
2725 | goto error_return; | 2669 | goto error_return_unlocked; |
2726 | 2670 | ||
2727 | free_bytes = xlog_space_left(log, log->l_grant_write_cycle, | 2671 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); |
2728 | log->l_grant_write_bytes); | ||
2729 | if (free_bytes < need_bytes) { | 2672 | if (free_bytes < need_bytes) { |
2730 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) | 2673 | spin_lock(&log->l_grant_write_lock); |
2731 | xlog_ins_ticketq(&log->l_write_headq, tic); | 2674 | if (list_empty(&tic->t_queue)) |
2732 | spin_unlock(&log->l_grant_lock); | 2675 | list_add_tail(&tic->t_queue, &log->l_writeq); |
2733 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
2734 | spin_lock(&log->l_grant_lock); | ||
2735 | |||
2736 | XFS_STATS_INC(xs_sleep_logspace); | ||
2737 | trace_xfs_log_regrant_write_sleep2(log, tic); | ||
2738 | |||
2739 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | ||
2740 | 2676 | ||
2741 | /* If we're shutting down, this tic is already off the queue */ | ||
2742 | spin_lock(&log->l_grant_lock); | ||
2743 | if (XLOG_FORCED_SHUTDOWN(log)) | 2677 | if (XLOG_FORCED_SHUTDOWN(log)) |
2744 | goto error_return; | 2678 | goto error_return; |
2745 | 2679 | ||
2680 | xlog_grant_push_ail(log, need_bytes); | ||
2681 | |||
2682 | XFS_STATS_INC(xs_sleep_logspace); | ||
2683 | trace_xfs_log_regrant_write_sleep2(log, tic); | ||
2684 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); | ||
2685 | |||
2746 | trace_xfs_log_regrant_write_wake2(log, tic); | 2686 | trace_xfs_log_regrant_write_wake2(log, tic); |
2747 | goto redo; | 2687 | goto redo; |
2748 | } else if (tic->t_flags & XLOG_TIC_IN_Q) | 2688 | } |
2749 | xlog_del_ticketq(&log->l_write_headq, tic); | ||
2750 | 2689 | ||
2751 | /* we've got enough space */ | 2690 | if (!list_empty(&tic->t_queue)) { |
2752 | xlog_grant_add_space_write(log, need_bytes); | 2691 | spin_lock(&log->l_grant_write_lock); |
2753 | #ifdef DEBUG | 2692 | list_del_init(&tic->t_queue); |
2754 | tail_lsn = log->l_tail_lsn; | 2693 | spin_unlock(&log->l_grant_write_lock); |
2755 | if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) { | ||
2756 | ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn)); | ||
2757 | ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn))); | ||
2758 | } | 2694 | } |
2759 | #endif | ||
2760 | 2695 | ||
2696 | /* we've got enough space */ | ||
2697 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | ||
2761 | trace_xfs_log_regrant_write_exit(log, tic); | 2698 | trace_xfs_log_regrant_write_exit(log, tic); |
2762 | 2699 | xlog_verify_grant_tail(log); | |
2763 | xlog_verify_grant_head(log, 1); | ||
2764 | spin_unlock(&log->l_grant_lock); | ||
2765 | return 0; | 2700 | return 0; |
2766 | 2701 | ||
2767 | 2702 | ||
2703 | error_return_unlocked: | ||
2704 | spin_lock(&log->l_grant_write_lock); | ||
2768 | error_return: | 2705 | error_return: |
2769 | if (tic->t_flags & XLOG_TIC_IN_Q) | 2706 | list_del_init(&tic->t_queue); |
2770 | xlog_del_ticketq(&log->l_reserve_headq, tic); | 2707 | spin_unlock(&log->l_grant_write_lock); |
2771 | |||
2772 | trace_xfs_log_regrant_write_error(log, tic); | 2708 | trace_xfs_log_regrant_write_error(log, tic); |
2773 | 2709 | ||
2774 | /* | 2710 | /* |
@@ -2778,7 +2714,6 @@ redo: | |||
2778 | */ | 2714 | */ |
2779 | tic->t_curr_res = 0; | 2715 | tic->t_curr_res = 0; |
2780 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ | 2716 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ |
2781 | spin_unlock(&log->l_grant_lock); | ||
2782 | return XFS_ERROR(EIO); | 2717 | return XFS_ERROR(EIO); |
2783 | } /* xlog_regrant_write_log_space */ | 2718 | } /* xlog_regrant_write_log_space */ |
2784 | 2719 | ||
@@ -2799,27 +2734,24 @@ xlog_regrant_reserve_log_space(xlog_t *log, | |||
2799 | if (ticket->t_cnt > 0) | 2734 | if (ticket->t_cnt > 0) |
2800 | ticket->t_cnt--; | 2735 | ticket->t_cnt--; |
2801 | 2736 | ||
2802 | spin_lock(&log->l_grant_lock); | 2737 | xlog_grant_sub_space(log, &log->l_grant_reserve_head, |
2803 | xlog_grant_sub_space(log, ticket->t_curr_res); | 2738 | ticket->t_curr_res); |
2739 | xlog_grant_sub_space(log, &log->l_grant_write_head, | ||
2740 | ticket->t_curr_res); | ||
2804 | ticket->t_curr_res = ticket->t_unit_res; | 2741 | ticket->t_curr_res = ticket->t_unit_res; |
2805 | xlog_tic_reset_res(ticket); | 2742 | xlog_tic_reset_res(ticket); |
2806 | 2743 | ||
2807 | trace_xfs_log_regrant_reserve_sub(log, ticket); | 2744 | trace_xfs_log_regrant_reserve_sub(log, ticket); |
2808 | 2745 | ||
2809 | xlog_verify_grant_head(log, 1); | ||
2810 | |||
2811 | /* 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 */ |
2812 | if (ticket->t_cnt > 0) { | 2747 | if (ticket->t_cnt > 0) |
2813 | spin_unlock(&log->l_grant_lock); | ||
2814 | return; | 2748 | return; |
2815 | } | ||
2816 | 2749 | ||
2817 | xlog_grant_add_space_reserve(log, ticket->t_unit_res); | 2750 | xlog_grant_add_space(log, &log->l_grant_reserve_head, |
2751 | ticket->t_unit_res); | ||
2818 | 2752 | ||
2819 | trace_xfs_log_regrant_reserve_exit(log, ticket); | 2753 | trace_xfs_log_regrant_reserve_exit(log, ticket); |
2820 | 2754 | ||
2821 | xlog_verify_grant_head(log, 0); | ||
2822 | spin_unlock(&log->l_grant_lock); | ||
2823 | ticket->t_curr_res = ticket->t_unit_res; | 2755 | ticket->t_curr_res = ticket->t_unit_res; |
2824 | xlog_tic_reset_res(ticket); | 2756 | xlog_tic_reset_res(ticket); |
2825 | } /* xlog_regrant_reserve_log_space */ | 2757 | } /* xlog_regrant_reserve_log_space */ |
@@ -2843,28 +2775,29 @@ STATIC void | |||
2843 | xlog_ungrant_log_space(xlog_t *log, | 2775 | xlog_ungrant_log_space(xlog_t *log, |
2844 | xlog_ticket_t *ticket) | 2776 | xlog_ticket_t *ticket) |
2845 | { | 2777 | { |
2778 | int bytes; | ||
2779 | |||
2846 | if (ticket->t_cnt > 0) | 2780 | if (ticket->t_cnt > 0) |
2847 | ticket->t_cnt--; | 2781 | ticket->t_cnt--; |
2848 | 2782 | ||
2849 | spin_lock(&log->l_grant_lock); | ||
2850 | trace_xfs_log_ungrant_enter(log, ticket); | 2783 | trace_xfs_log_ungrant_enter(log, ticket); |
2851 | |||
2852 | xlog_grant_sub_space(log, ticket->t_curr_res); | ||
2853 | |||
2854 | trace_xfs_log_ungrant_sub(log, ticket); | 2784 | trace_xfs_log_ungrant_sub(log, ticket); |
2855 | 2785 | ||
2856 | /* If this is a permanent reservation ticket, we may be able to free | 2786 | /* |
2787 | * If this is a permanent reservation ticket, we may be able to free | ||
2857 | * up more space based on the remaining count. | 2788 | * up more space based on the remaining count. |
2858 | */ | 2789 | */ |
2790 | bytes = ticket->t_curr_res; | ||
2859 | if (ticket->t_cnt > 0) { | 2791 | if (ticket->t_cnt > 0) { |
2860 | ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV); | 2792 | ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV); |
2861 | xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt); | 2793 | bytes += ticket->t_unit_res*ticket->t_cnt; |
2862 | } | 2794 | } |
2863 | 2795 | ||
2796 | xlog_grant_sub_space(log, &log->l_grant_reserve_head, bytes); | ||
2797 | xlog_grant_sub_space(log, &log->l_grant_write_head, bytes); | ||
2798 | |||
2864 | trace_xfs_log_ungrant_exit(log, ticket); | 2799 | trace_xfs_log_ungrant_exit(log, ticket); |
2865 | 2800 | ||
2866 | xlog_verify_grant_head(log, 1); | ||
2867 | spin_unlock(&log->l_grant_lock); | ||
2868 | xfs_log_move_tail(log->l_mp, 1); | 2801 | xfs_log_move_tail(log->l_mp, 1); |
2869 | } /* xlog_ungrant_log_space */ | 2802 | } /* xlog_ungrant_log_space */ |
2870 | 2803 | ||
@@ -2901,11 +2834,11 @@ xlog_state_release_iclog( | |||
2901 | 2834 | ||
2902 | if (iclog->ic_state == XLOG_STATE_WANT_SYNC) { | 2835 | if (iclog->ic_state == XLOG_STATE_WANT_SYNC) { |
2903 | /* update tail before writing to iclog */ | 2836 | /* update tail before writing to iclog */ |
2904 | xlog_assign_tail_lsn(log->l_mp); | 2837 | xfs_lsn_t tail_lsn = xlog_assign_tail_lsn(log->l_mp); |
2905 | sync++; | 2838 | sync++; |
2906 | iclog->ic_state = XLOG_STATE_SYNCING; | 2839 | iclog->ic_state = XLOG_STATE_SYNCING; |
2907 | iclog->ic_header.h_tail_lsn = cpu_to_be64(log->l_tail_lsn); | 2840 | iclog->ic_header.h_tail_lsn = cpu_to_be64(tail_lsn); |
2908 | xlog_verify_tail_lsn(log, iclog, log->l_tail_lsn); | 2841 | xlog_verify_tail_lsn(log, iclog, tail_lsn); |
2909 | /* cycle incremented when incrementing curr_block */ | 2842 | /* cycle incremented when incrementing curr_block */ |
2910 | } | 2843 | } |
2911 | spin_unlock(&log->l_icloglock); | 2844 | spin_unlock(&log->l_icloglock); |
@@ -3088,7 +3021,7 @@ maybe_sleep: | |||
3088 | return XFS_ERROR(EIO); | 3021 | return XFS_ERROR(EIO); |
3089 | } | 3022 | } |
3090 | XFS_STATS_INC(xs_log_force_sleep); | 3023 | XFS_STATS_INC(xs_log_force_sleep); |
3091 | sv_wait(&iclog->ic_force_wait, PINOD, &log->l_icloglock, s); | 3024 | xlog_wait(&iclog->ic_force_wait, &log->l_icloglock); |
3092 | /* | 3025 | /* |
3093 | * No need to grab the log lock here since we're | 3026 | * No need to grab the log lock here since we're |
3094 | * only deciding whether or not to return EIO | 3027 | * only deciding whether or not to return EIO |
@@ -3206,8 +3139,8 @@ try_again: | |||
3206 | 3139 | ||
3207 | XFS_STATS_INC(xs_log_force_sleep); | 3140 | XFS_STATS_INC(xs_log_force_sleep); |
3208 | 3141 | ||
3209 | sv_wait(&iclog->ic_prev->ic_write_wait, | 3142 | xlog_wait(&iclog->ic_prev->ic_write_wait, |
3210 | PSWP, &log->l_icloglock, s); | 3143 | &log->l_icloglock); |
3211 | if (log_flushed) | 3144 | if (log_flushed) |
3212 | *log_flushed = 1; | 3145 | *log_flushed = 1; |
3213 | already_slept = 1; | 3146 | already_slept = 1; |
@@ -3235,7 +3168,7 @@ try_again: | |||
3235 | return XFS_ERROR(EIO); | 3168 | return XFS_ERROR(EIO); |
3236 | } | 3169 | } |
3237 | XFS_STATS_INC(xs_log_force_sleep); | 3170 | XFS_STATS_INC(xs_log_force_sleep); |
3238 | sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s); | 3171 | xlog_wait(&iclog->ic_force_wait, &log->l_icloglock); |
3239 | /* | 3172 | /* |
3240 | * No need to grab the log lock here since we're | 3173 | * No need to grab the log lock here since we're |
3241 | * only deciding whether or not to return EIO | 3174 | * only deciding whether or not to return EIO |
@@ -3310,10 +3243,8 @@ xfs_log_ticket_put( | |||
3310 | xlog_ticket_t *ticket) | 3243 | xlog_ticket_t *ticket) |
3311 | { | 3244 | { |
3312 | ASSERT(atomic_read(&ticket->t_ref) > 0); | 3245 | ASSERT(atomic_read(&ticket->t_ref) > 0); |
3313 | if (atomic_dec_and_test(&ticket->t_ref)) { | 3246 | if (atomic_dec_and_test(&ticket->t_ref)) |
3314 | sv_destroy(&ticket->t_wait); | ||
3315 | kmem_zone_free(xfs_log_ticket_zone, ticket); | 3247 | kmem_zone_free(xfs_log_ticket_zone, ticket); |
3316 | } | ||
3317 | } | 3248 | } |
3318 | 3249 | ||
3319 | xlog_ticket_t * | 3250 | xlog_ticket_t * |
@@ -3435,6 +3366,7 @@ xlog_ticket_alloc( | |||
3435 | } | 3366 | } |
3436 | 3367 | ||
3437 | atomic_set(&tic->t_ref, 1); | 3368 | atomic_set(&tic->t_ref, 1); |
3369 | INIT_LIST_HEAD(&tic->t_queue); | ||
3438 | tic->t_unit_res = unit_bytes; | 3370 | tic->t_unit_res = unit_bytes; |
3439 | tic->t_curr_res = unit_bytes; | 3371 | tic->t_curr_res = unit_bytes; |
3440 | tic->t_cnt = cnt; | 3372 | tic->t_cnt = cnt; |
@@ -3445,7 +3377,7 @@ xlog_ticket_alloc( | |||
3445 | tic->t_trans_type = 0; | 3377 | tic->t_trans_type = 0; |
3446 | if (xflags & XFS_LOG_PERM_RESERV) | 3378 | if (xflags & XFS_LOG_PERM_RESERV) |
3447 | tic->t_flags |= XLOG_TIC_PERM_RESERV; | 3379 | tic->t_flags |= XLOG_TIC_PERM_RESERV; |
3448 | sv_init(&tic->t_wait, SV_DEFAULT, "logtick"); | 3380 | init_waitqueue_head(&tic->t_wait); |
3449 | 3381 | ||
3450 | xlog_tic_reset_res(tic); | 3382 | xlog_tic_reset_res(tic); |
3451 | 3383 | ||
@@ -3484,18 +3416,25 @@ xlog_verify_dest_ptr( | |||
3484 | } | 3416 | } |
3485 | 3417 | ||
3486 | STATIC void | 3418 | STATIC void |
3487 | xlog_verify_grant_head(xlog_t *log, int equals) | 3419 | xlog_verify_grant_tail( |
3420 | struct log *log) | ||
3488 | { | 3421 | { |
3489 | if (log->l_grant_reserve_cycle == log->l_grant_write_cycle) { | 3422 | int tail_cycle, tail_blocks; |
3490 | if (equals) | 3423 | int cycle, space; |
3491 | ASSERT(log->l_grant_reserve_bytes >= log->l_grant_write_bytes); | 3424 | |
3492 | else | 3425 | /* |
3493 | ASSERT(log->l_grant_reserve_bytes > log->l_grant_write_bytes); | 3426 | * Check to make sure the grant write head didn't just over lap the |
3494 | } else { | 3427 | * tail. If the cycles are the same, we can't be overlapping. |
3495 | ASSERT(log->l_grant_reserve_cycle-1 == log->l_grant_write_cycle); | 3428 | * Otherwise, make sure that the cycles differ by exactly one and |
3496 | ASSERT(log->l_grant_write_bytes >= log->l_grant_reserve_bytes); | 3429 | * check the byte count. |
3497 | } | 3430 | */ |
3498 | } /* xlog_verify_grant_head */ | 3431 | xlog_crack_grant_head(&log->l_grant_write_head, &cycle, &space); |
3432 | xlog_crack_atomic_lsn(&log->l_tail_lsn, &tail_cycle, &tail_blocks); | ||
3433 | if (tail_cycle != cycle) { | ||
3434 | ASSERT(cycle - 1 == tail_cycle); | ||
3435 | ASSERT(space <= BBTOB(tail_blocks)); | ||
3436 | } | ||
3437 | } | ||
3499 | 3438 | ||
3500 | /* check if it will fit */ | 3439 | /* check if it will fit */ |
3501 | STATIC void | 3440 | STATIC void |
@@ -3716,12 +3655,10 @@ xfs_log_force_umount( | |||
3716 | xlog_cil_force(log); | 3655 | xlog_cil_force(log); |
3717 | 3656 | ||
3718 | /* | 3657 | /* |
3719 | * We must hold both the GRANT lock and the LOG lock, | 3658 | * mark the filesystem and the as in a shutdown state and wake |
3720 | * before we mark the filesystem SHUTDOWN and wake | 3659 | * everybody up to tell them the bad news. |
3721 | * everybody up to tell the bad news. | ||
3722 | */ | 3660 | */ |
3723 | spin_lock(&log->l_icloglock); | 3661 | spin_lock(&log->l_icloglock); |
3724 | spin_lock(&log->l_grant_lock); | ||
3725 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; | 3662 | mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; |
3726 | if (mp->m_sb_bp) | 3663 | if (mp->m_sb_bp) |
3727 | XFS_BUF_DONE(mp->m_sb_bp); | 3664 | XFS_BUF_DONE(mp->m_sb_bp); |
@@ -3742,27 +3679,21 @@ xfs_log_force_umount( | |||
3742 | spin_unlock(&log->l_icloglock); | 3679 | spin_unlock(&log->l_icloglock); |
3743 | 3680 | ||
3744 | /* | 3681 | /* |
3745 | * We don't want anybody waiting for log reservations | 3682 | * We don't want anybody waiting for log reservations after this. That |
3746 | * after this. That means we have to wake up everybody | 3683 | * means we have to wake up everybody queued up on reserveq as well as |
3747 | * queued up on reserve_headq as well as write_headq. | 3684 | * writeq. In addition, we make sure in xlog_{re}grant_log_space that |
3748 | * In addition, we make sure in xlog_{re}grant_log_space | 3685 | * we don't enqueue anything once the SHUTDOWN flag is set, and this |
3749 | * that we don't enqueue anything once the SHUTDOWN flag | 3686 | * action is protected by the grant locks. |
3750 | * is set, and this action is protected by the GRANTLOCK. | ||
3751 | */ | 3687 | */ |
3752 | if ((tic = log->l_reserve_headq)) { | 3688 | spin_lock(&log->l_grant_reserve_lock); |
3753 | do { | 3689 | list_for_each_entry(tic, &log->l_reserveq, t_queue) |
3754 | sv_signal(&tic->t_wait); | 3690 | wake_up(&tic->t_wait); |
3755 | tic = tic->t_next; | 3691 | spin_unlock(&log->l_grant_reserve_lock); |
3756 | } while (tic != log->l_reserve_headq); | 3692 | |
3757 | } | 3693 | spin_lock(&log->l_grant_write_lock); |
3758 | 3694 | list_for_each_entry(tic, &log->l_writeq, t_queue) | |
3759 | if ((tic = log->l_write_headq)) { | 3695 | wake_up(&tic->t_wait); |
3760 | do { | 3696 | spin_unlock(&log->l_grant_write_lock); |
3761 | sv_signal(&tic->t_wait); | ||
3762 | tic = tic->t_next; | ||
3763 | } while (tic != log->l_write_headq); | ||
3764 | } | ||
3765 | spin_unlock(&log->l_grant_lock); | ||
3766 | 3697 | ||
3767 | if (!(log->l_iclog->ic_state & XLOG_STATE_IOERROR)) { | 3698 | if (!(log->l_iclog->ic_state & XLOG_STATE_IOERROR)) { |
3768 | ASSERT(!logerror); | 3699 | ASSERT(!logerror); |