diff options
Diffstat (limited to 'fs/jbd2')
| -rw-r--r-- | fs/jbd2/Kconfig | 33 | ||||
| -rw-r--r-- | fs/jbd2/checkpoint.c | 71 | ||||
| -rw-r--r-- | fs/jbd2/commit.c | 35 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 103 | ||||
| -rw-r--r-- | fs/jbd2/recovery.c | 7 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 1 |
6 files changed, 182 insertions, 68 deletions
diff --git a/fs/jbd2/Kconfig b/fs/jbd2/Kconfig new file mode 100644 index 00000000000..f32f346f4b0 --- /dev/null +++ b/fs/jbd2/Kconfig | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | config JBD2 | ||
| 2 | tristate | ||
| 3 | select CRC32 | ||
| 4 | help | ||
| 5 | This is a generic journaling layer for block devices that support | ||
| 6 | both 32-bit and 64-bit block numbers. It is currently used by | ||
| 7 | the ext4 and OCFS2 filesystems, but it could also be used to add | ||
| 8 | journal support to other file systems or block devices such | ||
| 9 | as RAID or LVM. | ||
| 10 | |||
| 11 | If you are using ext4 or OCFS2, you need to say Y here. | ||
| 12 | If you are not using ext4 or OCFS2 then you will | ||
| 13 | probably want to say N. | ||
| 14 | |||
| 15 | To compile this device as a module, choose M here. The module will be | ||
| 16 | called jbd2. If you are compiling ext4 or OCFS2 into the kernel, | ||
| 17 | you cannot compile this code as a module. | ||
| 18 | |||
| 19 | config JBD2_DEBUG | ||
| 20 | bool "JBD2 (ext4) debugging support" | ||
| 21 | depends on JBD2 && DEBUG_FS | ||
| 22 | help | ||
| 23 | If you are using the ext4 journaled file system (or | ||
| 24 | potentially any other filesystem/device using JBD2), this option | ||
| 25 | allows you to enable debugging output while the system is running, | ||
| 26 | in order to help track down any problems you are having. | ||
| 27 | By default, the debugging output will be turned off. | ||
| 28 | |||
| 29 | If you select Y here, then you will be able to turn on debugging | ||
| 30 | with "echo N > /sys/kernel/debug/jbd2/jbd2-debug", where N is a | ||
| 31 | number between 1 and 5. The higher the number, the more debugging | ||
| 32 | output is generated. To turn debugging off again, do | ||
| 33 | "echo 0 > /sys/kernel/debug/jbd2/jbd2-debug". | ||
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 91389c8aee8..9203c3332f1 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
| 21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
| 22 | #include <linux/jbd2.h> | 22 | #include <linux/jbd2.h> |
| 23 | #include <linux/marker.h> | ||
| 23 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 25 | 26 | ||
| @@ -93,7 +94,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
| 93 | int ret = 0; | 94 | int ret = 0; |
| 94 | struct buffer_head *bh = jh2bh(jh); | 95 | struct buffer_head *bh = jh2bh(jh); |
| 95 | 96 | ||
| 96 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { | 97 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && |
| 98 | !buffer_dirty(bh) && !buffer_write_io_error(bh)) { | ||
| 97 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 99 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
| 98 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; | 100 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; |
| 99 | jbd_unlock_bh_state(bh); | 101 | jbd_unlock_bh_state(bh); |
| @@ -126,14 +128,29 @@ void __jbd2_log_wait_for_space(journal_t *journal) | |||
| 126 | 128 | ||
| 127 | /* | 129 | /* |
| 128 | * Test again, another process may have checkpointed while we | 130 | * Test again, another process may have checkpointed while we |
| 129 | * were waiting for the checkpoint lock | 131 | * were waiting for the checkpoint lock. If there are no |
| 132 | * outstanding transactions there is nothing to checkpoint and | ||
| 133 | * we can't make progress. Abort the journal in this case. | ||
| 130 | */ | 134 | */ |
| 131 | spin_lock(&journal->j_state_lock); | 135 | spin_lock(&journal->j_state_lock); |
| 136 | spin_lock(&journal->j_list_lock); | ||
| 132 | nblocks = jbd_space_needed(journal); | 137 | nblocks = jbd_space_needed(journal); |
| 133 | if (__jbd2_log_space_left(journal) < nblocks) { | 138 | if (__jbd2_log_space_left(journal) < nblocks) { |
| 139 | int chkpt = journal->j_checkpoint_transactions != NULL; | ||
| 140 | |||
| 141 | spin_unlock(&journal->j_list_lock); | ||
| 134 | spin_unlock(&journal->j_state_lock); | 142 | spin_unlock(&journal->j_state_lock); |
| 135 | jbd2_log_do_checkpoint(journal); | 143 | if (chkpt) { |
| 144 | jbd2_log_do_checkpoint(journal); | ||
| 145 | } else { | ||
| 146 | printk(KERN_ERR "%s: no transactions\n", | ||
| 147 | __func__); | ||
| 148 | jbd2_journal_abort(journal, 0); | ||
| 149 | } | ||
| 150 | |||
| 136 | spin_lock(&journal->j_state_lock); | 151 | spin_lock(&journal->j_state_lock); |
| 152 | } else { | ||
| 153 | spin_unlock(&journal->j_list_lock); | ||
| 137 | } | 154 | } |
| 138 | mutex_unlock(&journal->j_checkpoint_mutex); | 155 | mutex_unlock(&journal->j_checkpoint_mutex); |
| 139 | } | 156 | } |
| @@ -160,21 +177,25 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) | |||
| 160 | * buffers. Note that we take the buffers in the opposite ordering | 177 | * buffers. Note that we take the buffers in the opposite ordering |
| 161 | * from the one in which they were submitted for IO. | 178 | * from the one in which they were submitted for IO. |
| 162 | * | 179 | * |
| 180 | * Return 0 on success, and return <0 if some buffers have failed | ||
| 181 | * to be written out. | ||
| 182 | * | ||
| 163 | * Called with j_list_lock held. | 183 | * Called with j_list_lock held. |
| 164 | */ | 184 | */ |
| 165 | static void __wait_cp_io(journal_t *journal, transaction_t *transaction) | 185 | static int __wait_cp_io(journal_t *journal, transaction_t *transaction) |
| 166 | { | 186 | { |
| 167 | struct journal_head *jh; | 187 | struct journal_head *jh; |
| 168 | struct buffer_head *bh; | 188 | struct buffer_head *bh; |
| 169 | tid_t this_tid; | 189 | tid_t this_tid; |
| 170 | int released = 0; | 190 | int released = 0; |
| 191 | int ret = 0; | ||
| 171 | 192 | ||
| 172 | this_tid = transaction->t_tid; | 193 | this_tid = transaction->t_tid; |
| 173 | restart: | 194 | restart: |
| 174 | /* Did somebody clean up the transaction in the meanwhile? */ | 195 | /* Did somebody clean up the transaction in the meanwhile? */ |
| 175 | if (journal->j_checkpoint_transactions != transaction || | 196 | if (journal->j_checkpoint_transactions != transaction || |
| 176 | transaction->t_tid != this_tid) | 197 | transaction->t_tid != this_tid) |
| 177 | return; | 198 | return ret; |
| 178 | while (!released && transaction->t_checkpoint_io_list) { | 199 | while (!released && transaction->t_checkpoint_io_list) { |
| 179 | jh = transaction->t_checkpoint_io_list; | 200 | jh = transaction->t_checkpoint_io_list; |
| 180 | bh = jh2bh(jh); | 201 | bh = jh2bh(jh); |
| @@ -194,6 +215,9 @@ restart: | |||
| 194 | spin_lock(&journal->j_list_lock); | 215 | spin_lock(&journal->j_list_lock); |
| 195 | goto restart; | 216 | goto restart; |
| 196 | } | 217 | } |
| 218 | if (unlikely(buffer_write_io_error(bh))) | ||
| 219 | ret = -EIO; | ||
| 220 | |||
| 197 | /* | 221 | /* |
| 198 | * Now in whatever state the buffer currently is, we know that | 222 | * Now in whatever state the buffer currently is, we know that |
| 199 | * it has been written out and so we can drop it from the list | 223 | * it has been written out and so we can drop it from the list |
| @@ -203,6 +227,8 @@ restart: | |||
| 203 | jbd2_journal_remove_journal_head(bh); | 227 | jbd2_journal_remove_journal_head(bh); |
| 204 | __brelse(bh); | 228 | __brelse(bh); |
| 205 | } | 229 | } |
| 230 | |||
| 231 | return ret; | ||
| 206 | } | 232 | } |
| 207 | 233 | ||
| 208 | #define NR_BATCH 64 | 234 | #define NR_BATCH 64 |
| @@ -226,7 +252,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) | |||
| 226 | * Try to flush one buffer from the checkpoint list to disk. | 252 | * Try to flush one buffer from the checkpoint list to disk. |
| 227 | * | 253 | * |
| 228 | * Return 1 if something happened which requires us to abort the current | 254 | * Return 1 if something happened which requires us to abort the current |
| 229 | * scan of the checkpoint list. | 255 | * scan of the checkpoint list. Return <0 if the buffer has failed to |
| 256 | * be written out. | ||
| 230 | * | 257 | * |
| 231 | * Called with j_list_lock held and drops it if 1 is returned | 258 | * Called with j_list_lock held and drops it if 1 is returned |
| 232 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it | 259 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it |
| @@ -258,6 +285,9 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
| 258 | jbd2_log_wait_commit(journal, tid); | 285 | jbd2_log_wait_commit(journal, tid); |
| 259 | ret = 1; | 286 | ret = 1; |
| 260 | } else if (!buffer_dirty(bh)) { | 287 | } else if (!buffer_dirty(bh)) { |
| 288 | ret = 1; | ||
| 289 | if (unlikely(buffer_write_io_error(bh))) | ||
| 290 | ret = -EIO; | ||
| 261 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); | 291 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); |
| 262 | BUFFER_TRACE(bh, "remove from checkpoint"); | 292 | BUFFER_TRACE(bh, "remove from checkpoint"); |
| 263 | __jbd2_journal_remove_checkpoint(jh); | 293 | __jbd2_journal_remove_checkpoint(jh); |
| @@ -265,7 +295,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
| 265 | jbd_unlock_bh_state(bh); | 295 | jbd_unlock_bh_state(bh); |
| 266 | jbd2_journal_remove_journal_head(bh); | 296 | jbd2_journal_remove_journal_head(bh); |
| 267 | __brelse(bh); | 297 | __brelse(bh); |
| 268 | ret = 1; | ||
| 269 | } else { | 298 | } else { |
| 270 | /* | 299 | /* |
| 271 | * Important: we are about to write the buffer, and | 300 | * Important: we are about to write the buffer, and |
| @@ -298,6 +327,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
| 298 | * to disk. We submit larger chunks of data at once. | 327 | * to disk. We submit larger chunks of data at once. |
| 299 | * | 328 | * |
| 300 | * The journal should be locked before calling this function. | 329 | * The journal should be locked before calling this function. |
| 330 | * Called with j_checkpoint_mutex held. | ||
| 301 | */ | 331 | */ |
| 302 | int jbd2_log_do_checkpoint(journal_t *journal) | 332 | int jbd2_log_do_checkpoint(journal_t *journal) |
| 303 | { | 333 | { |
| @@ -313,6 +343,8 @@ int jbd2_log_do_checkpoint(journal_t *journal) | |||
| 313 | * journal straight away. | 343 | * journal straight away. |
| 314 | */ | 344 | */ |
| 315 | result = jbd2_cleanup_journal_tail(journal); | 345 | result = jbd2_cleanup_journal_tail(journal); |
| 346 | trace_mark(jbd2_checkpoint, "dev %s need_checkpoint %d", | ||
| 347 | journal->j_devname, result); | ||
| 316 | jbd_debug(1, "cleanup_journal_tail returned %d\n", result); | 348 | jbd_debug(1, "cleanup_journal_tail returned %d\n", result); |
| 317 | if (result <= 0) | 349 | if (result <= 0) |
| 318 | return result; | 350 | return result; |
| @@ -321,6 +353,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) | |||
| 321 | * OK, we need to start writing disk blocks. Take one transaction | 353 | * OK, we need to start writing disk blocks. Take one transaction |
| 322 | * and write it. | 354 | * and write it. |
| 323 | */ | 355 | */ |
| 356 | result = 0; | ||
| 324 | spin_lock(&journal->j_list_lock); | 357 | spin_lock(&journal->j_list_lock); |
| 325 | if (!journal->j_checkpoint_transactions) | 358 | if (!journal->j_checkpoint_transactions) |
| 326 | goto out; | 359 | goto out; |
| @@ -339,7 +372,7 @@ restart: | |||
| 339 | int batch_count = 0; | 372 | int batch_count = 0; |
| 340 | struct buffer_head *bhs[NR_BATCH]; | 373 | struct buffer_head *bhs[NR_BATCH]; |
| 341 | struct journal_head *jh; | 374 | struct journal_head *jh; |
| 342 | int retry = 0; | 375 | int retry = 0, err; |
| 343 | 376 | ||
| 344 | while (!retry && transaction->t_checkpoint_list) { | 377 | while (!retry && transaction->t_checkpoint_list) { |
| 345 | struct buffer_head *bh; | 378 | struct buffer_head *bh; |
| @@ -353,6 +386,8 @@ restart: | |||
| 353 | } | 386 | } |
| 354 | retry = __process_buffer(journal, jh, bhs, &batch_count, | 387 | retry = __process_buffer(journal, jh, bhs, &batch_count, |
| 355 | transaction); | 388 | transaction); |
| 389 | if (retry < 0 && !result) | ||
| 390 | result = retry; | ||
| 356 | if (!retry && (need_resched() || | 391 | if (!retry && (need_resched() || |
| 357 | spin_needbreak(&journal->j_list_lock))) { | 392 | spin_needbreak(&journal->j_list_lock))) { |
| 358 | spin_unlock(&journal->j_list_lock); | 393 | spin_unlock(&journal->j_list_lock); |
| @@ -377,14 +412,18 @@ restart: | |||
| 377 | * Now we have cleaned up the first transaction's checkpoint | 412 | * Now we have cleaned up the first transaction's checkpoint |
| 378 | * list. Let's clean up the second one | 413 | * list. Let's clean up the second one |
| 379 | */ | 414 | */ |
| 380 | __wait_cp_io(journal, transaction); | 415 | err = __wait_cp_io(journal, transaction); |
| 416 | if (!result) | ||
| 417 | result = err; | ||
| 381 | } | 418 | } |
| 382 | out: | 419 | out: |
| 383 | spin_unlock(&journal->j_list_lock); | 420 | spin_unlock(&journal->j_list_lock); |
| 384 | result = jbd2_cleanup_journal_tail(journal); | ||
| 385 | if (result < 0) | 421 | if (result < 0) |
| 386 | return result; | 422 | jbd2_journal_abort(journal, result); |
| 387 | return 0; | 423 | else |
| 424 | result = jbd2_cleanup_journal_tail(journal); | ||
| 425 | |||
| 426 | return (result < 0) ? result : 0; | ||
| 388 | } | 427 | } |
| 389 | 428 | ||
| 390 | /* | 429 | /* |
| @@ -400,8 +439,9 @@ out: | |||
| 400 | * This is the only part of the journaling code which really needs to be | 439 | * This is the only part of the journaling code which really needs to be |
| 401 | * aware of transaction aborts. Checkpointing involves writing to the | 440 | * aware of transaction aborts. Checkpointing involves writing to the |
| 402 | * main filesystem area rather than to the journal, so it can proceed | 441 | * main filesystem area rather than to the journal, so it can proceed |
| 403 | * even in abort state, but we must not update the journal superblock if | 442 | * even in abort state, but we must not update the super block if |
| 404 | * we have an abort error outstanding. | 443 | * checkpointing may have failed. Otherwise, we would lose some metadata |
| 444 | * buffers which should be written-back to the filesystem. | ||
| 405 | */ | 445 | */ |
| 406 | 446 | ||
| 407 | int jbd2_cleanup_journal_tail(journal_t *journal) | 447 | int jbd2_cleanup_journal_tail(journal_t *journal) |
| @@ -410,6 +450,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
| 410 | tid_t first_tid; | 450 | tid_t first_tid; |
| 411 | unsigned long blocknr, freed; | 451 | unsigned long blocknr, freed; |
| 412 | 452 | ||
| 453 | if (is_journal_aborted(journal)) | ||
| 454 | return 1; | ||
| 455 | |||
| 413 | /* OK, work out the oldest transaction remaining in the log, and | 456 | /* OK, work out the oldest transaction remaining in the log, and |
| 414 | * the log block it starts at. | 457 | * the log block it starts at. |
| 415 | * | 458 | * |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index f2ad061e95e..8b119e16aa3 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
| 17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
| 18 | #include <linux/jbd2.h> | 18 | #include <linux/jbd2.h> |
| 19 | #include <linux/marker.h> | ||
| 19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
| 20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 21 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
| @@ -126,8 +127,7 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 126 | 127 | ||
| 127 | JBUFFER_TRACE(descriptor, "submit commit block"); | 128 | JBUFFER_TRACE(descriptor, "submit commit block"); |
| 128 | lock_buffer(bh); | 129 | lock_buffer(bh); |
| 129 | get_bh(bh); | 130 | clear_buffer_dirty(bh); |
| 130 | set_buffer_dirty(bh); | ||
| 131 | set_buffer_uptodate(bh); | 131 | set_buffer_uptodate(bh); |
| 132 | bh->b_end_io = journal_end_buffer_io_sync; | 132 | bh->b_end_io = journal_end_buffer_io_sync; |
| 133 | 133 | ||
| @@ -147,12 +147,9 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 147 | * to remember if we sent a barrier request | 147 | * to remember if we sent a barrier request |
| 148 | */ | 148 | */ |
| 149 | if (ret == -EOPNOTSUPP && barrier_done) { | 149 | if (ret == -EOPNOTSUPP && barrier_done) { |
| 150 | char b[BDEVNAME_SIZE]; | ||
| 151 | |||
| 152 | printk(KERN_WARNING | 150 | printk(KERN_WARNING |
| 153 | "JBD: barrier-based sync failed on %s - " | 151 | "JBD: barrier-based sync failed on %s - " |
| 154 | "disabling barriers\n", | 152 | "disabling barriers\n", journal->j_devname); |
| 155 | bdevname(journal->j_dev, b)); | ||
| 156 | spin_lock(&journal->j_state_lock); | 153 | spin_lock(&journal->j_state_lock); |
| 157 | journal->j_flags &= ~JBD2_BARRIER; | 154 | journal->j_flags &= ~JBD2_BARRIER; |
| 158 | spin_unlock(&journal->j_state_lock); | 155 | spin_unlock(&journal->j_state_lock); |
| @@ -160,7 +157,7 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 160 | /* And try again, without the barrier */ | 157 | /* And try again, without the barrier */ |
| 161 | lock_buffer(bh); | 158 | lock_buffer(bh); |
| 162 | set_buffer_uptodate(bh); | 159 | set_buffer_uptodate(bh); |
| 163 | set_buffer_dirty(bh); | 160 | clear_buffer_dirty(bh); |
| 164 | ret = submit_bh(WRITE, bh); | 161 | ret = submit_bh(WRITE, bh); |
| 165 | } | 162 | } |
| 166 | *cbh = bh; | 163 | *cbh = bh; |
| @@ -371,6 +368,8 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 371 | commit_transaction = journal->j_running_transaction; | 368 | commit_transaction = journal->j_running_transaction; |
| 372 | J_ASSERT(commit_transaction->t_state == T_RUNNING); | 369 | J_ASSERT(commit_transaction->t_state == T_RUNNING); |
| 373 | 370 | ||
| 371 | trace_mark(jbd2_start_commit, "dev %s transaction %d", | ||
| 372 | journal->j_devname, commit_transaction->t_tid); | ||
| 374 | jbd_debug(1, "JBD: starting commit of transaction %d\n", | 373 | jbd_debug(1, "JBD: starting commit of transaction %d\n", |
| 375 | commit_transaction->t_tid); | 374 | commit_transaction->t_tid); |
| 376 | 375 | ||
| @@ -505,9 +504,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 505 | jh = commit_transaction->t_buffers; | 504 | jh = commit_transaction->t_buffers; |
| 506 | 505 | ||
| 507 | /* If we're in abort mode, we just un-journal the buffer and | 506 | /* If we're in abort mode, we just un-journal the buffer and |
| 508 | release it for background writing. */ | 507 | release it. */ |
| 509 | 508 | ||
| 510 | if (is_journal_aborted(journal)) { | 509 | if (is_journal_aborted(journal)) { |
| 510 | clear_buffer_jbddirty(jh2bh(jh)); | ||
| 511 | JBUFFER_TRACE(jh, "journal is aborting: refile"); | 511 | JBUFFER_TRACE(jh, "journal is aborting: refile"); |
| 512 | jbd2_journal_refile_buffer(journal, jh); | 512 | jbd2_journal_refile_buffer(journal, jh); |
| 513 | /* If that was the last one, we need to clean up | 513 | /* If that was the last one, we need to clean up |
| @@ -681,11 +681,11 @@ start_journal_io: | |||
| 681 | */ | 681 | */ |
| 682 | err = journal_finish_inode_data_buffers(journal, commit_transaction); | 682 | err = journal_finish_inode_data_buffers(journal, commit_transaction); |
| 683 | if (err) { | 683 | if (err) { |
| 684 | char b[BDEVNAME_SIZE]; | ||
| 685 | |||
| 686 | printk(KERN_WARNING | 684 | printk(KERN_WARNING |
| 687 | "JBD2: Detected IO errors while flushing file data " | 685 | "JBD2: Detected IO errors while flushing file data " |
| 688 | "on %s\n", bdevname(journal->j_fs_dev, b)); | 686 | "on %s\n", journal->j_devname); |
| 687 | if (journal->j_flags & JBD2_ABORT_ON_SYNCDATA_ERR) | ||
| 688 | jbd2_journal_abort(journal, err); | ||
| 689 | err = 0; | 689 | err = 0; |
| 690 | } | 690 | } |
| 691 | 691 | ||
| @@ -786,6 +786,9 @@ wait_for_iobuf: | |||
| 786 | /* AKPM: bforget here */ | 786 | /* AKPM: bforget here */ |
| 787 | } | 787 | } |
| 788 | 788 | ||
| 789 | if (err) | ||
| 790 | jbd2_journal_abort(journal, err); | ||
| 791 | |||
| 789 | jbd_debug(3, "JBD: commit phase 5\n"); | 792 | jbd_debug(3, "JBD: commit phase 5\n"); |
| 790 | 793 | ||
| 791 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 794 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, |
| @@ -884,6 +887,8 @@ restart_loop: | |||
| 884 | if (buffer_jbddirty(bh)) { | 887 | if (buffer_jbddirty(bh)) { |
| 885 | JBUFFER_TRACE(jh, "add to new checkpointing trans"); | 888 | JBUFFER_TRACE(jh, "add to new checkpointing trans"); |
| 886 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); | 889 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); |
| 890 | if (is_journal_aborted(journal)) | ||
| 891 | clear_buffer_jbddirty(bh); | ||
| 887 | JBUFFER_TRACE(jh, "refile for checkpoint writeback"); | 892 | JBUFFER_TRACE(jh, "refile for checkpoint writeback"); |
| 888 | __jbd2_journal_refile_buffer(jh); | 893 | __jbd2_journal_refile_buffer(jh); |
| 889 | jbd_unlock_bh_state(bh); | 894 | jbd_unlock_bh_state(bh); |
| @@ -990,6 +995,12 @@ restart_loop: | |||
| 990 | } | 995 | } |
| 991 | spin_unlock(&journal->j_list_lock); | 996 | spin_unlock(&journal->j_list_lock); |
| 992 | 997 | ||
| 998 | if (journal->j_commit_callback) | ||
| 999 | journal->j_commit_callback(journal, commit_transaction); | ||
| 1000 | |||
| 1001 | trace_mark(jbd2_end_commit, "dev %s transaction %d head %d", | ||
| 1002 | journal->j_devname, commit_transaction->t_tid, | ||
| 1003 | journal->j_tail_sequence); | ||
| 993 | jbd_debug(1, "JBD: commit %d complete, head %d\n", | 1004 | jbd_debug(1, "JBD: commit %d complete, head %d\n", |
| 994 | journal->j_commit_sequence, journal->j_tail_sequence); | 1005 | journal->j_commit_sequence, journal->j_tail_sequence); |
| 995 | 1006 | ||
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 8207a01c4ed..783de118de9 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -597,13 +597,9 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, | |||
| 597 | if (ret) | 597 | if (ret) |
| 598 | *retp = ret; | 598 | *retp = ret; |
| 599 | else { | 599 | else { |
| 600 | char b[BDEVNAME_SIZE]; | ||
| 601 | |||
| 602 | printk(KERN_ALERT "%s: journal block not found " | 600 | printk(KERN_ALERT "%s: journal block not found " |
| 603 | "at offset %lu on %s\n", | 601 | "at offset %lu on %s\n", |
| 604 | __func__, | 602 | __func__, blocknr, journal->j_devname); |
| 605 | blocknr, | ||
| 606 | bdevname(journal->j_dev, b)); | ||
| 607 | err = -EIO; | 603 | err = -EIO; |
| 608 | __journal_abort_soft(journal, err); | 604 | __journal_abort_soft(journal, err); |
| 609 | } | 605 | } |
| @@ -901,10 +897,7 @@ static struct proc_dir_entry *proc_jbd2_stats; | |||
| 901 | 897 | ||
| 902 | static void jbd2_stats_proc_init(journal_t *journal) | 898 | static void jbd2_stats_proc_init(journal_t *journal) |
| 903 | { | 899 | { |
| 904 | char name[BDEVNAME_SIZE]; | 900 | journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats); |
| 905 | |||
| 906 | bdevname(journal->j_dev, name); | ||
| 907 | journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats); | ||
| 908 | if (journal->j_proc_entry) { | 901 | if (journal->j_proc_entry) { |
| 909 | proc_create_data("history", S_IRUGO, journal->j_proc_entry, | 902 | proc_create_data("history", S_IRUGO, journal->j_proc_entry, |
| 910 | &jbd2_seq_history_fops, journal); | 903 | &jbd2_seq_history_fops, journal); |
| @@ -915,12 +908,9 @@ static void jbd2_stats_proc_init(journal_t *journal) | |||
| 915 | 908 | ||
| 916 | static void jbd2_stats_proc_exit(journal_t *journal) | 909 | static void jbd2_stats_proc_exit(journal_t *journal) |
| 917 | { | 910 | { |
| 918 | char name[BDEVNAME_SIZE]; | ||
| 919 | |||
| 920 | bdevname(journal->j_dev, name); | ||
| 921 | remove_proc_entry("info", journal->j_proc_entry); | 911 | remove_proc_entry("info", journal->j_proc_entry); |
| 922 | remove_proc_entry("history", journal->j_proc_entry); | 912 | remove_proc_entry("history", journal->j_proc_entry); |
| 923 | remove_proc_entry(name, proc_jbd2_stats); | 913 | remove_proc_entry(journal->j_devname, proc_jbd2_stats); |
| 924 | } | 914 | } |
| 925 | 915 | ||
| 926 | static void journal_init_stats(journal_t *journal) | 916 | static void journal_init_stats(journal_t *journal) |
| @@ -1018,6 +1008,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
| 1018 | { | 1008 | { |
| 1019 | journal_t *journal = journal_init_common(); | 1009 | journal_t *journal = journal_init_common(); |
| 1020 | struct buffer_head *bh; | 1010 | struct buffer_head *bh; |
| 1011 | char *p; | ||
| 1021 | int n; | 1012 | int n; |
| 1022 | 1013 | ||
| 1023 | if (!journal) | 1014 | if (!journal) |
| @@ -1039,6 +1030,10 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
| 1039 | journal->j_fs_dev = fs_dev; | 1030 | journal->j_fs_dev = fs_dev; |
| 1040 | journal->j_blk_offset = start; | 1031 | journal->j_blk_offset = start; |
| 1041 | journal->j_maxlen = len; | 1032 | journal->j_maxlen = len; |
| 1033 | bdevname(journal->j_dev, journal->j_devname); | ||
| 1034 | p = journal->j_devname; | ||
| 1035 | while ((p = strchr(p, '/'))) | ||
| 1036 | *p = '!'; | ||
| 1042 | jbd2_stats_proc_init(journal); | 1037 | jbd2_stats_proc_init(journal); |
| 1043 | 1038 | ||
| 1044 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | 1039 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); |
| @@ -1061,6 +1056,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1061 | { | 1056 | { |
| 1062 | struct buffer_head *bh; | 1057 | struct buffer_head *bh; |
| 1063 | journal_t *journal = journal_init_common(); | 1058 | journal_t *journal = journal_init_common(); |
| 1059 | char *p; | ||
| 1064 | int err; | 1060 | int err; |
| 1065 | int n; | 1061 | int n; |
| 1066 | unsigned long long blocknr; | 1062 | unsigned long long blocknr; |
| @@ -1070,6 +1066,12 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1070 | 1066 | ||
| 1071 | journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev; | 1067 | journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev; |
| 1072 | journal->j_inode = inode; | 1068 | journal->j_inode = inode; |
| 1069 | bdevname(journal->j_dev, journal->j_devname); | ||
| 1070 | p = journal->j_devname; | ||
| 1071 | while ((p = strchr(p, '/'))) | ||
| 1072 | *p = '!'; | ||
| 1073 | p = journal->j_devname + strlen(journal->j_devname); | ||
| 1074 | sprintf(p, ":%lu", journal->j_inode->i_ino); | ||
| 1073 | jbd_debug(1, | 1075 | jbd_debug(1, |
| 1074 | "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n", | 1076 | "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n", |
| 1075 | journal, inode->i_sb->s_id, inode->i_ino, | 1077 | journal, inode->i_sb->s_id, inode->i_ino, |
| @@ -1253,6 +1255,22 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) | |||
| 1253 | goto out; | 1255 | goto out; |
| 1254 | } | 1256 | } |
| 1255 | 1257 | ||
| 1258 | if (buffer_write_io_error(bh)) { | ||
| 1259 | /* | ||
| 1260 | * Oh, dear. A previous attempt to write the journal | ||
| 1261 | * superblock failed. This could happen because the | ||
| 1262 | * USB device was yanked out. Or it could happen to | ||
| 1263 | * be a transient write error and maybe the block will | ||
| 1264 | * be remapped. Nothing we can do but to retry the | ||
| 1265 | * write and hope for the best. | ||
| 1266 | */ | ||
| 1267 | printk(KERN_ERR "JBD2: previous I/O error detected " | ||
| 1268 | "for journal superblock update for %s.\n", | ||
| 1269 | journal->j_devname); | ||
| 1270 | clear_buffer_write_io_error(bh); | ||
| 1271 | set_buffer_uptodate(bh); | ||
| 1272 | } | ||
| 1273 | |||
| 1256 | spin_lock(&journal->j_state_lock); | 1274 | spin_lock(&journal->j_state_lock); |
| 1257 | jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", | 1275 | jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", |
| 1258 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); | 1276 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); |
| @@ -1264,9 +1282,16 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) | |||
| 1264 | 1282 | ||
| 1265 | BUFFER_TRACE(bh, "marking dirty"); | 1283 | BUFFER_TRACE(bh, "marking dirty"); |
| 1266 | mark_buffer_dirty(bh); | 1284 | mark_buffer_dirty(bh); |
| 1267 | if (wait) | 1285 | if (wait) { |
| 1268 | sync_dirty_buffer(bh); | 1286 | sync_dirty_buffer(bh); |
| 1269 | else | 1287 | if (buffer_write_io_error(bh)) { |
| 1288 | printk(KERN_ERR "JBD2: I/O error detected " | ||
| 1289 | "when updating journal superblock for %s.\n", | ||
| 1290 | journal->j_devname); | ||
| 1291 | clear_buffer_write_io_error(bh); | ||
| 1292 | set_buffer_uptodate(bh); | ||
| 1293 | } | ||
| 1294 | } else | ||
| 1270 | ll_rw_block(SWRITE, 1, &bh); | 1295 | ll_rw_block(SWRITE, 1, &bh); |
| 1271 | 1296 | ||
| 1272 | out: | 1297 | out: |
| @@ -1426,9 +1451,12 @@ recovery_error: | |||
| 1426 | * | 1451 | * |
| 1427 | * Release a journal_t structure once it is no longer in use by the | 1452 | * Release a journal_t structure once it is no longer in use by the |
| 1428 | * journaled object. | 1453 | * journaled object. |
| 1454 | * Return <0 if we couldn't clean up the journal. | ||
| 1429 | */ | 1455 | */ |
| 1430 | void jbd2_journal_destroy(journal_t *journal) | 1456 | int jbd2_journal_destroy(journal_t *journal) |
| 1431 | { | 1457 | { |
| 1458 | int err = 0; | ||
| 1459 | |||
| 1432 | /* Wait for the commit thread to wake up and die. */ | 1460 | /* Wait for the commit thread to wake up and die. */ |
| 1433 | journal_kill_thread(journal); | 1461 | journal_kill_thread(journal); |
| 1434 | 1462 | ||
| @@ -1451,11 +1479,16 @@ void jbd2_journal_destroy(journal_t *journal) | |||
| 1451 | J_ASSERT(journal->j_checkpoint_transactions == NULL); | 1479 | J_ASSERT(journal->j_checkpoint_transactions == NULL); |
| 1452 | spin_unlock(&journal->j_list_lock); | 1480 | spin_unlock(&journal->j_list_lock); |
| 1453 | 1481 | ||
| 1454 | /* We can now mark the journal as empty. */ | ||
| 1455 | journal->j_tail = 0; | ||
| 1456 | journal->j_tail_sequence = ++journal->j_transaction_sequence; | ||
| 1457 | if (journal->j_sb_buffer) { | 1482 | if (journal->j_sb_buffer) { |
| 1458 | jbd2_journal_update_superblock(journal, 1); | 1483 | if (!is_journal_aborted(journal)) { |
| 1484 | /* We can now mark the journal as empty. */ | ||
| 1485 | journal->j_tail = 0; | ||
| 1486 | journal->j_tail_sequence = | ||
| 1487 | ++journal->j_transaction_sequence; | ||
| 1488 | jbd2_journal_update_superblock(journal, 1); | ||
| 1489 | } else { | ||
| 1490 | err = -EIO; | ||
| 1491 | } | ||
| 1459 | brelse(journal->j_sb_buffer); | 1492 | brelse(journal->j_sb_buffer); |
| 1460 | } | 1493 | } |
| 1461 | 1494 | ||
| @@ -1467,6 +1500,8 @@ void jbd2_journal_destroy(journal_t *journal) | |||
| 1467 | jbd2_journal_destroy_revoke(journal); | 1500 | jbd2_journal_destroy_revoke(journal); |
| 1468 | kfree(journal->j_wbuf); | 1501 | kfree(journal->j_wbuf); |
| 1469 | kfree(journal); | 1502 | kfree(journal); |
| 1503 | |||
| 1504 | return err; | ||
| 1470 | } | 1505 | } |
| 1471 | 1506 | ||
| 1472 | 1507 | ||
| @@ -1692,10 +1727,16 @@ int jbd2_journal_flush(journal_t *journal) | |||
| 1692 | spin_lock(&journal->j_list_lock); | 1727 | spin_lock(&journal->j_list_lock); |
| 1693 | while (!err && journal->j_checkpoint_transactions != NULL) { | 1728 | while (!err && journal->j_checkpoint_transactions != NULL) { |
| 1694 | spin_unlock(&journal->j_list_lock); | 1729 | spin_unlock(&journal->j_list_lock); |
| 1730 | mutex_lock(&journal->j_checkpoint_mutex); | ||
| 1695 | err = jbd2_log_do_checkpoint(journal); | 1731 | err = jbd2_log_do_checkpoint(journal); |
| 1732 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
| 1696 | spin_lock(&journal->j_list_lock); | 1733 | spin_lock(&journal->j_list_lock); |
| 1697 | } | 1734 | } |
| 1698 | spin_unlock(&journal->j_list_lock); | 1735 | spin_unlock(&journal->j_list_lock); |
| 1736 | |||
| 1737 | if (is_journal_aborted(journal)) | ||
| 1738 | return -EIO; | ||
| 1739 | |||
| 1699 | jbd2_cleanup_journal_tail(journal); | 1740 | jbd2_cleanup_journal_tail(journal); |
| 1700 | 1741 | ||
| 1701 | /* Finally, mark the journal as really needing no recovery. | 1742 | /* Finally, mark the journal as really needing no recovery. |
| @@ -1717,7 +1758,7 @@ int jbd2_journal_flush(journal_t *journal) | |||
| 1717 | J_ASSERT(journal->j_head == journal->j_tail); | 1758 | J_ASSERT(journal->j_head == journal->j_tail); |
| 1718 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); | 1759 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); |
| 1719 | spin_unlock(&journal->j_state_lock); | 1760 | spin_unlock(&journal->j_state_lock); |
| 1720 | return err; | 1761 | return 0; |
| 1721 | } | 1762 | } |
| 1722 | 1763 | ||
| 1723 | /** | 1764 | /** |
| @@ -1761,23 +1802,6 @@ int jbd2_journal_wipe(journal_t *journal, int write) | |||
| 1761 | } | 1802 | } |
| 1762 | 1803 | ||
| 1763 | /* | 1804 | /* |
| 1764 | * journal_dev_name: format a character string to describe on what | ||
| 1765 | * device this journal is present. | ||
| 1766 | */ | ||
| 1767 | |||
| 1768 | static const char *journal_dev_name(journal_t *journal, char *buffer) | ||
| 1769 | { | ||
| 1770 | struct block_device *bdev; | ||
| 1771 | |||
| 1772 | if (journal->j_inode) | ||
| 1773 | bdev = journal->j_inode->i_sb->s_bdev; | ||
| 1774 | else | ||
| 1775 | bdev = journal->j_dev; | ||
| 1776 | |||
| 1777 | return bdevname(bdev, buffer); | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | /* | ||
| 1781 | * Journal abort has very specific semantics, which we describe | 1805 | * Journal abort has very specific semantics, which we describe |
| 1782 | * for journal abort. | 1806 | * for journal abort. |
| 1783 | * | 1807 | * |
| @@ -1793,13 +1817,12 @@ static const char *journal_dev_name(journal_t *journal, char *buffer) | |||
| 1793 | void __jbd2_journal_abort_hard(journal_t *journal) | 1817 | void __jbd2_journal_abort_hard(journal_t *journal) |
| 1794 | { | 1818 | { |
| 1795 | transaction_t *transaction; | 1819 | transaction_t *transaction; |
| 1796 | char b[BDEVNAME_SIZE]; | ||
| 1797 | 1820 | ||
| 1798 | if (journal->j_flags & JBD2_ABORT) | 1821 | if (journal->j_flags & JBD2_ABORT) |
| 1799 | return; | 1822 | return; |
| 1800 | 1823 | ||
| 1801 | printk(KERN_ERR "Aborting journal on device %s.\n", | 1824 | printk(KERN_ERR "Aborting journal on device %s.\n", |
| 1802 | journal_dev_name(journal, b)); | 1825 | journal->j_devname); |
| 1803 | 1826 | ||
| 1804 | spin_lock(&journal->j_state_lock); | 1827 | spin_lock(&journal->j_state_lock); |
| 1805 | journal->j_flags |= JBD2_ABORT; | 1828 | journal->j_flags |= JBD2_ABORT; |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 058f50f65b7..73063285b13 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
| @@ -225,7 +225,7 @@ do { \ | |||
| 225 | */ | 225 | */ |
| 226 | int jbd2_journal_recover(journal_t *journal) | 226 | int jbd2_journal_recover(journal_t *journal) |
| 227 | { | 227 | { |
| 228 | int err; | 228 | int err, err2; |
| 229 | journal_superblock_t * sb; | 229 | journal_superblock_t * sb; |
| 230 | 230 | ||
| 231 | struct recovery_info info; | 231 | struct recovery_info info; |
| @@ -263,7 +263,10 @@ int jbd2_journal_recover(journal_t *journal) | |||
| 263 | journal->j_transaction_sequence = ++info.end_transaction; | 263 | journal->j_transaction_sequence = ++info.end_transaction; |
| 264 | 264 | ||
| 265 | jbd2_journal_clear_revoke(journal); | 265 | jbd2_journal_clear_revoke(journal); |
| 266 | sync_blockdev(journal->j_fs_dev); | 266 | err2 = sync_blockdev(journal->j_fs_dev); |
| 267 | if (!err) | ||
| 268 | err = err2; | ||
| 269 | |||
| 267 | return err; | 270 | return err; |
| 268 | } | 271 | } |
| 269 | 272 | ||
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index e5d540588fa..39b7805a599 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -52,6 +52,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
| 52 | transaction->t_expires = jiffies + journal->j_commit_interval; | 52 | transaction->t_expires = jiffies + journal->j_commit_interval; |
| 53 | spin_lock_init(&transaction->t_handle_lock); | 53 | spin_lock_init(&transaction->t_handle_lock); |
| 54 | INIT_LIST_HEAD(&transaction->t_inode_list); | 54 | INIT_LIST_HEAD(&transaction->t_inode_list); |
| 55 | INIT_LIST_HEAD(&transaction->t_private_list); | ||
| 55 | 56 | ||
| 56 | /* Set up the commit timer for the new transaction. */ | 57 | /* Set up the commit timer for the new transaction. */ |
| 57 | journal->j_commit_timer.expires = round_jiffies(transaction->t_expires); | 58 | journal->j_commit_timer.expires = round_jiffies(transaction->t_expires); |
