diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 15 | ||||
-rw-r--r-- | fs/ext4/mmp.c | 6 | ||||
-rw-r--r-- | fs/ext4/super.c | 31 |
3 files changed, 23 insertions, 29 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 89b59cb7f9b8..6324f74e0342 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -233,6 +233,11 @@ void ext4_evict_inode(struct inode *inode) | |||
233 | if (is_bad_inode(inode)) | 233 | if (is_bad_inode(inode)) |
234 | goto no_delete; | 234 | goto no_delete; |
235 | 235 | ||
236 | /* | ||
237 | * Protect us against freezing - iput() caller didn't have to have any | ||
238 | * protection against it | ||
239 | */ | ||
240 | sb_start_intwrite(inode->i_sb); | ||
236 | handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3); | 241 | handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3); |
237 | if (IS_ERR(handle)) { | 242 | if (IS_ERR(handle)) { |
238 | ext4_std_error(inode->i_sb, PTR_ERR(handle)); | 243 | ext4_std_error(inode->i_sb, PTR_ERR(handle)); |
@@ -242,6 +247,7 @@ void ext4_evict_inode(struct inode *inode) | |||
242 | * cleaned up. | 247 | * cleaned up. |
243 | */ | 248 | */ |
244 | ext4_orphan_del(NULL, inode); | 249 | ext4_orphan_del(NULL, inode); |
250 | sb_end_intwrite(inode->i_sb); | ||
245 | goto no_delete; | 251 | goto no_delete; |
246 | } | 252 | } |
247 | 253 | ||
@@ -273,6 +279,7 @@ void ext4_evict_inode(struct inode *inode) | |||
273 | stop_handle: | 279 | stop_handle: |
274 | ext4_journal_stop(handle); | 280 | ext4_journal_stop(handle); |
275 | ext4_orphan_del(NULL, inode); | 281 | ext4_orphan_del(NULL, inode); |
282 | sb_end_intwrite(inode->i_sb); | ||
276 | goto no_delete; | 283 | goto no_delete; |
277 | } | 284 | } |
278 | } | 285 | } |
@@ -301,6 +308,7 @@ void ext4_evict_inode(struct inode *inode) | |||
301 | else | 308 | else |
302 | ext4_free_inode(handle, inode); | 309 | ext4_free_inode(handle, inode); |
303 | ext4_journal_stop(handle); | 310 | ext4_journal_stop(handle); |
311 | sb_end_intwrite(inode->i_sb); | ||
304 | return; | 312 | return; |
305 | no_delete: | 313 | no_delete: |
306 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ | 314 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ |
@@ -4779,11 +4787,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
4779 | get_block_t *get_block; | 4787 | get_block_t *get_block; |
4780 | int retries = 0; | 4788 | int retries = 0; |
4781 | 4789 | ||
4782 | /* | 4790 | sb_start_pagefault(inode->i_sb); |
4783 | * This check is racy but catches the common case. We rely on | ||
4784 | * __block_page_mkwrite() to do a reliable check. | ||
4785 | */ | ||
4786 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
4787 | /* Delalloc case is easy... */ | 4791 | /* Delalloc case is easy... */ |
4788 | if (test_opt(inode->i_sb, DELALLOC) && | 4792 | if (test_opt(inode->i_sb, DELALLOC) && |
4789 | !ext4_should_journal_data(inode) && | 4793 | !ext4_should_journal_data(inode) && |
@@ -4851,5 +4855,6 @@ retry_alloc: | |||
4851 | out_ret: | 4855 | out_ret: |
4852 | ret = block_page_mkwrite_return(ret); | 4856 | ret = block_page_mkwrite_return(ret); |
4853 | out: | 4857 | out: |
4858 | sb_end_pagefault(inode->i_sb); | ||
4854 | return ret; | 4859 | return ret; |
4855 | } | 4860 | } |
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index f99a1311e847..fe7c63f4717e 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c | |||
@@ -44,6 +44,11 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) | |||
44 | { | 44 | { |
45 | struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data); | 45 | struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data); |
46 | 46 | ||
47 | /* | ||
48 | * We protect against freezing so that we don't create dirty buffers | ||
49 | * on frozen filesystem. | ||
50 | */ | ||
51 | sb_start_write(sb); | ||
47 | ext4_mmp_csum_set(sb, mmp); | 52 | ext4_mmp_csum_set(sb, mmp); |
48 | mark_buffer_dirty(bh); | 53 | mark_buffer_dirty(bh); |
49 | lock_buffer(bh); | 54 | lock_buffer(bh); |
@@ -51,6 +56,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) | |||
51 | get_bh(bh); | 56 | get_bh(bh); |
52 | submit_bh(WRITE_SYNC, bh); | 57 | submit_bh(WRITE_SYNC, bh); |
53 | wait_on_buffer(bh); | 58 | wait_on_buffer(bh); |
59 | sb_end_write(sb); | ||
54 | if (unlikely(!buffer_uptodate(bh))) | 60 | if (unlikely(!buffer_uptodate(bh))) |
55 | return 1; | 61 | return 1; |
56 | 62 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2d51cd9af225..d76ec8277d3f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -331,33 +331,17 @@ static void ext4_put_nojournal(handle_t *handle) | |||
331 | * journal_end calls result in the superblock being marked dirty, so | 331 | * journal_end calls result in the superblock being marked dirty, so |
332 | * that sync() will call the filesystem's write_super callback if | 332 | * that sync() will call the filesystem's write_super callback if |
333 | * appropriate. | 333 | * appropriate. |
334 | * | ||
335 | * To avoid j_barrier hold in userspace when a user calls freeze(), | ||
336 | * ext4 prevents a new handle from being started by s_frozen, which | ||
337 | * is in an upper layer. | ||
338 | */ | 334 | */ |
339 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | 335 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) |
340 | { | 336 | { |
341 | journal_t *journal; | 337 | journal_t *journal; |
342 | handle_t *handle; | ||
343 | 338 | ||
344 | trace_ext4_journal_start(sb, nblocks, _RET_IP_); | 339 | trace_ext4_journal_start(sb, nblocks, _RET_IP_); |
345 | if (sb->s_flags & MS_RDONLY) | 340 | if (sb->s_flags & MS_RDONLY) |
346 | return ERR_PTR(-EROFS); | 341 | return ERR_PTR(-EROFS); |
347 | 342 | ||
343 | WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); | ||
348 | journal = EXT4_SB(sb)->s_journal; | 344 | journal = EXT4_SB(sb)->s_journal; |
349 | handle = ext4_journal_current_handle(); | ||
350 | |||
351 | /* | ||
352 | * If a handle has been started, it should be allowed to | ||
353 | * finish, otherwise deadlock could happen between freeze | ||
354 | * and others(e.g. truncate) due to the restart of the | ||
355 | * journal handle if the filesystem is forzen and active | ||
356 | * handles are not stopped. | ||
357 | */ | ||
358 | if (!handle) | ||
359 | vfs_check_frozen(sb, SB_FREEZE_TRANS); | ||
360 | |||
361 | if (!journal) | 345 | if (!journal) |
362 | return ext4_get_nojournal(); | 346 | return ext4_get_nojournal(); |
363 | /* | 347 | /* |
@@ -2747,6 +2731,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) | |||
2747 | sb = elr->lr_super; | 2731 | sb = elr->lr_super; |
2748 | ngroups = EXT4_SB(sb)->s_groups_count; | 2732 | ngroups = EXT4_SB(sb)->s_groups_count; |
2749 | 2733 | ||
2734 | sb_start_write(sb); | ||
2750 | for (group = elr->lr_next_group; group < ngroups; group++) { | 2735 | for (group = elr->lr_next_group; group < ngroups; group++) { |
2751 | gdp = ext4_get_group_desc(sb, group, NULL); | 2736 | gdp = ext4_get_group_desc(sb, group, NULL); |
2752 | if (!gdp) { | 2737 | if (!gdp) { |
@@ -2773,6 +2758,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) | |||
2773 | elr->lr_next_sched = jiffies + elr->lr_timeout; | 2758 | elr->lr_next_sched = jiffies + elr->lr_timeout; |
2774 | elr->lr_next_group = group + 1; | 2759 | elr->lr_next_group = group + 1; |
2775 | } | 2760 | } |
2761 | sb_end_write(sb); | ||
2776 | 2762 | ||
2777 | return ret; | 2763 | return ret; |
2778 | } | 2764 | } |
@@ -4460,10 +4446,8 @@ int ext4_force_commit(struct super_block *sb) | |||
4460 | return 0; | 4446 | return 0; |
4461 | 4447 | ||
4462 | journal = EXT4_SB(sb)->s_journal; | 4448 | journal = EXT4_SB(sb)->s_journal; |
4463 | if (journal) { | 4449 | if (journal) |
4464 | vfs_check_frozen(sb, SB_FREEZE_TRANS); | ||
4465 | ret = ext4_journal_force_commit(journal); | 4450 | ret = ext4_journal_force_commit(journal); |
4466 | } | ||
4467 | 4451 | ||
4468 | return ret; | 4452 | return ret; |
4469 | } | 4453 | } |
@@ -4493,9 +4477,8 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
4493 | * gives us a chance to flush the journal completely and mark the fs clean. | 4477 | * gives us a chance to flush the journal completely and mark the fs clean. |
4494 | * | 4478 | * |
4495 | * Note that only this function cannot bring a filesystem to be in a clean | 4479 | * Note that only this function cannot bring a filesystem to be in a clean |
4496 | * state independently, because ext4 prevents a new handle from being started | 4480 | * state independently. It relies on upper layer to stop all data & metadata |
4497 | * by @sb->s_frozen, which stays in an upper layer. It thus needs help from | 4481 | * modifications. |
4498 | * the upper layer. | ||
4499 | */ | 4482 | */ |
4500 | static int ext4_freeze(struct super_block *sb) | 4483 | static int ext4_freeze(struct super_block *sb) |
4501 | { | 4484 | { |
@@ -4522,7 +4505,7 @@ static int ext4_freeze(struct super_block *sb) | |||
4522 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 4505 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
4523 | error = ext4_commit_super(sb, 1); | 4506 | error = ext4_commit_super(sb, 1); |
4524 | out: | 4507 | out: |
4525 | /* we rely on s_frozen to stop further updates */ | 4508 | /* we rely on upper layer to stop further updates */ |
4526 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 4509 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
4527 | return error; | 4510 | return error; |
4528 | } | 4511 | } |