diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 130 |
1 files changed, 87 insertions, 43 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c77a7ac753f3..45d0f70a1f04 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -72,12 +72,17 @@ static int ext4_inode_is_fast_symlink(struct inode *inode) | |||
72 | * "bh" may be NULL: a metadata block may have been freed from memory | 72 | * "bh" may be NULL: a metadata block may have been freed from memory |
73 | * but there may still be a record of it in the journal, and that record | 73 | * but there may still be a record of it in the journal, and that record |
74 | * still needs to be revoked. | 74 | * still needs to be revoked. |
75 | * | ||
76 | * If the handle isn't valid we're not journaling so there's nothing to do. | ||
75 | */ | 77 | */ |
76 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, | 78 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, |
77 | struct buffer_head *bh, ext4_fsblk_t blocknr) | 79 | struct buffer_head *bh, ext4_fsblk_t blocknr) |
78 | { | 80 | { |
79 | int err; | 81 | int err; |
80 | 82 | ||
83 | if (!ext4_handle_valid(handle)) | ||
84 | return 0; | ||
85 | |||
81 | might_sleep(); | 86 | might_sleep(); |
82 | 87 | ||
83 | BUFFER_TRACE(bh, "enter"); | 88 | BUFFER_TRACE(bh, "enter"); |
@@ -170,7 +175,9 @@ static handle_t *start_transaction(struct inode *inode) | |||
170 | */ | 175 | */ |
171 | static int try_to_extend_transaction(handle_t *handle, struct inode *inode) | 176 | static int try_to_extend_transaction(handle_t *handle, struct inode *inode) |
172 | { | 177 | { |
173 | if (handle->h_buffer_credits > EXT4_RESERVE_TRANS_BLOCKS) | 178 | if (!ext4_handle_valid(handle)) |
179 | return 0; | ||
180 | if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1)) | ||
174 | return 0; | 181 | return 0; |
175 | if (!ext4_journal_extend(handle, blocks_for_truncate(inode))) | 182 | if (!ext4_journal_extend(handle, blocks_for_truncate(inode))) |
176 | return 0; | 183 | return 0; |
@@ -184,6 +191,7 @@ static int try_to_extend_transaction(handle_t *handle, struct inode *inode) | |||
184 | */ | 191 | */ |
185 | static int ext4_journal_test_restart(handle_t *handle, struct inode *inode) | 192 | static int ext4_journal_test_restart(handle_t *handle, struct inode *inode) |
186 | { | 193 | { |
194 | BUG_ON(EXT4_JOURNAL(inode) == NULL); | ||
187 | jbd_debug(2, "restarting handle %p\n", handle); | 195 | jbd_debug(2, "restarting handle %p\n", handle); |
188 | return ext4_journal_restart(handle, blocks_for_truncate(inode)); | 196 | return ext4_journal_restart(handle, blocks_for_truncate(inode)); |
189 | } | 197 | } |
@@ -216,7 +224,7 @@ void ext4_delete_inode(struct inode *inode) | |||
216 | } | 224 | } |
217 | 225 | ||
218 | if (IS_SYNC(inode)) | 226 | if (IS_SYNC(inode)) |
219 | handle->h_sync = 1; | 227 | ext4_handle_sync(handle); |
220 | inode->i_size = 0; | 228 | inode->i_size = 0; |
221 | err = ext4_mark_inode_dirty(handle, inode); | 229 | err = ext4_mark_inode_dirty(handle, inode); |
222 | if (err) { | 230 | if (err) { |
@@ -233,7 +241,7 @@ void ext4_delete_inode(struct inode *inode) | |||
233 | * enough credits left in the handle to remove the inode from | 241 | * enough credits left in the handle to remove the inode from |
234 | * the orphan list and set the dtime field. | 242 | * the orphan list and set the dtime field. |
235 | */ | 243 | */ |
236 | if (handle->h_buffer_credits < 3) { | 244 | if (!ext4_handle_has_enough_credits(handle, 3)) { |
237 | err = ext4_journal_extend(handle, 3); | 245 | err = ext4_journal_extend(handle, 3); |
238 | if (err > 0) | 246 | if (err > 0) |
239 | err = ext4_journal_restart(handle, 3); | 247 | err = ext4_journal_restart(handle, 3); |
@@ -717,8 +725,8 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, | |||
717 | set_buffer_uptodate(bh); | 725 | set_buffer_uptodate(bh); |
718 | unlock_buffer(bh); | 726 | unlock_buffer(bh); |
719 | 727 | ||
720 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 728 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
721 | err = ext4_journal_dirty_metadata(handle, bh); | 729 | err = ext4_handle_dirty_metadata(handle, inode, bh); |
722 | if (err) | 730 | if (err) |
723 | goto failed; | 731 | goto failed; |
724 | } | 732 | } |
@@ -800,8 +808,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode, | |||
800 | * generic_commit_write->__mark_inode_dirty->ext4_dirty_inode. | 808 | * generic_commit_write->__mark_inode_dirty->ext4_dirty_inode. |
801 | */ | 809 | */ |
802 | jbd_debug(5, "splicing indirect only\n"); | 810 | jbd_debug(5, "splicing indirect only\n"); |
803 | BUFFER_TRACE(where->bh, "call ext4_journal_dirty_metadata"); | 811 | BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata"); |
804 | err = ext4_journal_dirty_metadata(handle, where->bh); | 812 | err = ext4_handle_dirty_metadata(handle, inode, where->bh); |
805 | if (err) | 813 | if (err) |
806 | goto err_out; | 814 | goto err_out; |
807 | } else { | 815 | } else { |
@@ -1229,8 +1237,8 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, | |||
1229 | set_buffer_uptodate(bh); | 1237 | set_buffer_uptodate(bh); |
1230 | } | 1238 | } |
1231 | unlock_buffer(bh); | 1239 | unlock_buffer(bh); |
1232 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 1240 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
1233 | err = ext4_journal_dirty_metadata(handle, bh); | 1241 | err = ext4_handle_dirty_metadata(handle, inode, bh); |
1234 | if (!fatal) | 1242 | if (!fatal) |
1235 | fatal = err; | 1243 | fatal = err; |
1236 | } else { | 1244 | } else { |
@@ -1395,7 +1403,7 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh) | |||
1395 | if (!buffer_mapped(bh) || buffer_freed(bh)) | 1403 | if (!buffer_mapped(bh) || buffer_freed(bh)) |
1396 | return 0; | 1404 | return 0; |
1397 | set_buffer_uptodate(bh); | 1405 | set_buffer_uptodate(bh); |
1398 | return ext4_journal_dirty_metadata(handle, bh); | 1406 | return ext4_handle_dirty_metadata(handle, NULL, bh); |
1399 | } | 1407 | } |
1400 | 1408 | ||
1401 | /* | 1409 | /* |
@@ -2762,7 +2770,10 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) | |||
2762 | filemap_write_and_wait(mapping); | 2770 | filemap_write_and_wait(mapping); |
2763 | } | 2771 | } |
2764 | 2772 | ||
2765 | if (EXT4_I(inode)->i_state & EXT4_STATE_JDATA) { | 2773 | BUG_ON(!EXT4_JOURNAL(inode) && |
2774 | EXT4_I(inode)->i_state & EXT4_STATE_JDATA); | ||
2775 | |||
2776 | if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) { | ||
2766 | /* | 2777 | /* |
2767 | * This is a REALLY heavyweight approach, but the use of | 2778 | * This is a REALLY heavyweight approach, but the use of |
2768 | * bmap on dirty files is expected to be extremely rare: | 2779 | * bmap on dirty files is expected to be extremely rare: |
@@ -3033,7 +3044,10 @@ static void ext4_invalidatepage(struct page *page, unsigned long offset) | |||
3033 | if (offset == 0) | 3044 | if (offset == 0) |
3034 | ClearPageChecked(page); | 3045 | ClearPageChecked(page); |
3035 | 3046 | ||
3036 | jbd2_journal_invalidatepage(journal, page, offset); | 3047 | if (journal) |
3048 | jbd2_journal_invalidatepage(journal, page, offset); | ||
3049 | else | ||
3050 | block_invalidatepage(page, offset); | ||
3037 | } | 3051 | } |
3038 | 3052 | ||
3039 | static int ext4_releasepage(struct page *page, gfp_t wait) | 3053 | static int ext4_releasepage(struct page *page, gfp_t wait) |
@@ -3043,7 +3057,10 @@ static int ext4_releasepage(struct page *page, gfp_t wait) | |||
3043 | WARN_ON(PageChecked(page)); | 3057 | WARN_ON(PageChecked(page)); |
3044 | if (!page_has_buffers(page)) | 3058 | if (!page_has_buffers(page)) |
3045 | return 0; | 3059 | return 0; |
3046 | return jbd2_journal_try_to_free_buffers(journal, page, wait); | 3060 | if (journal) |
3061 | return jbd2_journal_try_to_free_buffers(journal, page, wait); | ||
3062 | else | ||
3063 | return try_to_free_buffers(page); | ||
3047 | } | 3064 | } |
3048 | 3065 | ||
3049 | /* | 3066 | /* |
@@ -3315,7 +3332,7 @@ int ext4_block_truncate_page(handle_t *handle, | |||
3315 | 3332 | ||
3316 | err = 0; | 3333 | err = 0; |
3317 | if (ext4_should_journal_data(inode)) { | 3334 | if (ext4_should_journal_data(inode)) { |
3318 | err = ext4_journal_dirty_metadata(handle, bh); | 3335 | err = ext4_handle_dirty_metadata(handle, inode, bh); |
3319 | } else { | 3336 | } else { |
3320 | if (ext4_should_order_data(inode)) | 3337 | if (ext4_should_order_data(inode)) |
3321 | err = ext4_jbd2_file_inode(handle, inode); | 3338 | err = ext4_jbd2_file_inode(handle, inode); |
@@ -3439,8 +3456,8 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, | |||
3439 | __le32 *p; | 3456 | __le32 *p; |
3440 | if (try_to_extend_transaction(handle, inode)) { | 3457 | if (try_to_extend_transaction(handle, inode)) { |
3441 | if (bh) { | 3458 | if (bh) { |
3442 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 3459 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
3443 | ext4_journal_dirty_metadata(handle, bh); | 3460 | ext4_handle_dirty_metadata(handle, inode, bh); |
3444 | } | 3461 | } |
3445 | ext4_mark_inode_dirty(handle, inode); | 3462 | ext4_mark_inode_dirty(handle, inode); |
3446 | ext4_journal_test_restart(handle, inode); | 3463 | ext4_journal_test_restart(handle, inode); |
@@ -3540,7 +3557,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, | |||
3540 | count, block_to_free_p, p); | 3557 | count, block_to_free_p, p); |
3541 | 3558 | ||
3542 | if (this_bh) { | 3559 | if (this_bh) { |
3543 | BUFFER_TRACE(this_bh, "call ext4_journal_dirty_metadata"); | 3560 | BUFFER_TRACE(this_bh, "call ext4_handle_dirty_metadata"); |
3544 | 3561 | ||
3545 | /* | 3562 | /* |
3546 | * The buffer head should have an attached journal head at this | 3563 | * The buffer head should have an attached journal head at this |
@@ -3549,7 +3566,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, | |||
3549 | * the block was cleared. Check for this instead of OOPSing. | 3566 | * the block was cleared. Check for this instead of OOPSing. |
3550 | */ | 3567 | */ |
3551 | if (bh2jh(this_bh)) | 3568 | if (bh2jh(this_bh)) |
3552 | ext4_journal_dirty_metadata(handle, this_bh); | 3569 | ext4_handle_dirty_metadata(handle, inode, this_bh); |
3553 | else | 3570 | else |
3554 | ext4_error(inode->i_sb, __func__, | 3571 | ext4_error(inode->i_sb, __func__, |
3555 | "circular indirect block detected, " | 3572 | "circular indirect block detected, " |
@@ -3579,7 +3596,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
3579 | ext4_fsblk_t nr; | 3596 | ext4_fsblk_t nr; |
3580 | __le32 *p; | 3597 | __le32 *p; |
3581 | 3598 | ||
3582 | if (is_handle_aborted(handle)) | 3599 | if (ext4_handle_is_aborted(handle)) |
3583 | return; | 3600 | return; |
3584 | 3601 | ||
3585 | if (depth--) { | 3602 | if (depth--) { |
@@ -3649,7 +3666,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
3649 | * will merely complain about releasing a free block, | 3666 | * will merely complain about releasing a free block, |
3650 | * rather than leaking blocks. | 3667 | * rather than leaking blocks. |
3651 | */ | 3668 | */ |
3652 | if (is_handle_aborted(handle)) | 3669 | if (ext4_handle_is_aborted(handle)) |
3653 | return; | 3670 | return; |
3654 | if (try_to_extend_transaction(handle, inode)) { | 3671 | if (try_to_extend_transaction(handle, inode)) { |
3655 | ext4_mark_inode_dirty(handle, inode); | 3672 | ext4_mark_inode_dirty(handle, inode); |
@@ -3668,9 +3685,10 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
3668 | parent_bh)){ | 3685 | parent_bh)){ |
3669 | *p = 0; | 3686 | *p = 0; |
3670 | BUFFER_TRACE(parent_bh, | 3687 | BUFFER_TRACE(parent_bh, |
3671 | "call ext4_journal_dirty_metadata"); | 3688 | "call ext4_handle_dirty_metadata"); |
3672 | ext4_journal_dirty_metadata(handle, | 3689 | ext4_handle_dirty_metadata(handle, |
3673 | parent_bh); | 3690 | inode, |
3691 | parent_bh); | ||
3674 | } | 3692 | } |
3675 | } | 3693 | } |
3676 | } | 3694 | } |
@@ -3858,7 +3876,7 @@ do_indirects: | |||
3858 | * synchronous | 3876 | * synchronous |
3859 | */ | 3877 | */ |
3860 | if (IS_SYNC(inode)) | 3878 | if (IS_SYNC(inode)) |
3861 | handle->h_sync = 1; | 3879 | ext4_handle_sync(handle); |
3862 | out_stop: | 3880 | out_stop: |
3863 | /* | 3881 | /* |
3864 | * If this was a simple ftruncate(), and the file will remain alive | 3882 | * If this was a simple ftruncate(), and the file will remain alive |
@@ -4357,8 +4375,8 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4357 | EXT4_SET_RO_COMPAT_FEATURE(sb, | 4375 | EXT4_SET_RO_COMPAT_FEATURE(sb, |
4358 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE); | 4376 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE); |
4359 | sb->s_dirt = 1; | 4377 | sb->s_dirt = 1; |
4360 | handle->h_sync = 1; | 4378 | ext4_handle_sync(handle); |
4361 | err = ext4_journal_dirty_metadata(handle, | 4379 | err = ext4_handle_dirty_metadata(handle, inode, |
4362 | EXT4_SB(sb)->s_sbh); | 4380 | EXT4_SB(sb)->s_sbh); |
4363 | } | 4381 | } |
4364 | } | 4382 | } |
@@ -4385,9 +4403,8 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4385 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); | 4403 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); |
4386 | } | 4404 | } |
4387 | 4405 | ||
4388 | 4406 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | |
4389 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 4407 | rc = ext4_handle_dirty_metadata(handle, inode, bh); |
4390 | rc = ext4_journal_dirty_metadata(handle, bh); | ||
4391 | if (!err) | 4408 | if (!err) |
4392 | err = rc; | 4409 | err = rc; |
4393 | ei->i_state &= ~EXT4_STATE_NEW; | 4410 | ei->i_state &= ~EXT4_STATE_NEW; |
@@ -4450,6 +4467,25 @@ int ext4_write_inode(struct inode *inode, int wait) | |||
4450 | return ext4_force_commit(inode->i_sb); | 4467 | return ext4_force_commit(inode->i_sb); |
4451 | } | 4468 | } |
4452 | 4469 | ||
4470 | int __ext4_write_dirty_metadata(struct inode *inode, struct buffer_head *bh) | ||
4471 | { | ||
4472 | int err = 0; | ||
4473 | |||
4474 | mark_buffer_dirty(bh); | ||
4475 | if (inode && inode_needs_sync(inode)) { | ||
4476 | sync_dirty_buffer(bh); | ||
4477 | if (buffer_req(bh) && !buffer_uptodate(bh)) { | ||
4478 | ext4_error(inode->i_sb, __func__, | ||
4479 | "IO error syncing inode, " | ||
4480 | "inode=%lu, block=%llu", | ||
4481 | inode->i_ino, | ||
4482 | (unsigned long long)bh->b_blocknr); | ||
4483 | err = -EIO; | ||
4484 | } | ||
4485 | } | ||
4486 | return err; | ||
4487 | } | ||
4488 | |||
4453 | /* | 4489 | /* |
4454 | * ext4_setattr() | 4490 | * ext4_setattr() |
4455 | * | 4491 | * |
@@ -4754,16 +4790,15 @@ int | |||
4754 | ext4_reserve_inode_write(handle_t *handle, struct inode *inode, | 4790 | ext4_reserve_inode_write(handle_t *handle, struct inode *inode, |
4755 | struct ext4_iloc *iloc) | 4791 | struct ext4_iloc *iloc) |
4756 | { | 4792 | { |
4757 | int err = 0; | 4793 | int err; |
4758 | if (handle) { | 4794 | |
4759 | err = ext4_get_inode_loc(inode, iloc); | 4795 | err = ext4_get_inode_loc(inode, iloc); |
4760 | if (!err) { | 4796 | if (!err) { |
4761 | BUFFER_TRACE(iloc->bh, "get_write_access"); | 4797 | BUFFER_TRACE(iloc->bh, "get_write_access"); |
4762 | err = ext4_journal_get_write_access(handle, iloc->bh); | 4798 | err = ext4_journal_get_write_access(handle, iloc->bh); |
4763 | if (err) { | 4799 | if (err) { |
4764 | brelse(iloc->bh); | 4800 | brelse(iloc->bh); |
4765 | iloc->bh = NULL; | 4801 | iloc->bh = NULL; |
4766 | } | ||
4767 | } | 4802 | } |
4768 | } | 4803 | } |
4769 | ext4_std_error(inode->i_sb, err); | 4804 | ext4_std_error(inode->i_sb, err); |
@@ -4835,7 +4870,8 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | |||
4835 | 4870 | ||
4836 | might_sleep(); | 4871 | might_sleep(); |
4837 | err = ext4_reserve_inode_write(handle, inode, &iloc); | 4872 | err = ext4_reserve_inode_write(handle, inode, &iloc); |
4838 | if (EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize && | 4873 | if (ext4_handle_valid(handle) && |
4874 | EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize && | ||
4839 | !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) { | 4875 | !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) { |
4840 | /* | 4876 | /* |
4841 | * We need extra buffer credits since we may write into EA block | 4877 | * We need extra buffer credits since we may write into EA block |
@@ -4887,6 +4923,11 @@ void ext4_dirty_inode(struct inode *inode) | |||
4887 | handle_t *current_handle = ext4_journal_current_handle(); | 4923 | handle_t *current_handle = ext4_journal_current_handle(); |
4888 | handle_t *handle; | 4924 | handle_t *handle; |
4889 | 4925 | ||
4926 | if (!ext4_handle_valid(current_handle)) { | ||
4927 | ext4_mark_inode_dirty(current_handle, inode); | ||
4928 | return; | ||
4929 | } | ||
4930 | |||
4890 | handle = ext4_journal_start(inode, 2); | 4931 | handle = ext4_journal_start(inode, 2); |
4891 | if (IS_ERR(handle)) | 4932 | if (IS_ERR(handle)) |
4892 | goto out; | 4933 | goto out; |
@@ -4924,8 +4965,9 @@ static int ext4_pin_inode(handle_t *handle, struct inode *inode) | |||
4924 | BUFFER_TRACE(iloc.bh, "get_write_access"); | 4965 | BUFFER_TRACE(iloc.bh, "get_write_access"); |
4925 | err = jbd2_journal_get_write_access(handle, iloc.bh); | 4966 | err = jbd2_journal_get_write_access(handle, iloc.bh); |
4926 | if (!err) | 4967 | if (!err) |
4927 | err = ext4_journal_dirty_metadata(handle, | 4968 | err = ext4_handle_dirty_metadata(handle, |
4928 | iloc.bh); | 4969 | inode, |
4970 | iloc.bh); | ||
4929 | brelse(iloc.bh); | 4971 | brelse(iloc.bh); |
4930 | } | 4972 | } |
4931 | } | 4973 | } |
@@ -4951,6 +4993,8 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) | |||
4951 | */ | 4993 | */ |
4952 | 4994 | ||
4953 | journal = EXT4_JOURNAL(inode); | 4995 | journal = EXT4_JOURNAL(inode); |
4996 | if (!journal) | ||
4997 | return 0; | ||
4954 | if (is_journal_aborted(journal)) | 4998 | if (is_journal_aborted(journal)) |
4955 | return -EROFS; | 4999 | return -EROFS; |
4956 | 5000 | ||
@@ -4980,7 +5024,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) | |||
4980 | return PTR_ERR(handle); | 5024 | return PTR_ERR(handle); |
4981 | 5025 | ||
4982 | err = ext4_mark_inode_dirty(handle, inode); | 5026 | err = ext4_mark_inode_dirty(handle, inode); |
4983 | handle->h_sync = 1; | 5027 | ext4_handle_sync(handle); |
4984 | ext4_journal_stop(handle); | 5028 | ext4_journal_stop(handle); |
4985 | ext4_std_error(inode->i_sb, err); | 5029 | ext4_std_error(inode->i_sb, err); |
4986 | 5030 | ||