diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 74 |
1 files changed, 58 insertions, 16 deletions
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 | } |
