diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e14d22c170d5..49d88c0597c4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -241,6 +241,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | |||
241 | if (sb->s_flags & MS_RDONLY) | 241 | if (sb->s_flags & MS_RDONLY) |
242 | return ERR_PTR(-EROFS); | 242 | return ERR_PTR(-EROFS); |
243 | 243 | ||
244 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | ||
244 | /* Special case here: if the journal has aborted behind our | 245 | /* Special case here: if the journal has aborted behind our |
245 | * backs (eg. EIO in the commit thread), then we still need to | 246 | * backs (eg. EIO in the commit thread), then we still need to |
246 | * take the FS itself readonly cleanly. */ | 247 | * take the FS itself readonly cleanly. */ |
@@ -941,6 +942,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
941 | seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0"); | 942 | seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0"); |
942 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) | 943 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) |
943 | seq_puts(seq, ",journal_async_commit"); | 944 | seq_puts(seq, ",journal_async_commit"); |
945 | else if (test_opt(sb, JOURNAL_CHECKSUM)) | ||
946 | seq_puts(seq, ",journal_checksum"); | ||
944 | if (test_opt(sb, NOBH)) | 947 | if (test_opt(sb, NOBH)) |
945 | seq_puts(seq, ",nobh"); | 948 | seq_puts(seq, ",nobh"); |
946 | if (test_opt(sb, I_VERSION)) | 949 | if (test_opt(sb, I_VERSION)) |
@@ -2213,7 +2216,7 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi) | |||
2213 | struct ext4_attr { | 2216 | struct ext4_attr { |
2214 | struct attribute attr; | 2217 | struct attribute attr; |
2215 | ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *); | 2218 | ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *); |
2216 | ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, | 2219 | ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, |
2217 | const char *, size_t); | 2220 | const char *, size_t); |
2218 | int offset; | 2221 | int offset; |
2219 | }; | 2222 | }; |
@@ -2430,6 +2433,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2430 | __releases(kernel_lock) | 2433 | __releases(kernel_lock) |
2431 | __acquires(kernel_lock) | 2434 | __acquires(kernel_lock) |
2432 | { | 2435 | { |
2436 | char *orig_data = kstrdup(data, GFP_KERNEL); | ||
2433 | struct buffer_head *bh; | 2437 | struct buffer_head *bh; |
2434 | struct ext4_super_block *es = NULL; | 2438 | struct ext4_super_block *es = NULL; |
2435 | struct ext4_sb_info *sbi; | 2439 | struct ext4_sb_info *sbi; |
@@ -2793,24 +2797,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2793 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 2797 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
2794 | spin_lock_init(&sbi->s_next_gen_lock); | 2798 | spin_lock_init(&sbi->s_next_gen_lock); |
2795 | 2799 | ||
2796 | err = percpu_counter_init(&sbi->s_freeblocks_counter, | ||
2797 | ext4_count_free_blocks(sb)); | ||
2798 | if (!err) { | ||
2799 | err = percpu_counter_init(&sbi->s_freeinodes_counter, | ||
2800 | ext4_count_free_inodes(sb)); | ||
2801 | } | ||
2802 | if (!err) { | ||
2803 | err = percpu_counter_init(&sbi->s_dirs_counter, | ||
2804 | ext4_count_dirs(sb)); | ||
2805 | } | ||
2806 | if (!err) { | ||
2807 | err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); | ||
2808 | } | ||
2809 | if (err) { | ||
2810 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | ||
2811 | goto failed_mount3; | ||
2812 | } | ||
2813 | |||
2814 | sbi->s_stripe = ext4_get_stripe_size(sbi); | 2800 | sbi->s_stripe = ext4_get_stripe_size(sbi); |
2815 | sbi->s_max_writeback_mb_bump = 128; | 2801 | sbi->s_max_writeback_mb_bump = 128; |
2816 | 2802 | ||
@@ -2910,6 +2896,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2910 | set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); | 2896 | set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); |
2911 | 2897 | ||
2912 | no_journal: | 2898 | no_journal: |
2899 | err = percpu_counter_init(&sbi->s_freeblocks_counter, | ||
2900 | ext4_count_free_blocks(sb)); | ||
2901 | if (!err) | ||
2902 | err = percpu_counter_init(&sbi->s_freeinodes_counter, | ||
2903 | ext4_count_free_inodes(sb)); | ||
2904 | if (!err) | ||
2905 | err = percpu_counter_init(&sbi->s_dirs_counter, | ||
2906 | ext4_count_dirs(sb)); | ||
2907 | if (!err) | ||
2908 | err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); | ||
2909 | if (err) { | ||
2910 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | ||
2911 | goto failed_mount_wq; | ||
2912 | } | ||
2913 | if (test_opt(sb, NOBH)) { | 2913 | if (test_opt(sb, NOBH)) { |
2914 | if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) { | 2914 | if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) { |
2915 | ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - " | 2915 | ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - " |
@@ -3001,7 +3001,7 @@ no_journal: | |||
3001 | err = ext4_setup_system_zone(sb); | 3001 | err = ext4_setup_system_zone(sb); |
3002 | if (err) { | 3002 | if (err) { |
3003 | ext4_msg(sb, KERN_ERR, "failed to initialize system " | 3003 | ext4_msg(sb, KERN_ERR, "failed to initialize system " |
3004 | "zone (%d)\n", err); | 3004 | "zone (%d)", err); |
3005 | goto failed_mount4; | 3005 | goto failed_mount4; |
3006 | } | 3006 | } |
3007 | 3007 | ||
@@ -3040,9 +3040,11 @@ no_journal: | |||
3040 | } else | 3040 | } else |
3041 | descr = "out journal"; | 3041 | descr = "out journal"; |
3042 | 3042 | ||
3043 | ext4_msg(sb, KERN_INFO, "mounted filesystem with%s", descr); | 3043 | ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " |
3044 | "Opts: %s", descr, orig_data); | ||
3044 | 3045 | ||
3045 | lock_kernel(); | 3046 | lock_kernel(); |
3047 | kfree(orig_data); | ||
3046 | return 0; | 3048 | return 0; |
3047 | 3049 | ||
3048 | cantfind_ext4: | 3050 | cantfind_ext4: |
@@ -3059,6 +3061,10 @@ failed_mount_wq: | |||
3059 | jbd2_journal_destroy(sbi->s_journal); | 3061 | jbd2_journal_destroy(sbi->s_journal); |
3060 | sbi->s_journal = NULL; | 3062 | sbi->s_journal = NULL; |
3061 | } | 3063 | } |
3064 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | ||
3065 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
3066 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
3067 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
3062 | failed_mount3: | 3068 | failed_mount3: |
3063 | if (sbi->s_flex_groups) { | 3069 | if (sbi->s_flex_groups) { |
3064 | if (is_vmalloc_addr(sbi->s_flex_groups)) | 3070 | if (is_vmalloc_addr(sbi->s_flex_groups)) |
@@ -3066,10 +3072,6 @@ failed_mount3: | |||
3066 | else | 3072 | else |
3067 | kfree(sbi->s_flex_groups); | 3073 | kfree(sbi->s_flex_groups); |
3068 | } | 3074 | } |
3069 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | ||
3070 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
3071 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
3072 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
3073 | failed_mount2: | 3075 | failed_mount2: |
3074 | for (i = 0; i < db_count; i++) | 3076 | for (i = 0; i < db_count; i++) |
3075 | brelse(sbi->s_group_desc[i]); | 3077 | brelse(sbi->s_group_desc[i]); |
@@ -3089,6 +3091,7 @@ out_fail: | |||
3089 | kfree(sbi->s_blockgroup_lock); | 3091 | kfree(sbi->s_blockgroup_lock); |
3090 | kfree(sbi); | 3092 | kfree(sbi); |
3091 | lock_kernel(); | 3093 | lock_kernel(); |
3094 | kfree(orig_data); | ||
3092 | return ret; | 3095 | return ret; |
3093 | } | 3096 | } |
3094 | 3097 | ||
@@ -3380,7 +3383,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) | |||
3380 | if (!(sb->s_flags & MS_RDONLY)) | 3383 | if (!(sb->s_flags & MS_RDONLY)) |
3381 | es->s_wtime = cpu_to_le32(get_seconds()); | 3384 | es->s_wtime = cpu_to_le32(get_seconds()); |
3382 | es->s_kbytes_written = | 3385 | es->s_kbytes_written = |
3383 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + | 3386 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + |
3384 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | 3387 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - |
3385 | EXT4_SB(sb)->s_sectors_written_start) >> 1)); | 3388 | EXT4_SB(sb)->s_sectors_written_start) >> 1)); |
3386 | ext4_free_blocks_count_set(es, percpu_counter_sum_positive( | 3389 | ext4_free_blocks_count_set(es, percpu_counter_sum_positive( |
@@ -3485,8 +3488,10 @@ int ext4_force_commit(struct super_block *sb) | |||
3485 | return 0; | 3488 | return 0; |
3486 | 3489 | ||
3487 | journal = EXT4_SB(sb)->s_journal; | 3490 | journal = EXT4_SB(sb)->s_journal; |
3488 | if (journal) | 3491 | if (journal) { |
3492 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | ||
3489 | ret = ext4_journal_force_commit(journal); | 3493 | ret = ext4_journal_force_commit(journal); |
3494 | } | ||
3490 | 3495 | ||
3491 | return ret; | 3496 | return ret; |
3492 | } | 3497 | } |
@@ -3535,18 +3540,16 @@ static int ext4_freeze(struct super_block *sb) | |||
3535 | * the journal. | 3540 | * the journal. |
3536 | */ | 3541 | */ |
3537 | error = jbd2_journal_flush(journal); | 3542 | error = jbd2_journal_flush(journal); |
3538 | if (error < 0) { | 3543 | if (error < 0) |
3539 | out: | 3544 | goto out; |
3540 | jbd2_journal_unlock_updates(journal); | ||
3541 | return error; | ||
3542 | } | ||
3543 | 3545 | ||
3544 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 3546 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
3545 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 3547 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
3546 | error = ext4_commit_super(sb, 1); | 3548 | error = ext4_commit_super(sb, 1); |
3547 | if (error) | 3549 | out: |
3548 | goto out; | 3550 | /* we rely on s_frozen to stop further updates */ |
3549 | return 0; | 3551 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
3552 | return error; | ||
3550 | } | 3553 | } |
3551 | 3554 | ||
3552 | /* | 3555 | /* |
@@ -3563,7 +3566,6 @@ static int ext4_unfreeze(struct super_block *sb) | |||
3563 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 3566 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
3564 | ext4_commit_super(sb, 1); | 3567 | ext4_commit_super(sb, 1); |
3565 | unlock_super(sb); | 3568 | unlock_super(sb); |
3566 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | ||
3567 | return 0; | 3569 | return 0; |
3568 | } | 3570 | } |
3569 | 3571 | ||
@@ -3580,6 +3582,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
3580 | #ifdef CONFIG_QUOTA | 3582 | #ifdef CONFIG_QUOTA |
3581 | int i; | 3583 | int i; |
3582 | #endif | 3584 | #endif |
3585 | char *orig_data = kstrdup(data, GFP_KERNEL); | ||
3583 | 3586 | ||
3584 | lock_kernel(); | 3587 | lock_kernel(); |
3585 | 3588 | ||
@@ -3713,6 +3716,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
3713 | #endif | 3716 | #endif |
3714 | unlock_super(sb); | 3717 | unlock_super(sb); |
3715 | unlock_kernel(); | 3718 | unlock_kernel(); |
3719 | |||
3720 | ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data); | ||
3721 | kfree(orig_data); | ||
3716 | return 0; | 3722 | return 0; |
3717 | 3723 | ||
3718 | restore_opts: | 3724 | restore_opts: |
@@ -3734,6 +3740,7 @@ restore_opts: | |||
3734 | #endif | 3740 | #endif |
3735 | unlock_super(sb); | 3741 | unlock_super(sb); |
3736 | unlock_kernel(); | 3742 | unlock_kernel(); |
3743 | kfree(orig_data); | ||
3737 | return err; | 3744 | return err; |
3738 | } | 3745 | } |
3739 | 3746 | ||
@@ -4141,6 +4148,7 @@ static int __init init_ext4_fs(void) | |||
4141 | { | 4148 | { |
4142 | int err; | 4149 | int err; |
4143 | 4150 | ||
4151 | ext4_check_flag_values(); | ||
4144 | err = init_ext4_system_zone(); | 4152 | err = init_ext4_system_zone(); |
4145 | if (err) | 4153 | if (err) |
4146 | return err; | 4154 | return err; |