diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-06-11 23:14:04 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-06-11 23:14:04 -0400 |
commit | a0375156ca1041574b5d47cc7e32f10b891151b0 (patch) | |
tree | b791961012b9348f289c3dda5dc071bdf9b736d2 /fs/ext4 | |
parent | 7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff) |
ext4: Clean up s_dirt handling
We don't need to set s_dirt in most of the ext4 code when journaling
is enabled. In ext3/4 some of the summary statistics for # of free
inodes, blocks, and directories are calculated from the per-block
group statistics when the file system is mounted or unmounted. As a
result the superblock doesn't have to be updated, either via the
journal or by setting s_dirt. There are a few exceptions, most
notably when resizing the file system, where the superblock needs to
be modified --- and in that case it should be done as a journalled
operation if possible, and s_dirt set only in no-journal mode.
This patch will optimize out some unneeded disk writes when using ext4
with a journal.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/balloc.c | 6 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 6 | ||||
-rw-r--r-- | fs/ext4/ext4_jbd2.c | 16 | ||||
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 5 | ||||
-rw-r--r-- | fs/ext4/file.c | 2 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 4 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 4 | ||||
-rw-r--r-- | fs/ext4/resize.c | 6 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 3 |
9 files changed, 36 insertions, 16 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 95b7594c76f9..bd30799a43ed 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -377,14 +377,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
377 | ext4_grpblk_t bit; | 377 | ext4_grpblk_t bit; |
378 | unsigned int i; | 378 | unsigned int i; |
379 | struct ext4_group_desc *desc; | 379 | struct ext4_group_desc *desc; |
380 | struct ext4_super_block *es; | 380 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
381 | struct ext4_sb_info *sbi; | ||
382 | int err = 0, ret, blk_free_count; | 381 | int err = 0, ret, blk_free_count; |
383 | ext4_grpblk_t blocks_freed; | 382 | ext4_grpblk_t blocks_freed; |
384 | struct ext4_group_info *grp; | 383 | struct ext4_group_info *grp; |
385 | 384 | ||
386 | sbi = EXT4_SB(sb); | ||
387 | es = sbi->s_es; | ||
388 | ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); | 385 | ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); |
389 | 386 | ||
390 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); | 387 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); |
@@ -477,7 +474,6 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
477 | ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); | 474 | ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); |
478 | if (!err) | 475 | if (!err) |
479 | err = ret; | 476 | err = ret; |
480 | sb->s_dirt = 1; | ||
481 | 477 | ||
482 | error_return: | 478 | error_return: |
483 | brelse(bitmap_bh); | 479 | brelse(bitmap_bh); |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 19a4de57128a..8b56b53328eb 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1860,6 +1860,12 @@ static inline void ext4_unlock_group(struct super_block *sb, | |||
1860 | spin_unlock(ext4_group_lock_ptr(sb, group)); | 1860 | spin_unlock(ext4_group_lock_ptr(sb, group)); |
1861 | } | 1861 | } |
1862 | 1862 | ||
1863 | static inline void ext4_mark_super_dirty(struct super_block *sb) | ||
1864 | { | ||
1865 | if (EXT4_SB(sb)->s_journal == NULL) | ||
1866 | sb->s_dirt =1; | ||
1867 | } | ||
1868 | |||
1863 | /* | 1869 | /* |
1864 | * Inodes and files operations | 1870 | * Inodes and files operations |
1865 | */ | 1871 | */ |
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 53d2764d71ca..cfd27b38fa15 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
@@ -143,3 +143,19 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, | |||
143 | } | 143 | } |
144 | return err; | 144 | return err; |
145 | } | 145 | } |
146 | |||
147 | int __ext4_handle_dirty_super(const char *where, handle_t *handle, | ||
148 | struct super_block *sb) | ||
149 | { | ||
150 | struct buffer_head *bh = EXT4_SB(sb)->s_sbh; | ||
151 | int err = 0; | ||
152 | |||
153 | if (ext4_handle_valid(handle)) { | ||
154 | err = jbd2_journal_dirty_metadata(handle, bh); | ||
155 | if (err) | ||
156 | ext4_journal_abort_handle(where, __func__, bh, | ||
157 | handle, err); | ||
158 | } else | ||
159 | sb->s_dirt = 1; | ||
160 | return err; | ||
161 | } | ||
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index dade0c024797..8ae8168900bf 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -141,6 +141,9 @@ int __ext4_journal_get_create_access(const char *where, | |||
141 | int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, | 141 | int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, |
142 | struct inode *inode, struct buffer_head *bh); | 142 | struct inode *inode, struct buffer_head *bh); |
143 | 143 | ||
144 | int __ext4_handle_dirty_super(const char *where, handle_t *handle, | ||
145 | struct super_block *sb); | ||
146 | |||
144 | #define ext4_journal_get_undo_access(handle, bh) \ | 147 | #define ext4_journal_get_undo_access(handle, bh) \ |
145 | __ext4_journal_get_undo_access(__func__, (handle), (bh)) | 148 | __ext4_journal_get_undo_access(__func__, (handle), (bh)) |
146 | #define ext4_journal_get_write_access(handle, bh) \ | 149 | #define ext4_journal_get_write_access(handle, bh) \ |
@@ -152,6 +155,8 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, | |||
152 | __ext4_journal_get_create_access(__func__, (handle), (bh)) | 155 | __ext4_journal_get_create_access(__func__, (handle), (bh)) |
153 | #define ext4_handle_dirty_metadata(handle, inode, bh) \ | 156 | #define ext4_handle_dirty_metadata(handle, inode, bh) \ |
154 | __ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh)) | 157 | __ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh)) |
158 | #define ext4_handle_dirty_super(handle, sb) \ | ||
159 | __ext4_handle_dirty_super(__func__, (handle), (sb)) | ||
155 | 160 | ||
156 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); | 161 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); |
157 | int __ext4_journal_stop(const char *where, handle_t *handle); | 162 | int __ext4_journal_stop(const char *where, handle_t *handle); |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 5313ae4cda2d..bd411c12d63d 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -123,7 +123,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
123 | if (!IS_ERR(cp)) { | 123 | if (!IS_ERR(cp)) { |
124 | memcpy(sbi->s_es->s_last_mounted, cp, | 124 | memcpy(sbi->s_es->s_last_mounted, cp, |
125 | sizeof(sbi->s_es->s_last_mounted)); | 125 | sizeof(sbi->s_es->s_last_mounted)); |
126 | sb->s_dirt = 1; | 126 | ext4_mark_super_dirty(sb); |
127 | } | 127 | } |
128 | } | 128 | } |
129 | return dquot_file_open(inode, filp); | 129 | return dquot_file_open(inode, filp); |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 25c4b3173fd9..ac377505ed57 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -279,7 +279,7 @@ out: | |||
279 | err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); | 279 | err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); |
280 | if (!fatal) | 280 | if (!fatal) |
281 | fatal = err; | 281 | fatal = err; |
282 | sb->s_dirt = 1; | 282 | ext4_mark_super_dirty(sb); |
283 | } else | 283 | } else |
284 | ext4_error(sb, "bit already cleared for inode %lu", ino); | 284 | ext4_error(sb, "bit already cleared for inode %lu", ino); |
285 | 285 | ||
@@ -965,7 +965,7 @@ got: | |||
965 | percpu_counter_dec(&sbi->s_freeinodes_counter); | 965 | percpu_counter_dec(&sbi->s_freeinodes_counter); |
966 | if (S_ISDIR(mode)) | 966 | if (S_ISDIR(mode)) |
967 | percpu_counter_inc(&sbi->s_dirs_counter); | 967 | percpu_counter_inc(&sbi->s_dirs_counter); |
968 | sb->s_dirt = 1; | 968 | ext4_mark_super_dirty(sb); |
969 | 969 | ||
970 | if (sbi->s_log_groups_per_flex) { | 970 | if (sbi->s_log_groups_per_flex) { |
971 | flex_group = ext4_flex_group(sbi, group); | 971 | flex_group = ext4_flex_group(sbi, group); |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 12b3bc026a68..d9d267181ddc 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2812,7 +2812,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2812 | err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh); | 2812 | err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh); |
2813 | 2813 | ||
2814 | out_err: | 2814 | out_err: |
2815 | sb->s_dirt = 1; | 2815 | ext4_mark_super_dirty(sb); |
2816 | brelse(bitmap_bh); | 2816 | brelse(bitmap_bh); |
2817 | return err; | 2817 | return err; |
2818 | } | 2818 | } |
@@ -4680,7 +4680,7 @@ do_more: | |||
4680 | put_bh(bitmap_bh); | 4680 | put_bh(bitmap_bh); |
4681 | goto do_more; | 4681 | goto do_more; |
4682 | } | 4682 | } |
4683 | sb->s_dirt = 1; | 4683 | ext4_mark_super_dirty(sb); |
4684 | error_return: | 4684 | error_return: |
4685 | if (freed) | 4685 | if (freed) |
4686 | dquot_free_block(inode, freed); | 4686 | dquot_free_block(inode, freed); |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 6df797eb9aeb..27527ae466ea 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -921,8 +921,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
921 | &sbi->s_flex_groups[flex_group].free_inodes); | 921 | &sbi->s_flex_groups[flex_group].free_inodes); |
922 | } | 922 | } |
923 | 923 | ||
924 | ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); | 924 | ext4_handle_dirty_super(handle, sb); |
925 | sb->s_dirt = 1; | ||
926 | 925 | ||
927 | exit_journal: | 926 | exit_journal: |
928 | mutex_unlock(&sbi->s_resize_lock); | 927 | mutex_unlock(&sbi->s_resize_lock); |
@@ -1045,13 +1044,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
1045 | goto exit_put; | 1044 | goto exit_put; |
1046 | } | 1045 | } |
1047 | ext4_blocks_count_set(es, o_blocks_count + add); | 1046 | ext4_blocks_count_set(es, o_blocks_count + add); |
1048 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); | ||
1049 | sb->s_dirt = 1; | ||
1050 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); | 1047 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); |
1051 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, | 1048 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, |
1052 | o_blocks_count + add); | 1049 | o_blocks_count + add); |
1053 | /* We add the blocks to the bitmap and set the group need init bit */ | 1050 | /* We add the blocks to the bitmap and set the group need init bit */ |
1054 | ext4_add_groupblocks(handle, sb, o_blocks_count, add); | 1051 | ext4_add_groupblocks(handle, sb, o_blocks_count, add); |
1052 | ext4_handle_dirty_super(handle, sb); | ||
1055 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, | 1053 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, |
1056 | o_blocks_count + add); | 1054 | o_blocks_count + add); |
1057 | if ((err = ext4_journal_stop(handle))) | 1055 | if ((err = ext4_journal_stop(handle))) |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 04338009793a..a6f314249574 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -458,8 +458,7 @@ static void ext4_xattr_update_super_block(handle_t *handle, | |||
458 | 458 | ||
459 | if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { | 459 | if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { |
460 | EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR); | 460 | EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR); |
461 | sb->s_dirt = 1; | 461 | ext4_handle_dirty_super(handle, sb); |
462 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); | ||
463 | } | 462 | } |
464 | } | 463 | } |
465 | 464 | ||