diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-02 22:33:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-02 22:33:21 -0500 |
commit | a7c1120d2dcc83691bafa034d98f70285757e826 (patch) | |
tree | 56779f292c2dea78feff290c3ce26724d33b3f3e /fs/ext4/super.c | |
parent | 6ec40b423032ca769c96fbf9a080db822821893d (diff) | |
parent | 9b2ff35753c0512bc8c6adae9e9c87cbeee86f82 (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bug fixes from Ted Ts'o:
"Various bug fixes for ext4. The most important is a fix for the new
extent cache's slab shrinker which can cause significant, user-visible
pauses when the system is under memory pressure."
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: enable quotas before orphan cleanup
ext4: don't allow quota mount options when quota feature enabled
ext4: fix a warning from sparse check for ext4_dir_llseek
ext4: convert number of blocks to clusters properly
ext4: fix possible memory leak in ext4_remount()
jbd2: fix ERR_PTR dereference in jbd2__journal_start
ext4: use percpu counter for extent cache count
ext4: optimize ext4_es_shrink()
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 620cf5615ba2..5e6c87836193 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -783,6 +783,7 @@ static void ext4_put_super(struct super_block *sb) | |||
783 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 783 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
784 | percpu_counter_destroy(&sbi->s_dirs_counter); | 784 | percpu_counter_destroy(&sbi->s_dirs_counter); |
785 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); | 785 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); |
786 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); | ||
786 | brelse(sbi->s_sbh); | 787 | brelse(sbi->s_sbh); |
787 | #ifdef CONFIG_QUOTA | 788 | #ifdef CONFIG_QUOTA |
788 | for (i = 0; i < MAXQUOTAS; i++) | 789 | for (i = 0; i < MAXQUOTAS; i++) |
@@ -1247,6 +1248,11 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) | |||
1247 | "quota options when quota turned on"); | 1248 | "quota options when quota turned on"); |
1248 | return -1; | 1249 | return -1; |
1249 | } | 1250 | } |
1251 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) { | ||
1252 | ext4_msg(sb, KERN_ERR, "Cannot set journaled quota options " | ||
1253 | "when QUOTA feature is enabled"); | ||
1254 | return -1; | ||
1255 | } | ||
1250 | qname = match_strdup(args); | 1256 | qname = match_strdup(args); |
1251 | if (!qname) { | 1257 | if (!qname) { |
1252 | ext4_msg(sb, KERN_ERR, | 1258 | ext4_msg(sb, KERN_ERR, |
@@ -1544,6 +1550,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1544 | "quota options when quota turned on"); | 1550 | "quota options when quota turned on"); |
1545 | return -1; | 1551 | return -1; |
1546 | } | 1552 | } |
1553 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
1554 | EXT4_FEATURE_RO_COMPAT_QUOTA)) { | ||
1555 | ext4_msg(sb, KERN_ERR, | ||
1556 | "Cannot set journaled quota options " | ||
1557 | "when QUOTA feature is enabled"); | ||
1558 | return -1; | ||
1559 | } | ||
1547 | sbi->s_jquota_fmt = m->mount_opt; | 1560 | sbi->s_jquota_fmt = m->mount_opt; |
1548 | #endif | 1561 | #endif |
1549 | } else { | 1562 | } else { |
@@ -1592,6 +1605,12 @@ static int parse_options(char *options, struct super_block *sb, | |||
1592 | return 0; | 1605 | return 0; |
1593 | } | 1606 | } |
1594 | #ifdef CONFIG_QUOTA | 1607 | #ifdef CONFIG_QUOTA |
1608 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && | ||
1609 | (test_opt(sb, USRQUOTA) || test_opt(sb, GRPQUOTA))) { | ||
1610 | ext4_msg(sb, KERN_ERR, "Cannot set quota options when QUOTA " | ||
1611 | "feature is enabled"); | ||
1612 | return 0; | ||
1613 | } | ||
1595 | if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { | 1614 | if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { |
1596 | if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA]) | 1615 | if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA]) |
1597 | clear_opt(sb, USRQUOTA); | 1616 | clear_opt(sb, USRQUOTA); |
@@ -3161,7 +3180,7 @@ int ext4_calculate_overhead(struct super_block *sb) | |||
3161 | } | 3180 | } |
3162 | /* Add the journal blocks as well */ | 3181 | /* Add the journal blocks as well */ |
3163 | if (sbi->s_journal) | 3182 | if (sbi->s_journal) |
3164 | overhead += EXT4_B2C(sbi, sbi->s_journal->j_maxlen); | 3183 | overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen); |
3165 | 3184 | ||
3166 | sbi->s_overhead = overhead; | 3185 | sbi->s_overhead = overhead; |
3167 | smp_wmb(); | 3186 | smp_wmb(); |
@@ -3688,6 +3707,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3688 | if (!err) { | 3707 | if (!err) { |
3689 | err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0); | 3708 | err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0); |
3690 | } | 3709 | } |
3710 | if (!err) { | ||
3711 | err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0); | ||
3712 | } | ||
3691 | if (err) { | 3713 | if (err) { |
3692 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | 3714 | ext4_msg(sb, KERN_ERR, "insufficient memory"); |
3693 | goto failed_mount3; | 3715 | goto failed_mount3; |
@@ -3711,13 +3733,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3711 | sb->s_export_op = &ext4_export_ops; | 3733 | sb->s_export_op = &ext4_export_ops; |
3712 | sb->s_xattr = ext4_xattr_handlers; | 3734 | sb->s_xattr = ext4_xattr_handlers; |
3713 | #ifdef CONFIG_QUOTA | 3735 | #ifdef CONFIG_QUOTA |
3714 | sb->s_qcop = &ext4_qctl_operations; | ||
3715 | sb->dq_op = &ext4_quota_operations; | 3736 | sb->dq_op = &ext4_quota_operations; |
3716 | 3737 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) | |
3717 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) { | ||
3718 | /* Use qctl operations for hidden quota files. */ | ||
3719 | sb->s_qcop = &ext4_qctl_sysfile_operations; | 3738 | sb->s_qcop = &ext4_qctl_sysfile_operations; |
3720 | } | 3739 | else |
3740 | sb->s_qcop = &ext4_qctl_operations; | ||
3721 | #endif | 3741 | #endif |
3722 | memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); | 3742 | memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); |
3723 | 3743 | ||
@@ -3913,6 +3933,16 @@ no_journal: | |||
3913 | if (err) | 3933 | if (err) |
3914 | goto failed_mount7; | 3934 | goto failed_mount7; |
3915 | 3935 | ||
3936 | #ifdef CONFIG_QUOTA | ||
3937 | /* Enable quota usage during mount. */ | ||
3938 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && | ||
3939 | !(sb->s_flags & MS_RDONLY)) { | ||
3940 | err = ext4_enable_quotas(sb); | ||
3941 | if (err) | ||
3942 | goto failed_mount8; | ||
3943 | } | ||
3944 | #endif /* CONFIG_QUOTA */ | ||
3945 | |||
3916 | EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS; | 3946 | EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS; |
3917 | ext4_orphan_cleanup(sb, es); | 3947 | ext4_orphan_cleanup(sb, es); |
3918 | EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS; | 3948 | EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS; |
@@ -3930,16 +3960,6 @@ no_journal: | |||
3930 | } else | 3960 | } else |
3931 | descr = "out journal"; | 3961 | descr = "out journal"; |
3932 | 3962 | ||
3933 | #ifdef CONFIG_QUOTA | ||
3934 | /* Enable quota usage during mount. */ | ||
3935 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && | ||
3936 | !(sb->s_flags & MS_RDONLY)) { | ||
3937 | err = ext4_enable_quotas(sb); | ||
3938 | if (err) | ||
3939 | goto failed_mount8; | ||
3940 | } | ||
3941 | #endif /* CONFIG_QUOTA */ | ||
3942 | |||
3943 | if (test_opt(sb, DISCARD)) { | 3963 | if (test_opt(sb, DISCARD)) { |
3944 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | 3964 | struct request_queue *q = bdev_get_queue(sb->s_bdev); |
3945 | if (!blk_queue_discard(q)) | 3965 | if (!blk_queue_discard(q)) |
@@ -3993,6 +4013,7 @@ failed_mount3: | |||
3993 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 4013 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
3994 | percpu_counter_destroy(&sbi->s_dirs_counter); | 4014 | percpu_counter_destroy(&sbi->s_dirs_counter); |
3995 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); | 4015 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); |
4016 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); | ||
3996 | if (sbi->s_mmp_tsk) | 4017 | if (sbi->s_mmp_tsk) |
3997 | kthread_stop(sbi->s_mmp_tsk); | 4018 | kthread_stop(sbi->s_mmp_tsk); |
3998 | failed_mount2: | 4019 | failed_mount2: |
@@ -4538,6 +4559,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
4538 | if (!old_opts.s_qf_names[i]) { | 4559 | if (!old_opts.s_qf_names[i]) { |
4539 | for (j = 0; j < i; j++) | 4560 | for (j = 0; j < i; j++) |
4540 | kfree(old_opts.s_qf_names[j]); | 4561 | kfree(old_opts.s_qf_names[j]); |
4562 | kfree(orig_data); | ||
4541 | return -ENOMEM; | 4563 | return -ENOMEM; |
4542 | } | 4564 | } |
4543 | } else | 4565 | } else |
@@ -4816,9 +4838,12 @@ static int ext4_release_dquot(struct dquot *dquot) | |||
4816 | 4838 | ||
4817 | static int ext4_mark_dquot_dirty(struct dquot *dquot) | 4839 | static int ext4_mark_dquot_dirty(struct dquot *dquot) |
4818 | { | 4840 | { |
4841 | struct super_block *sb = dquot->dq_sb; | ||
4842 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
4843 | |||
4819 | /* Are we journaling quotas? */ | 4844 | /* Are we journaling quotas? */ |
4820 | if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || | 4845 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) || |
4821 | EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { | 4846 | sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { |
4822 | dquot_mark_dquot_dirty(dquot); | 4847 | dquot_mark_dquot_dirty(dquot); |
4823 | return ext4_write_dquot(dquot); | 4848 | return ext4_write_dquot(dquot); |
4824 | } else { | 4849 | } else { |