diff options
Diffstat (limited to 'fs/jbd2/commit.c')
-rw-r--r-- | fs/jbd2/commit.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 92b6ac3df8ab..3ca107b5c86b 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -355,6 +355,81 @@ write_out_data: | |||
355 | journal_do_submit_data(wbuf, bufs); | 355 | journal_do_submit_data(wbuf, bufs); |
356 | } | 356 | } |
357 | 357 | ||
358 | /* | ||
359 | * Submit all the data buffers of inode associated with the transaction to | ||
360 | * disk. | ||
361 | * | ||
362 | * We are in a committing transaction. Therefore no new inode can be added to | ||
363 | * our inode list. We use JI_COMMIT_RUNNING flag to protect inode we currently | ||
364 | * operate on from being released while we write out pages. | ||
365 | */ | ||
366 | static int journal_submit_inode_data_buffers(journal_t *journal, | ||
367 | transaction_t *commit_transaction) | ||
368 | { | ||
369 | struct jbd2_inode *jinode; | ||
370 | int err, ret = 0; | ||
371 | struct address_space *mapping; | ||
372 | |||
373 | spin_lock(&journal->j_list_lock); | ||
374 | list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { | ||
375 | mapping = jinode->i_vfs_inode->i_mapping; | ||
376 | jinode->i_flags |= JI_COMMIT_RUNNING; | ||
377 | spin_unlock(&journal->j_list_lock); | ||
378 | err = filemap_fdatawrite_range(mapping, 0, | ||
379 | i_size_read(jinode->i_vfs_inode)); | ||
380 | if (!ret) | ||
381 | ret = err; | ||
382 | spin_lock(&journal->j_list_lock); | ||
383 | J_ASSERT(jinode->i_transaction == commit_transaction); | ||
384 | jinode->i_flags &= ~JI_COMMIT_RUNNING; | ||
385 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); | ||
386 | } | ||
387 | spin_unlock(&journal->j_list_lock); | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * Wait for data submitted for writeout, refile inodes to proper | ||
393 | * transaction if needed. | ||
394 | * | ||
395 | */ | ||
396 | static int journal_finish_inode_data_buffers(journal_t *journal, | ||
397 | transaction_t *commit_transaction) | ||
398 | { | ||
399 | struct jbd2_inode *jinode, *next_i; | ||
400 | int err, ret = 0; | ||
401 | |||
402 | /* For locking, see the comment in journal_submit_inode_data_buffers() */ | ||
403 | spin_lock(&journal->j_list_lock); | ||
404 | list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { | ||
405 | jinode->i_flags |= JI_COMMIT_RUNNING; | ||
406 | spin_unlock(&journal->j_list_lock); | ||
407 | err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping); | ||
408 | if (!ret) | ||
409 | ret = err; | ||
410 | spin_lock(&journal->j_list_lock); | ||
411 | jinode->i_flags &= ~JI_COMMIT_RUNNING; | ||
412 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); | ||
413 | } | ||
414 | |||
415 | /* Now refile inode to proper lists */ | ||
416 | list_for_each_entry_safe(jinode, next_i, | ||
417 | &commit_transaction->t_inode_list, i_list) { | ||
418 | list_del(&jinode->i_list); | ||
419 | if (jinode->i_next_transaction) { | ||
420 | jinode->i_transaction = jinode->i_next_transaction; | ||
421 | jinode->i_next_transaction = NULL; | ||
422 | list_add(&jinode->i_list, | ||
423 | &jinode->i_transaction->t_inode_list); | ||
424 | } else { | ||
425 | jinode->i_transaction = NULL; | ||
426 | } | ||
427 | } | ||
428 | spin_unlock(&journal->j_list_lock); | ||
429 | |||
430 | return ret; | ||
431 | } | ||
432 | |||
358 | static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) | 433 | static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) |
359 | { | 434 | { |
360 | struct page *page = bh->b_page; | 435 | struct page *page = bh->b_page; |
@@ -529,6 +604,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
529 | */ | 604 | */ |
530 | err = 0; | 605 | err = 0; |
531 | journal_submit_data_buffers(journal, commit_transaction); | 606 | journal_submit_data_buffers(journal, commit_transaction); |
607 | err = journal_submit_inode_data_buffers(journal, commit_transaction); | ||
608 | if (err) | ||
609 | jbd2_journal_abort(journal, err); | ||
532 | 610 | ||
533 | /* | 611 | /* |
534 | * Wait for all previously submitted IO to complete if commit | 612 | * Wait for all previously submitted IO to complete if commit |
@@ -760,6 +838,17 @@ start_journal_io: | |||
760 | __jbd2_journal_abort_hard(journal); | 838 | __jbd2_journal_abort_hard(journal); |
761 | } | 839 | } |
762 | 840 | ||
841 | /* | ||
842 | * This is the right place to wait for data buffers both for ASYNC | ||
843 | * and !ASYNC commit. If commit is ASYNC, we need to wait only after | ||
844 | * the commit block went to disk (which happens above). If commit is | ||
845 | * SYNC, we need to wait for data buffers before we start writing | ||
846 | * commit block, which happens below in such setting. | ||
847 | */ | ||
848 | err = journal_finish_inode_data_buffers(journal, commit_transaction); | ||
849 | if (err) | ||
850 | jbd2_journal_abort(journal, err); | ||
851 | |||
763 | /* Lo and behold: we have just managed to send a transaction to | 852 | /* Lo and behold: we have just managed to send a transaction to |
764 | the log. Before we can commit it, wait for the IO so far to | 853 | the log. Before we can commit it, wait for the IO so far to |
765 | complete. Control buffers being written are on the | 854 | complete. Control buffers being written are on the |
@@ -880,6 +969,7 @@ wait_for_iobuf: | |||
880 | jbd_debug(3, "JBD: commit phase 7\n"); | 969 | jbd_debug(3, "JBD: commit phase 7\n"); |
881 | 970 | ||
882 | J_ASSERT(commit_transaction->t_sync_datalist == NULL); | 971 | J_ASSERT(commit_transaction->t_sync_datalist == NULL); |
972 | J_ASSERT(list_empty(&commit_transaction->t_inode_list)); | ||
883 | J_ASSERT(commit_transaction->t_buffers == NULL); | 973 | J_ASSERT(commit_transaction->t_buffers == NULL); |
884 | J_ASSERT(commit_transaction->t_checkpoint_list == NULL); | 974 | J_ASSERT(commit_transaction->t_checkpoint_list == NULL); |
885 | J_ASSERT(commit_transaction->t_iobuf_list == NULL); | 975 | J_ASSERT(commit_transaction->t_iobuf_list == NULL); |