diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-11 18:45:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-11 18:45:47 -0400 |
commit | a97b52022a73ec12e43f0b2c7d4bd1f40f89c81d (patch) | |
tree | 1a35544915a5704fa59c63b43e9f46e20be1e296 /fs/ext4 | |
parent | 18770c7c3a0ccd60017ac76b5d2e7d1f71376b94 (diff) | |
parent | c8205636029fc869278c55b7336053b3e7ae3ef4 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix data corruption regression by reverting commit 6de9843dab3f
ext4: Allow indirect-block file to grow the file size to max file size
ext4: allow an active handle to be started when freezing
ext4: sync the directory inode in ext4_sync_parent()
ext4: init timer earlier to avoid a kernel panic in __save_error_info
jbd2: fix potential memory leak on transaction commit
ext4: fix a double free in ext4_register_li_request
ext4: fix credits computing for indirect mapped files
ext4: remove unnecessary [cm]time update of quota file
jbd2: move bdget out of critical section
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 4 | ||||
-rw-r--r-- | fs/ext4/fsync.c | 17 | ||||
-rw-r--r-- | fs/ext4/inode.c | 35 | ||||
-rw-r--r-- | fs/ext4/super.c | 74 |
4 files changed, 97 insertions, 33 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index e25e99bf7ee1..d0f53538a57f 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -86,8 +86,8 @@ | |||
86 | 86 | ||
87 | #ifdef CONFIG_QUOTA | 87 | #ifdef CONFIG_QUOTA |
88 | /* Amount of blocks needed for quota update - we know that the structure was | 88 | /* Amount of blocks needed for quota update - we know that the structure was |
89 | * allocated so we need to update only inode+data */ | 89 | * allocated so we need to update only data block */ |
90 | #define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0) | 90 | #define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0) |
91 | /* Amount of blocks needed for quota insert/delete - we do some block writes | 91 | /* Amount of blocks needed for quota insert/delete - we do some block writes |
92 | * but inode, sb and group updates are done only once */ | 92 | * but inode, sb and group updates are done only once */ |
93 | #define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ | 93 | #define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ |
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 4673bc05274f..e9473cbe80df 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c | |||
@@ -125,9 +125,11 @@ extern int ext4_flush_completed_IO(struct inode *inode) | |||
125 | * the parent directory's parent as well, and so on recursively, if | 125 | * the parent directory's parent as well, and so on recursively, if |
126 | * they are also freshly created. | 126 | * they are also freshly created. |
127 | */ | 127 | */ |
128 | static void ext4_sync_parent(struct inode *inode) | 128 | static int ext4_sync_parent(struct inode *inode) |
129 | { | 129 | { |
130 | struct writeback_control wbc; | ||
130 | struct dentry *dentry = NULL; | 131 | struct dentry *dentry = NULL; |
132 | int ret = 0; | ||
131 | 133 | ||
132 | while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { | 134 | while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { |
133 | ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); | 135 | ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); |
@@ -136,8 +138,17 @@ static void ext4_sync_parent(struct inode *inode) | |||
136 | if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode) | 138 | if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode) |
137 | break; | 139 | break; |
138 | inode = dentry->d_parent->d_inode; | 140 | inode = dentry->d_parent->d_inode; |
139 | sync_mapping_buffers(inode->i_mapping); | 141 | ret = sync_mapping_buffers(inode->i_mapping); |
142 | if (ret) | ||
143 | break; | ||
144 | memset(&wbc, 0, sizeof(wbc)); | ||
145 | wbc.sync_mode = WB_SYNC_ALL; | ||
146 | wbc.nr_to_write = 0; /* only write out the inode */ | ||
147 | ret = sync_inode(inode, &wbc); | ||
148 | if (ret) | ||
149 | break; | ||
140 | } | 150 | } |
151 | return ret; | ||
141 | } | 152 | } |
142 | 153 | ||
143 | /* | 154 | /* |
@@ -176,7 +187,7 @@ int ext4_sync_file(struct file *file, int datasync) | |||
176 | if (!journal) { | 187 | if (!journal) { |
177 | ret = generic_file_fsync(file, datasync); | 188 | ret = generic_file_fsync(file, datasync); |
178 | if (!ret && !list_empty(&inode->i_dentry)) | 189 | if (!ret && !list_empty(&inode->i_dentry)) |
179 | ext4_sync_parent(inode); | 190 | ret = ext4_sync_parent(inode); |
180 | goto out; | 191 | goto out; |
181 | } | 192 | } |
182 | 193 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ad8e303c0d29..f2fa5e8a582c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2502,6 +2502,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
2502 | * for partial write. | 2502 | * for partial write. |
2503 | */ | 2503 | */ |
2504 | set_buffer_new(bh); | 2504 | set_buffer_new(bh); |
2505 | set_buffer_mapped(bh); | ||
2505 | } | 2506 | } |
2506 | return 0; | 2507 | return 0; |
2507 | } | 2508 | } |
@@ -4429,8 +4430,8 @@ void ext4_truncate(struct inode *inode) | |||
4429 | Indirect chain[4]; | 4430 | Indirect chain[4]; |
4430 | Indirect *partial; | 4431 | Indirect *partial; |
4431 | __le32 nr = 0; | 4432 | __le32 nr = 0; |
4432 | int n; | 4433 | int n = 0; |
4433 | ext4_lblk_t last_block; | 4434 | ext4_lblk_t last_block, max_block; |
4434 | unsigned blocksize = inode->i_sb->s_blocksize; | 4435 | unsigned blocksize = inode->i_sb->s_blocksize; |
4435 | 4436 | ||
4436 | trace_ext4_truncate_enter(inode); | 4437 | trace_ext4_truncate_enter(inode); |
@@ -4455,14 +4456,18 @@ void ext4_truncate(struct inode *inode) | |||
4455 | 4456 | ||
4456 | last_block = (inode->i_size + blocksize-1) | 4457 | last_block = (inode->i_size + blocksize-1) |
4457 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); | 4458 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); |
4459 | max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1) | ||
4460 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); | ||
4458 | 4461 | ||
4459 | if (inode->i_size & (blocksize - 1)) | 4462 | if (inode->i_size & (blocksize - 1)) |
4460 | if (ext4_block_truncate_page(handle, mapping, inode->i_size)) | 4463 | if (ext4_block_truncate_page(handle, mapping, inode->i_size)) |
4461 | goto out_stop; | 4464 | goto out_stop; |
4462 | 4465 | ||
4463 | n = ext4_block_to_path(inode, last_block, offsets, NULL); | 4466 | if (last_block != max_block) { |
4464 | if (n == 0) | 4467 | n = ext4_block_to_path(inode, last_block, offsets, NULL); |
4465 | goto out_stop; /* error */ | 4468 | if (n == 0) |
4469 | goto out_stop; /* error */ | ||
4470 | } | ||
4466 | 4471 | ||
4467 | /* | 4472 | /* |
4468 | * OK. This truncate is going to happen. We add the inode to the | 4473 | * OK. This truncate is going to happen. We add the inode to the |
@@ -4493,7 +4498,13 @@ void ext4_truncate(struct inode *inode) | |||
4493 | */ | 4498 | */ |
4494 | ei->i_disksize = inode->i_size; | 4499 | ei->i_disksize = inode->i_size; |
4495 | 4500 | ||
4496 | if (n == 1) { /* direct blocks */ | 4501 | if (last_block == max_block) { |
4502 | /* | ||
4503 | * It is unnecessary to free any data blocks if last_block is | ||
4504 | * equal to the indirect block limit. | ||
4505 | */ | ||
4506 | goto out_unlock; | ||
4507 | } else if (n == 1) { /* direct blocks */ | ||
4497 | ext4_free_data(handle, inode, NULL, i_data+offsets[0], | 4508 | ext4_free_data(handle, inode, NULL, i_data+offsets[0], |
4498 | i_data + EXT4_NDIR_BLOCKS); | 4509 | i_data + EXT4_NDIR_BLOCKS); |
4499 | goto do_indirects; | 4510 | goto do_indirects; |
@@ -4553,6 +4564,7 @@ do_indirects: | |||
4553 | ; | 4564 | ; |
4554 | } | 4565 | } |
4555 | 4566 | ||
4567 | out_unlock: | ||
4556 | up_write(&ei->i_data_sem); | 4568 | up_write(&ei->i_data_sem); |
4557 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | 4569 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); |
4558 | ext4_mark_inode_dirty(handle, inode); | 4570 | ext4_mark_inode_dirty(handle, inode); |
@@ -5398,13 +5410,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, | |||
5398 | /* if nrblocks are contiguous */ | 5410 | /* if nrblocks are contiguous */ |
5399 | if (chunk) { | 5411 | if (chunk) { |
5400 | /* | 5412 | /* |
5401 | * With N contiguous data blocks, it need at most | 5413 | * With N contiguous data blocks, we need at most |
5402 | * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks | 5414 | * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks, |
5403 | * 2 dindirect blocks | 5415 | * 2 dindirect blocks, and 1 tindirect block |
5404 | * 1 tindirect block | ||
5405 | */ | 5416 | */ |
5406 | indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); | 5417 | return DIV_ROUND_UP(nrblocks, |
5407 | return indirects + 3; | 5418 | EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4; |
5408 | } | 5419 | } |
5409 | /* | 5420 | /* |
5410 | * if nrblocks are not contiguous, worse case, each block touch | 5421 | * if nrblocks are not contiguous, worse case, each block touch |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 056474b7b8e0..8553dfb310af 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -242,27 +242,44 @@ static void ext4_put_nojournal(handle_t *handle) | |||
242 | * journal_end calls result in the superblock being marked dirty, so | 242 | * journal_end calls result in the superblock being marked dirty, so |
243 | * that sync() will call the filesystem's write_super callback if | 243 | * that sync() will call the filesystem's write_super callback if |
244 | * appropriate. | 244 | * appropriate. |
245 | * | ||
246 | * To avoid j_barrier hold in userspace when a user calls freeze(), | ||
247 | * ext4 prevents a new handle from being started by s_frozen, which | ||
248 | * is in an upper layer. | ||
245 | */ | 249 | */ |
246 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | 250 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) |
247 | { | 251 | { |
248 | journal_t *journal; | 252 | journal_t *journal; |
253 | handle_t *handle; | ||
249 | 254 | ||
250 | if (sb->s_flags & MS_RDONLY) | 255 | if (sb->s_flags & MS_RDONLY) |
251 | return ERR_PTR(-EROFS); | 256 | return ERR_PTR(-EROFS); |
252 | 257 | ||
253 | vfs_check_frozen(sb, SB_FREEZE_TRANS); | ||
254 | /* Special case here: if the journal has aborted behind our | ||
255 | * backs (eg. EIO in the commit thread), then we still need to | ||
256 | * take the FS itself readonly cleanly. */ | ||
257 | journal = EXT4_SB(sb)->s_journal; | 258 | journal = EXT4_SB(sb)->s_journal; |
258 | if (journal) { | 259 | handle = ext4_journal_current_handle(); |
259 | if (is_journal_aborted(journal)) { | 260 | |
260 | ext4_abort(sb, "Detected aborted journal"); | 261 | /* |
261 | return ERR_PTR(-EROFS); | 262 | * If a handle has been started, it should be allowed to |
262 | } | 263 | * finish, otherwise deadlock could happen between freeze |
263 | return jbd2_journal_start(journal, nblocks); | 264 | * and others(e.g. truncate) due to the restart of the |
265 | * journal handle if the filesystem is forzen and active | ||
266 | * handles are not stopped. | ||
267 | */ | ||
268 | if (!handle) | ||
269 | vfs_check_frozen(sb, SB_FREEZE_TRANS); | ||
270 | |||
271 | if (!journal) | ||
272 | return ext4_get_nojournal(); | ||
273 | /* | ||
274 | * Special case here: if the journal has aborted behind our | ||
275 | * backs (eg. EIO in the commit thread), then we still need to | ||
276 | * take the FS itself readonly cleanly. | ||
277 | */ | ||
278 | if (is_journal_aborted(journal)) { | ||
279 | ext4_abort(sb, "Detected aborted journal"); | ||
280 | return ERR_PTR(-EROFS); | ||
264 | } | 281 | } |
265 | return ext4_get_nojournal(); | 282 | return jbd2_journal_start(journal, nblocks); |
266 | } | 283 | } |
267 | 284 | ||
268 | /* | 285 | /* |
@@ -2975,6 +2992,12 @@ static int ext4_register_li_request(struct super_block *sb, | |||
2975 | mutex_unlock(&ext4_li_info->li_list_mtx); | 2992 | mutex_unlock(&ext4_li_info->li_list_mtx); |
2976 | 2993 | ||
2977 | sbi->s_li_request = elr; | 2994 | sbi->s_li_request = elr; |
2995 | /* | ||
2996 | * set elr to NULL here since it has been inserted to | ||
2997 | * the request_list and the removal and free of it is | ||
2998 | * handled by ext4_clear_request_list from now on. | ||
2999 | */ | ||
3000 | elr = NULL; | ||
2978 | 3001 | ||
2979 | if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) { | 3002 | if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) { |
2980 | ret = ext4_run_lazyinit_thread(); | 3003 | ret = ext4_run_lazyinit_thread(); |
@@ -3385,6 +3408,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3385 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 3408 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
3386 | spin_lock_init(&sbi->s_next_gen_lock); | 3409 | spin_lock_init(&sbi->s_next_gen_lock); |
3387 | 3410 | ||
3411 | init_timer(&sbi->s_err_report); | ||
3412 | sbi->s_err_report.function = print_daily_error_info; | ||
3413 | sbi->s_err_report.data = (unsigned long) sb; | ||
3414 | |||
3388 | err = percpu_counter_init(&sbi->s_freeblocks_counter, | 3415 | err = percpu_counter_init(&sbi->s_freeblocks_counter, |
3389 | ext4_count_free_blocks(sb)); | 3416 | ext4_count_free_blocks(sb)); |
3390 | if (!err) { | 3417 | if (!err) { |
@@ -3646,9 +3673,6 @@ no_journal: | |||
3646 | "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts, | 3673 | "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts, |
3647 | *sbi->s_es->s_mount_opts ? "; " : "", orig_data); | 3674 | *sbi->s_es->s_mount_opts ? "; " : "", orig_data); |
3648 | 3675 | ||
3649 | init_timer(&sbi->s_err_report); | ||
3650 | sbi->s_err_report.function = print_daily_error_info; | ||
3651 | sbi->s_err_report.data = (unsigned long) sb; | ||
3652 | if (es->s_error_count) | 3676 | if (es->s_error_count) |
3653 | mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ | 3677 | mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ |
3654 | 3678 | ||
@@ -3672,6 +3696,7 @@ failed_mount_wq: | |||
3672 | sbi->s_journal = NULL; | 3696 | sbi->s_journal = NULL; |
3673 | } | 3697 | } |
3674 | failed_mount3: | 3698 | failed_mount3: |
3699 | del_timer(&sbi->s_err_report); | ||
3675 | if (sbi->s_flex_groups) { | 3700 | if (sbi->s_flex_groups) { |
3676 | if (is_vmalloc_addr(sbi->s_flex_groups)) | 3701 | if (is_vmalloc_addr(sbi->s_flex_groups)) |
3677 | vfree(sbi->s_flex_groups); | 3702 | vfree(sbi->s_flex_groups); |
@@ -4138,6 +4163,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
4138 | /* | 4163 | /* |
4139 | * LVM calls this function before a (read-only) snapshot is created. This | 4164 | * LVM calls this function before a (read-only) snapshot is created. This |
4140 | * gives us a chance to flush the journal completely and mark the fs clean. | 4165 | * gives us a chance to flush the journal completely and mark the fs clean. |
4166 | * | ||
4167 | * Note that only this function cannot bring a filesystem to be in a clean | ||
4168 | * state independently, because ext4 prevents a new handle from being started | ||
4169 | * by @sb->s_frozen, which stays in an upper layer. It thus needs help from | ||
4170 | * the upper layer. | ||
4141 | */ | 4171 | */ |
4142 | static int ext4_freeze(struct super_block *sb) | 4172 | static int ext4_freeze(struct super_block *sb) |
4143 | { | 4173 | { |
@@ -4614,11 +4644,24 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, | |||
4614 | 4644 | ||
4615 | static int ext4_quota_off(struct super_block *sb, int type) | 4645 | static int ext4_quota_off(struct super_block *sb, int type) |
4616 | { | 4646 | { |
4647 | struct inode *inode = sb_dqopt(sb)->files[type]; | ||
4648 | handle_t *handle; | ||
4649 | |||
4617 | /* Force all delayed allocation blocks to be allocated. | 4650 | /* Force all delayed allocation blocks to be allocated. |
4618 | * Caller already holds s_umount sem */ | 4651 | * Caller already holds s_umount sem */ |
4619 | if (test_opt(sb, DELALLOC)) | 4652 | if (test_opt(sb, DELALLOC)) |
4620 | sync_filesystem(sb); | 4653 | sync_filesystem(sb); |
4621 | 4654 | ||
4655 | /* Update modification times of quota files when userspace can | ||
4656 | * start looking at them */ | ||
4657 | handle = ext4_journal_start(inode, 1); | ||
4658 | if (IS_ERR(handle)) | ||
4659 | goto out; | ||
4660 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
4661 | ext4_mark_inode_dirty(handle, inode); | ||
4662 | ext4_journal_stop(handle); | ||
4663 | |||
4664 | out: | ||
4622 | return dquot_quota_off(sb, type); | 4665 | return dquot_quota_off(sb, type); |
4623 | } | 4666 | } |
4624 | 4667 | ||
@@ -4714,9 +4757,8 @@ out: | |||
4714 | if (inode->i_size < off + len) { | 4757 | if (inode->i_size < off + len) { |
4715 | i_size_write(inode, off + len); | 4758 | i_size_write(inode, off + len); |
4716 | EXT4_I(inode)->i_disksize = inode->i_size; | 4759 | EXT4_I(inode)->i_disksize = inode->i_size; |
4760 | ext4_mark_inode_dirty(handle, inode); | ||
4717 | } | 4761 | } |
4718 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
4719 | ext4_mark_inode_dirty(handle, inode); | ||
4720 | mutex_unlock(&inode->i_mutex); | 4762 | mutex_unlock(&inode->i_mutex); |
4721 | return len; | 4763 | return len; |
4722 | } | 4764 | } |