diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 11:04:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 11:04:12 -0400 |
commit | 149b306089b88e186942a8d6647028ae6683aaf9 (patch) | |
tree | 1b7436034261947bae3efad41c55a91a8ef0f68d /fs/jbd2 | |
parent | b0ca4d0123608cfec73fc689c74295da89fc934e (diff) | |
parent | 0d606e2c9fccdd4e67febf1e2da500e1bfe9e045 (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o:
"Mostly performance and bug fixes, plus some cleanups. The one new
feature this merge window is a new ioctl EXT4_IOC_SWAP_BOOT which
allows installation of a hidden inode designed for boot loaders."
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (50 commits)
ext4: fix type-widening bug in inode table readahead code
ext4: add check for inodes_count overflow in new resize ioctl
ext4: fix Kconfig documentation for CONFIG_EXT4_DEBUG
ext4: fix online resizing for ext3-compat file systems
jbd2: trace when lock_buffer in do_get_write_access takes a long time
ext4: mark metadata blocks using bh flags
buffer: add BH_Prio and BH_Meta flags
ext4: mark all metadata I/O with REQ_META
ext4: fix readdir error in case inline_data+^dir_index.
ext4: fix readdir error in the case of inline_data+dir_index
jbd2: use kmem_cache_zalloc instead of kmem_cache_alloc/memset
ext4: mext_insert_extents should update extent block checksum
ext4: move quota initialization out of inode allocation transaction
ext4: reserve xattr index for Rich ACL support
jbd2: reduce journal_head size
ext4: clear buffer_uninit flag when submitting IO
ext4: use io_end for multiple bios
ext4: make ext4_bio_write_page() use BH_Async_Write flags
ext4: Use kstrtoul() instead of parse_strtoul()
ext4: defragmentation code cleanup
...
Diffstat (limited to 'fs/jbd2')
-rw-r--r-- | fs/jbd2/commit.c | 50 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 31 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 9 |
3 files changed, 67 insertions, 23 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 750c70148eff..0f53946f13c1 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -382,7 +382,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
382 | int space_left = 0; | 382 | int space_left = 0; |
383 | int first_tag = 0; | 383 | int first_tag = 0; |
384 | int tag_flag; | 384 | int tag_flag; |
385 | int i, to_free = 0; | 385 | int i; |
386 | int tag_bytes = journal_tag_bytes(journal); | 386 | int tag_bytes = journal_tag_bytes(journal); |
387 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | 387 | struct buffer_head *cbh = NULL; /* For transactional checksums */ |
388 | __u32 crc32_sum = ~0; | 388 | __u32 crc32_sum = ~0; |
@@ -1134,7 +1134,7 @@ restart_loop: | |||
1134 | journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; | 1134 | journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; |
1135 | spin_unlock(&journal->j_history_lock); | 1135 | spin_unlock(&journal->j_history_lock); |
1136 | 1136 | ||
1137 | commit_transaction->t_state = T_FINISHED; | 1137 | commit_transaction->t_state = T_COMMIT_CALLBACK; |
1138 | J_ASSERT(commit_transaction == journal->j_committing_transaction); | 1138 | J_ASSERT(commit_transaction == journal->j_committing_transaction); |
1139 | journal->j_commit_sequence = commit_transaction->t_tid; | 1139 | journal->j_commit_sequence = commit_transaction->t_tid; |
1140 | journal->j_committing_transaction = NULL; | 1140 | journal->j_committing_transaction = NULL; |
@@ -1149,38 +1149,44 @@ restart_loop: | |||
1149 | journal->j_average_commit_time*3) / 4; | 1149 | journal->j_average_commit_time*3) / 4; |
1150 | else | 1150 | else |
1151 | journal->j_average_commit_time = commit_time; | 1151 | journal->j_average_commit_time = commit_time; |
1152 | |||
1152 | write_unlock(&journal->j_state_lock); | 1153 | write_unlock(&journal->j_state_lock); |
1153 | 1154 | ||
1154 | if (commit_transaction->t_checkpoint_list == NULL && | 1155 | if (journal->j_checkpoint_transactions == NULL) { |
1155 | commit_transaction->t_checkpoint_io_list == NULL) { | 1156 | journal->j_checkpoint_transactions = commit_transaction; |
1156 | __jbd2_journal_drop_transaction(journal, commit_transaction); | 1157 | commit_transaction->t_cpnext = commit_transaction; |
1157 | to_free = 1; | 1158 | commit_transaction->t_cpprev = commit_transaction; |
1158 | } else { | 1159 | } else { |
1159 | if (journal->j_checkpoint_transactions == NULL) { | 1160 | commit_transaction->t_cpnext = |
1160 | journal->j_checkpoint_transactions = commit_transaction; | 1161 | journal->j_checkpoint_transactions; |
1161 | commit_transaction->t_cpnext = commit_transaction; | 1162 | commit_transaction->t_cpprev = |
1162 | commit_transaction->t_cpprev = commit_transaction; | 1163 | commit_transaction->t_cpnext->t_cpprev; |
1163 | } else { | 1164 | commit_transaction->t_cpnext->t_cpprev = |
1164 | commit_transaction->t_cpnext = | 1165 | commit_transaction; |
1165 | journal->j_checkpoint_transactions; | 1166 | commit_transaction->t_cpprev->t_cpnext = |
1166 | commit_transaction->t_cpprev = | ||
1167 | commit_transaction->t_cpnext->t_cpprev; | ||
1168 | commit_transaction->t_cpnext->t_cpprev = | ||
1169 | commit_transaction; | ||
1170 | commit_transaction->t_cpprev->t_cpnext = | ||
1171 | commit_transaction; | 1167 | commit_transaction; |
1172 | } | ||
1173 | } | 1168 | } |
1174 | spin_unlock(&journal->j_list_lock); | 1169 | spin_unlock(&journal->j_list_lock); |
1175 | 1170 | /* Drop all spin_locks because commit_callback may be block. | |
1171 | * __journal_remove_checkpoint() can not destroy transaction | ||
1172 | * under us because it is not marked as T_FINISHED yet */ | ||
1176 | if (journal->j_commit_callback) | 1173 | if (journal->j_commit_callback) |
1177 | journal->j_commit_callback(journal, commit_transaction); | 1174 | journal->j_commit_callback(journal, commit_transaction); |
1178 | 1175 | ||
1179 | trace_jbd2_end_commit(journal, commit_transaction); | 1176 | trace_jbd2_end_commit(journal, commit_transaction); |
1180 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", | 1177 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", |
1181 | journal->j_commit_sequence, journal->j_tail_sequence); | 1178 | journal->j_commit_sequence, journal->j_tail_sequence); |
1182 | if (to_free) | ||
1183 | jbd2_journal_free_transaction(commit_transaction); | ||
1184 | 1179 | ||
1180 | write_lock(&journal->j_state_lock); | ||
1181 | spin_lock(&journal->j_list_lock); | ||
1182 | commit_transaction->t_state = T_FINISHED; | ||
1183 | /* Recheck checkpoint lists after j_list_lock was dropped */ | ||
1184 | if (commit_transaction->t_checkpoint_list == NULL && | ||
1185 | commit_transaction->t_checkpoint_io_list == NULL) { | ||
1186 | __jbd2_journal_drop_transaction(journal, commit_transaction); | ||
1187 | jbd2_journal_free_transaction(commit_transaction); | ||
1188 | } | ||
1189 | spin_unlock(&journal->j_list_lock); | ||
1190 | write_unlock(&journal->j_state_lock); | ||
1185 | wake_up(&journal->j_wait_done_commit); | 1191 | wake_up(&journal->j_wait_done_commit); |
1186 | } | 1192 | } |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 8b220f1ab54f..f6c5ba027f4f 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -708,6 +708,37 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid) | |||
708 | } | 708 | } |
709 | 709 | ||
710 | /* | 710 | /* |
711 | * When this function returns the transaction corresponding to tid | ||
712 | * will be completed. If the transaction has currently running, start | ||
713 | * committing that transaction before waiting for it to complete. If | ||
714 | * the transaction id is stale, it is by definition already completed, | ||
715 | * so just return SUCCESS. | ||
716 | */ | ||
717 | int jbd2_complete_transaction(journal_t *journal, tid_t tid) | ||
718 | { | ||
719 | int need_to_wait = 1; | ||
720 | |||
721 | read_lock(&journal->j_state_lock); | ||
722 | if (journal->j_running_transaction && | ||
723 | journal->j_running_transaction->t_tid == tid) { | ||
724 | if (journal->j_commit_request != tid) { | ||
725 | /* transaction not yet started, so request it */ | ||
726 | read_unlock(&journal->j_state_lock); | ||
727 | jbd2_log_start_commit(journal, tid); | ||
728 | goto wait_commit; | ||
729 | } | ||
730 | } else if (!(journal->j_committing_transaction && | ||
731 | journal->j_committing_transaction->t_tid == tid)) | ||
732 | need_to_wait = 0; | ||
733 | read_unlock(&journal->j_state_lock); | ||
734 | if (!need_to_wait) | ||
735 | return 0; | ||
736 | wait_commit: | ||
737 | return jbd2_log_wait_commit(journal, tid); | ||
738 | } | ||
739 | EXPORT_SYMBOL(jbd2_complete_transaction); | ||
740 | |||
741 | /* | ||
711 | * Log buffer allocation routines: | 742 | * Log buffer allocation routines: |
712 | */ | 743 | */ |
713 | 744 | ||
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 325bc019ed88..10f524c59ea8 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -332,7 +332,6 @@ static handle_t *new_handle(int nblocks) | |||
332 | handle_t *handle = jbd2_alloc_handle(GFP_NOFS); | 332 | handle_t *handle = jbd2_alloc_handle(GFP_NOFS); |
333 | if (!handle) | 333 | if (!handle) |
334 | return NULL; | 334 | return NULL; |
335 | memset(handle, 0, sizeof(*handle)); | ||
336 | handle->h_buffer_credits = nblocks; | 335 | handle->h_buffer_credits = nblocks; |
337 | handle->h_ref = 1; | 336 | handle->h_ref = 1; |
338 | 337 | ||
@@ -640,6 +639,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, | |||
640 | int error; | 639 | int error; |
641 | char *frozen_buffer = NULL; | 640 | char *frozen_buffer = NULL; |
642 | int need_copy = 0; | 641 | int need_copy = 0; |
642 | unsigned long start_lock, time_lock; | ||
643 | 643 | ||
644 | if (is_handle_aborted(handle)) | 644 | if (is_handle_aborted(handle)) |
645 | return -EROFS; | 645 | return -EROFS; |
@@ -655,9 +655,16 @@ repeat: | |||
655 | 655 | ||
656 | /* @@@ Need to check for errors here at some point. */ | 656 | /* @@@ Need to check for errors here at some point. */ |
657 | 657 | ||
658 | start_lock = jiffies; | ||
658 | lock_buffer(bh); | 659 | lock_buffer(bh); |
659 | jbd_lock_bh_state(bh); | 660 | jbd_lock_bh_state(bh); |
660 | 661 | ||
662 | /* If it takes too long to lock the buffer, trace it */ | ||
663 | time_lock = jbd2_time_diff(start_lock, jiffies); | ||
664 | if (time_lock > HZ/10) | ||
665 | trace_jbd2_lock_buffer_stall(bh->b_bdev->bd_dev, | ||
666 | jiffies_to_msecs(time_lock)); | ||
667 | |||
661 | /* We now hold the buffer lock so it is safe to query the buffer | 668 | /* We now hold the buffer lock so it is safe to query the buffer |
662 | * state. Is the buffer dirty? | 669 | * state. Is the buffer dirty? |
663 | * | 670 | * |