diff options
Diffstat (limited to 'fs/jbd')
-rw-r--r-- | fs/jbd/commit.c | 23 | ||||
-rw-r--r-- | fs/jbd/journal.c | 34 | ||||
-rw-r--r-- | fs/jbd/transaction.c | 2 |
3 files changed, 41 insertions, 18 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 3fbffb1ea714..f8077b9c8981 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/bio.h> | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * Default IO end handler for temporary BJ_IO buffer_heads. | 26 | * Default IO end handler for temporary BJ_IO buffer_heads. |
@@ -171,14 +172,15 @@ static int journal_write_commit_record(journal_t *journal, | |||
171 | return (ret == -EIO); | 172 | return (ret == -EIO); |
172 | } | 173 | } |
173 | 174 | ||
174 | static void journal_do_submit_data(struct buffer_head **wbuf, int bufs) | 175 | static void journal_do_submit_data(struct buffer_head **wbuf, int bufs, |
176 | int write_op) | ||
175 | { | 177 | { |
176 | int i; | 178 | int i; |
177 | 179 | ||
178 | for (i = 0; i < bufs; i++) { | 180 | for (i = 0; i < bufs; i++) { |
179 | wbuf[i]->b_end_io = end_buffer_write_sync; | 181 | wbuf[i]->b_end_io = end_buffer_write_sync; |
180 | /* We use-up our safety reference in submit_bh() */ | 182 | /* We use-up our safety reference in submit_bh() */ |
181 | submit_bh(WRITE, wbuf[i]); | 183 | submit_bh(write_op, wbuf[i]); |
182 | } | 184 | } |
183 | } | 185 | } |
184 | 186 | ||
@@ -186,7 +188,8 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs) | |||
186 | * Submit all the data buffers to disk | 188 | * Submit all the data buffers to disk |
187 | */ | 189 | */ |
188 | static int journal_submit_data_buffers(journal_t *journal, | 190 | static int journal_submit_data_buffers(journal_t *journal, |
189 | transaction_t *commit_transaction) | 191 | transaction_t *commit_transaction, |
192 | int write_op) | ||
190 | { | 193 | { |
191 | struct journal_head *jh; | 194 | struct journal_head *jh; |
192 | struct buffer_head *bh; | 195 | struct buffer_head *bh; |
@@ -225,7 +228,7 @@ write_out_data: | |||
225 | BUFFER_TRACE(bh, "needs blocking lock"); | 228 | BUFFER_TRACE(bh, "needs blocking lock"); |
226 | spin_unlock(&journal->j_list_lock); | 229 | spin_unlock(&journal->j_list_lock); |
227 | /* Write out all data to prevent deadlocks */ | 230 | /* Write out all data to prevent deadlocks */ |
228 | journal_do_submit_data(wbuf, bufs); | 231 | journal_do_submit_data(wbuf, bufs, write_op); |
229 | bufs = 0; | 232 | bufs = 0; |
230 | lock_buffer(bh); | 233 | lock_buffer(bh); |
231 | spin_lock(&journal->j_list_lock); | 234 | spin_lock(&journal->j_list_lock); |
@@ -256,7 +259,7 @@ write_out_data: | |||
256 | jbd_unlock_bh_state(bh); | 259 | jbd_unlock_bh_state(bh); |
257 | if (bufs == journal->j_wbufsize) { | 260 | if (bufs == journal->j_wbufsize) { |
258 | spin_unlock(&journal->j_list_lock); | 261 | spin_unlock(&journal->j_list_lock); |
259 | journal_do_submit_data(wbuf, bufs); | 262 | journal_do_submit_data(wbuf, bufs, write_op); |
260 | bufs = 0; | 263 | bufs = 0; |
261 | goto write_out_data; | 264 | goto write_out_data; |
262 | } | 265 | } |
@@ -286,7 +289,7 @@ write_out_data: | |||
286 | } | 289 | } |
287 | } | 290 | } |
288 | spin_unlock(&journal->j_list_lock); | 291 | spin_unlock(&journal->j_list_lock); |
289 | journal_do_submit_data(wbuf, bufs); | 292 | journal_do_submit_data(wbuf, bufs, write_op); |
290 | 293 | ||
291 | return err; | 294 | return err; |
292 | } | 295 | } |
@@ -315,6 +318,7 @@ void journal_commit_transaction(journal_t *journal) | |||
315 | int first_tag = 0; | 318 | int first_tag = 0; |
316 | int tag_flag; | 319 | int tag_flag; |
317 | int i; | 320 | int i; |
321 | int write_op = WRITE; | ||
318 | 322 | ||
319 | /* | 323 | /* |
320 | * First job: lock down the current transaction and wait for | 324 | * First job: lock down the current transaction and wait for |
@@ -347,6 +351,8 @@ void journal_commit_transaction(journal_t *journal) | |||
347 | spin_lock(&journal->j_state_lock); | 351 | spin_lock(&journal->j_state_lock); |
348 | commit_transaction->t_state = T_LOCKED; | 352 | commit_transaction->t_state = T_LOCKED; |
349 | 353 | ||
354 | if (commit_transaction->t_synchronous_commit) | ||
355 | write_op = WRITE_SYNC; | ||
350 | spin_lock(&commit_transaction->t_handle_lock); | 356 | spin_lock(&commit_transaction->t_handle_lock); |
351 | while (commit_transaction->t_updates) { | 357 | while (commit_transaction->t_updates) { |
352 | DEFINE_WAIT(wait); | 358 | DEFINE_WAIT(wait); |
@@ -431,7 +437,8 @@ void journal_commit_transaction(journal_t *journal) | |||
431 | * Now start flushing things to disk, in the order they appear | 437 | * Now start flushing things to disk, in the order they appear |
432 | * on the transaction lists. Data blocks go first. | 438 | * on the transaction lists. Data blocks go first. |
433 | */ | 439 | */ |
434 | err = journal_submit_data_buffers(journal, commit_transaction); | 440 | err = journal_submit_data_buffers(journal, commit_transaction, |
441 | write_op); | ||
435 | 442 | ||
436 | /* | 443 | /* |
437 | * Wait for all previously submitted IO to complete. | 444 | * Wait for all previously submitted IO to complete. |
@@ -660,7 +667,7 @@ start_journal_io: | |||
660 | clear_buffer_dirty(bh); | 667 | clear_buffer_dirty(bh); |
661 | set_buffer_uptodate(bh); | 668 | set_buffer_uptodate(bh); |
662 | bh->b_end_io = journal_end_buffer_io_sync; | 669 | bh->b_end_io = journal_end_buffer_io_sync; |
663 | submit_bh(WRITE, bh); | 670 | submit_bh(write_op, bh); |
664 | } | 671 | } |
665 | cond_resched(); | 672 | cond_resched(); |
666 | 673 | ||
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index e79c07812afa..737f7246a4b5 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -637,6 +637,8 @@ struct journal_head *journal_get_descriptor_buffer(journal_t *journal) | |||
637 | return NULL; | 637 | return NULL; |
638 | 638 | ||
639 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); | 639 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); |
640 | if (!bh) | ||
641 | return NULL; | ||
640 | lock_buffer(bh); | 642 | lock_buffer(bh); |
641 | memset(bh->b_data, 0, journal->j_blocksize); | 643 | memset(bh->b_data, 0, journal->j_blocksize); |
642 | set_buffer_uptodate(bh); | 644 | set_buffer_uptodate(bh); |
@@ -733,9 +735,7 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
733 | if (!journal->j_wbuf) { | 735 | if (!journal->j_wbuf) { |
734 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 736 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
735 | __func__); | 737 | __func__); |
736 | kfree(journal); | 738 | goto out_err; |
737 | journal = NULL; | ||
738 | goto out; | ||
739 | } | 739 | } |
740 | journal->j_dev = bdev; | 740 | journal->j_dev = bdev; |
741 | journal->j_fs_dev = fs_dev; | 741 | journal->j_fs_dev = fs_dev; |
@@ -743,11 +743,19 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
743 | journal->j_maxlen = len; | 743 | journal->j_maxlen = len; |
744 | 744 | ||
745 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | 745 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); |
746 | J_ASSERT(bh != NULL); | 746 | if (!bh) { |
747 | printk(KERN_ERR | ||
748 | "%s: Cannot get buffer for journal superblock\n", | ||
749 | __func__); | ||
750 | goto out_err; | ||
751 | } | ||
747 | journal->j_sb_buffer = bh; | 752 | journal->j_sb_buffer = bh; |
748 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | 753 | journal->j_superblock = (journal_superblock_t *)bh->b_data; |
749 | out: | 754 | |
750 | return journal; | 755 | return journal; |
756 | out_err: | ||
757 | kfree(journal); | ||
758 | return NULL; | ||
751 | } | 759 | } |
752 | 760 | ||
753 | /** | 761 | /** |
@@ -787,8 +795,7 @@ journal_t * journal_init_inode (struct inode *inode) | |||
787 | if (!journal->j_wbuf) { | 795 | if (!journal->j_wbuf) { |
788 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 796 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
789 | __func__); | 797 | __func__); |
790 | kfree(journal); | 798 | goto out_err; |
791 | return NULL; | ||
792 | } | 799 | } |
793 | 800 | ||
794 | err = journal_bmap(journal, 0, &blocknr); | 801 | err = journal_bmap(journal, 0, &blocknr); |
@@ -796,16 +803,23 @@ journal_t * journal_init_inode (struct inode *inode) | |||
796 | if (err) { | 803 | if (err) { |
797 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", | 804 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", |
798 | __func__); | 805 | __func__); |
799 | kfree(journal); | 806 | goto out_err; |
800 | return NULL; | ||
801 | } | 807 | } |
802 | 808 | ||
803 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); | 809 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); |
804 | J_ASSERT(bh != NULL); | 810 | if (!bh) { |
811 | printk(KERN_ERR | ||
812 | "%s: Cannot get buffer for journal superblock\n", | ||
813 | __func__); | ||
814 | goto out_err; | ||
815 | } | ||
805 | journal->j_sb_buffer = bh; | 816 | journal->j_sb_buffer = bh; |
806 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | 817 | journal->j_superblock = (journal_superblock_t *)bh->b_data; |
807 | 818 | ||
808 | return journal; | 819 | return journal; |
820 | out_err: | ||
821 | kfree(journal); | ||
822 | return NULL; | ||
809 | } | 823 | } |
810 | 824 | ||
811 | /* | 825 | /* |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index e6a117431277..ed886e6db399 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -1440,6 +1440,8 @@ int journal_stop(handle_t *handle) | |||
1440 | } | 1440 | } |
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | if (handle->h_sync) | ||
1444 | transaction->t_synchronous_commit = 1; | ||
1443 | current->journal_info = NULL; | 1445 | current->journal_info = NULL; |
1444 | spin_lock(&journal->j_state_lock); | 1446 | spin_lock(&journal->j_state_lock); |
1445 | spin_lock(&transaction->t_handle_lock); | 1447 | spin_lock(&transaction->t_handle_lock); |