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 | |
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')
-rw-r--r-- | fs/ext4/balloc.c | 2 | ||||
-rw-r--r-- | fs/ext4/dir.c | 2 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/extents_status.c | 39 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 8 | ||||
-rw-r--r-- | fs/ext4/resize.c | 6 | ||||
-rw-r--r-- | fs/ext4/super.c | 61 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 2 |
8 files changed, 67 insertions, 54 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 2f2e0da1a6b7..92e68b33fffd 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -635,7 +635,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) | |||
635 | brelse(bitmap_bh); | 635 | brelse(bitmap_bh); |
636 | printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu" | 636 | printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu" |
637 | ", computed = %llu, %llu\n", | 637 | ", computed = %llu, %llu\n", |
638 | EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)), | 638 | EXT4_NUM_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)), |
639 | desc_count, bitmap_count); | 639 | desc_count, bitmap_count); |
640 | return bitmap_count; | 640 | return bitmap_count; |
641 | #else | 641 | #else |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 6dda04f05ef4..d8cd1f0f4661 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -334,7 +334,7 @@ static inline loff_t ext4_get_htree_eof(struct file *filp) | |||
334 | * | 334 | * |
335 | * For non-htree, ext4_llseek already chooses the proper max offset. | 335 | * For non-htree, ext4_llseek already chooses the proper max offset. |
336 | */ | 336 | */ |
337 | loff_t ext4_dir_llseek(struct file *file, loff_t offset, int whence) | 337 | static loff_t ext4_dir_llseek(struct file *file, loff_t offset, int whence) |
338 | { | 338 | { |
339 | struct inode *inode = file->f_mapping->host; | 339 | struct inode *inode = file->f_mapping->host; |
340 | int dx_dir = is_dx_dir(inode); | 340 | int dx_dir = is_dx_dir(inode); |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6e16c1867959..4a01ba315262 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1309,6 +1309,7 @@ struct ext4_sb_info { | |||
1309 | /* Reclaim extents from extent status tree */ | 1309 | /* Reclaim extents from extent status tree */ |
1310 | struct shrinker s_es_shrinker; | 1310 | struct shrinker s_es_shrinker; |
1311 | struct list_head s_es_lru; | 1311 | struct list_head s_es_lru; |
1312 | struct percpu_counter s_extent_cache_cnt; | ||
1312 | spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; | 1313 | spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; |
1313 | }; | 1314 | }; |
1314 | 1315 | ||
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index f768f4a98a2b..95796a1b7522 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c | |||
@@ -147,11 +147,12 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, | |||
147 | ext4_lblk_t end); | 147 | ext4_lblk_t end); |
148 | static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, | 148 | static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, |
149 | int nr_to_scan); | 149 | int nr_to_scan); |
150 | static int ext4_es_reclaim_extents_count(struct super_block *sb); | ||
151 | 150 | ||
152 | int __init ext4_init_es(void) | 151 | int __init ext4_init_es(void) |
153 | { | 152 | { |
154 | ext4_es_cachep = KMEM_CACHE(extent_status, SLAB_RECLAIM_ACCOUNT); | 153 | ext4_es_cachep = kmem_cache_create("ext4_extent_status", |
154 | sizeof(struct extent_status), | ||
155 | 0, (SLAB_RECLAIM_ACCOUNT), NULL); | ||
155 | if (ext4_es_cachep == NULL) | 156 | if (ext4_es_cachep == NULL) |
156 | return -ENOMEM; | 157 | return -ENOMEM; |
157 | return 0; | 158 | return 0; |
@@ -302,8 +303,10 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len, | |||
302 | /* | 303 | /* |
303 | * We don't count delayed extent because we never try to reclaim them | 304 | * We don't count delayed extent because we never try to reclaim them |
304 | */ | 305 | */ |
305 | if (!ext4_es_is_delayed(es)) | 306 | if (!ext4_es_is_delayed(es)) { |
306 | EXT4_I(inode)->i_es_lru_nr++; | 307 | EXT4_I(inode)->i_es_lru_nr++; |
308 | percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt); | ||
309 | } | ||
307 | 310 | ||
308 | return es; | 311 | return es; |
309 | } | 312 | } |
@@ -314,6 +317,7 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es) | |||
314 | if (!ext4_es_is_delayed(es)) { | 317 | if (!ext4_es_is_delayed(es)) { |
315 | BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0); | 318 | BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0); |
316 | EXT4_I(inode)->i_es_lru_nr--; | 319 | EXT4_I(inode)->i_es_lru_nr--; |
320 | percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt); | ||
317 | } | 321 | } |
318 | 322 | ||
319 | kmem_cache_free(ext4_es_cachep, es); | 323 | kmem_cache_free(ext4_es_cachep, es); |
@@ -674,10 +678,11 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) | |||
674 | int nr_to_scan = sc->nr_to_scan; | 678 | int nr_to_scan = sc->nr_to_scan; |
675 | int ret, nr_shrunk = 0; | 679 | int ret, nr_shrunk = 0; |
676 | 680 | ||
677 | trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan); | 681 | ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); |
682 | trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret); | ||
678 | 683 | ||
679 | if (!nr_to_scan) | 684 | if (!nr_to_scan) |
680 | return ext4_es_reclaim_extents_count(sbi->s_sb); | 685 | return ret; |
681 | 686 | ||
682 | INIT_LIST_HEAD(&scanned); | 687 | INIT_LIST_HEAD(&scanned); |
683 | 688 | ||
@@ -705,9 +710,10 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) | |||
705 | } | 710 | } |
706 | list_splice_tail(&scanned, &sbi->s_es_lru); | 711 | list_splice_tail(&scanned, &sbi->s_es_lru); |
707 | spin_unlock(&sbi->s_es_lru_lock); | 712 | spin_unlock(&sbi->s_es_lru_lock); |
708 | trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk); | ||
709 | 713 | ||
710 | return ext4_es_reclaim_extents_count(sbi->s_sb); | 714 | ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); |
715 | trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret); | ||
716 | return ret; | ||
711 | } | 717 | } |
712 | 718 | ||
713 | void ext4_es_register_shrinker(struct super_block *sb) | 719 | void ext4_es_register_shrinker(struct super_block *sb) |
@@ -751,25 +757,6 @@ void ext4_es_lru_del(struct inode *inode) | |||
751 | spin_unlock(&sbi->s_es_lru_lock); | 757 | spin_unlock(&sbi->s_es_lru_lock); |
752 | } | 758 | } |
753 | 759 | ||
754 | static int ext4_es_reclaim_extents_count(struct super_block *sb) | ||
755 | { | ||
756 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
757 | struct ext4_inode_info *ei; | ||
758 | struct list_head *cur; | ||
759 | int nr_cached = 0; | ||
760 | |||
761 | spin_lock(&sbi->s_es_lru_lock); | ||
762 | list_for_each(cur, &sbi->s_es_lru) { | ||
763 | ei = list_entry(cur, struct ext4_inode_info, i_es_lru); | ||
764 | read_lock(&ei->i_es_lock); | ||
765 | nr_cached += ei->i_es_lru_nr; | ||
766 | read_unlock(&ei->i_es_lock); | ||
767 | } | ||
768 | spin_unlock(&sbi->s_es_lru_lock); | ||
769 | trace_ext4_es_reclaim_extents_count(sb, nr_cached); | ||
770 | return nr_cached; | ||
771 | } | ||
772 | |||
773 | static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, | 760 | static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, |
774 | int nr_to_scan) | 761 | int nr_to_scan) |
775 | { | 762 | { |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6540ebe058e3..7bb713a46fe4 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -3419,7 +3419,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) | |||
3419 | win = offs; | 3419 | win = offs; |
3420 | 3420 | ||
3421 | ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - | 3421 | ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - |
3422 | EXT4_B2C(sbi, win); | 3422 | EXT4_NUM_B2C(sbi, win); |
3423 | BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical); | 3423 | BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical); |
3424 | BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len); | 3424 | BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len); |
3425 | } | 3425 | } |
@@ -4565,7 +4565,7 @@ do_more: | |||
4565 | EXT4_BLOCKS_PER_GROUP(sb); | 4565 | EXT4_BLOCKS_PER_GROUP(sb); |
4566 | count -= overflow; | 4566 | count -= overflow; |
4567 | } | 4567 | } |
4568 | count_clusters = EXT4_B2C(sbi, count); | 4568 | count_clusters = EXT4_NUM_B2C(sbi, count); |
4569 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); | 4569 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); |
4570 | if (!bitmap_bh) { | 4570 | if (!bitmap_bh) { |
4571 | err = -EIO; | 4571 | err = -EIO; |
@@ -4807,11 +4807,11 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, | |||
4807 | ext4_group_desc_csum_set(sb, block_group, desc); | 4807 | ext4_group_desc_csum_set(sb, block_group, desc); |
4808 | ext4_unlock_group(sb, block_group); | 4808 | ext4_unlock_group(sb, block_group); |
4809 | percpu_counter_add(&sbi->s_freeclusters_counter, | 4809 | percpu_counter_add(&sbi->s_freeclusters_counter, |
4810 | EXT4_B2C(sbi, blocks_freed)); | 4810 | EXT4_NUM_B2C(sbi, blocks_freed)); |
4811 | 4811 | ||
4812 | if (sbi->s_log_groups_per_flex) { | 4812 | if (sbi->s_log_groups_per_flex) { |
4813 | ext4_group_t flex_group = ext4_flex_group(sbi, block_group); | 4813 | ext4_group_t flex_group = ext4_flex_group(sbi, block_group); |
4814 | atomic_add(EXT4_B2C(sbi, blocks_freed), | 4814 | atomic_add(EXT4_NUM_B2C(sbi, blocks_freed), |
4815 | &sbi->s_flex_groups[flex_group].free_clusters); | 4815 | &sbi->s_flex_groups[flex_group].free_clusters); |
4816 | } | 4816 | } |
4817 | 4817 | ||
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index c7f4d7584669..b2c8ee56eb98 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -1247,7 +1247,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, | |||
1247 | 1247 | ||
1248 | ext4_inode_table_set(sb, gdp, group_data->inode_table); | 1248 | ext4_inode_table_set(sb, gdp, group_data->inode_table); |
1249 | ext4_free_group_clusters_set(sb, gdp, | 1249 | ext4_free_group_clusters_set(sb, gdp, |
1250 | EXT4_B2C(sbi, group_data->free_blocks_count)); | 1250 | EXT4_NUM_B2C(sbi, group_data->free_blocks_count)); |
1251 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); | 1251 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); |
1252 | if (ext4_has_group_desc_csum(sb)) | 1252 | if (ext4_has_group_desc_csum(sb)) |
1253 | ext4_itable_unused_set(sb, gdp, | 1253 | ext4_itable_unused_set(sb, gdp, |
@@ -1349,7 +1349,7 @@ static void ext4_update_super(struct super_block *sb, | |||
1349 | 1349 | ||
1350 | /* Update the free space counts */ | 1350 | /* Update the free space counts */ |
1351 | percpu_counter_add(&sbi->s_freeclusters_counter, | 1351 | percpu_counter_add(&sbi->s_freeclusters_counter, |
1352 | EXT4_B2C(sbi, free_blocks)); | 1352 | EXT4_NUM_B2C(sbi, free_blocks)); |
1353 | percpu_counter_add(&sbi->s_freeinodes_counter, | 1353 | percpu_counter_add(&sbi->s_freeinodes_counter, |
1354 | EXT4_INODES_PER_GROUP(sb) * flex_gd->count); | 1354 | EXT4_INODES_PER_GROUP(sb) * flex_gd->count); |
1355 | 1355 | ||
@@ -1360,7 +1360,7 @@ static void ext4_update_super(struct super_block *sb, | |||
1360 | sbi->s_log_groups_per_flex) { | 1360 | sbi->s_log_groups_per_flex) { |
1361 | ext4_group_t flex_group; | 1361 | ext4_group_t flex_group; |
1362 | flex_group = ext4_flex_group(sbi, group_data[0].group); | 1362 | flex_group = ext4_flex_group(sbi, group_data[0].group); |
1363 | atomic_add(EXT4_B2C(sbi, free_blocks), | 1363 | atomic_add(EXT4_NUM_B2C(sbi, free_blocks), |
1364 | &sbi->s_flex_groups[flex_group].free_clusters); | 1364 | &sbi->s_flex_groups[flex_group].free_clusters); |
1365 | atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count, | 1365 | atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count, |
1366 | &sbi->s_flex_groups[flex_group].free_inodes); | 1366 | &sbi->s_flex_groups[flex_group].free_inodes); |
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 { |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b7e2385c6e92..d6ee5aed56b1 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -382,7 +382,7 @@ handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask, | |||
382 | if (err < 0) { | 382 | if (err < 0) { |
383 | jbd2_free_handle(handle); | 383 | jbd2_free_handle(handle); |
384 | current->journal_info = NULL; | 384 | current->journal_info = NULL; |
385 | handle = ERR_PTR(err); | 385 | return ERR_PTR(err); |
386 | } | 386 | } |
387 | handle->h_type = type; | 387 | handle->h_type = type; |
388 | handle->h_line_no = line_no; | 388 | handle->h_line_no = line_no; |