Commit a0375156 authored by Theodore Ts'o's avatar Theodore Ts'o

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: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 7e27d6e7
...@@ -377,14 +377,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, ...@@ -377,14 +377,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
ext4_grpblk_t bit; ext4_grpblk_t bit;
unsigned int i; unsigned int i;
struct ext4_group_desc *desc; struct ext4_group_desc *desc;
struct ext4_super_block *es; struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_sb_info *sbi;
int err = 0, ret, blk_free_count; int err = 0, ret, blk_free_count;
ext4_grpblk_t blocks_freed; ext4_grpblk_t blocks_freed;
struct ext4_group_info *grp; struct ext4_group_info *grp;
sbi = EXT4_SB(sb);
es = sbi->s_es;
ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1);
ext4_get_group_no_and_offset(sb, block, &block_group, &bit); 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,7 +474,6 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
if (!err) if (!err)
err = ret; err = ret;
sb->s_dirt = 1;
error_return: error_return:
brelse(bitmap_bh); brelse(bitmap_bh);
......
...@@ -1860,6 +1860,12 @@ static inline void ext4_unlock_group(struct super_block *sb, ...@@ -1860,6 +1860,12 @@ static inline void ext4_unlock_group(struct super_block *sb,
spin_unlock(ext4_group_lock_ptr(sb, group)); spin_unlock(ext4_group_lock_ptr(sb, group));
} }
static inline void ext4_mark_super_dirty(struct super_block *sb)
{
if (EXT4_SB(sb)->s_journal == NULL)
sb->s_dirt =1;
}
/* /*
* Inodes and files operations * Inodes and files operations
*/ */
......
...@@ -143,3 +143,19 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, ...@@ -143,3 +143,19 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
} }
return err; return err;
} }
int __ext4_handle_dirty_super(const char *where, handle_t *handle,
struct super_block *sb)
{
struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
int err = 0;
if (ext4_handle_valid(handle)) {
err = jbd2_journal_dirty_metadata(handle, bh);
if (err)
ext4_journal_abort_handle(where, __func__, bh,
handle, err);
} else
sb->s_dirt = 1;
return err;
}
...@@ -141,6 +141,9 @@ int __ext4_journal_get_create_access(const char *where, ...@@ -141,6 +141,9 @@ int __ext4_journal_get_create_access(const char *where,
int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
struct inode *inode, struct buffer_head *bh); struct inode *inode, struct buffer_head *bh);
int __ext4_handle_dirty_super(const char *where, handle_t *handle,
struct super_block *sb);
#define ext4_journal_get_undo_access(handle, bh) \ #define ext4_journal_get_undo_access(handle, bh) \
__ext4_journal_get_undo_access(__func__, (handle), (bh)) __ext4_journal_get_undo_access(__func__, (handle), (bh))
#define ext4_journal_get_write_access(handle, bh) \ #define ext4_journal_get_write_access(handle, bh) \
...@@ -152,6 +155,8 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, ...@@ -152,6 +155,8 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
__ext4_journal_get_create_access(__func__, (handle), (bh)) __ext4_journal_get_create_access(__func__, (handle), (bh))
#define ext4_handle_dirty_metadata(handle, inode, bh) \ #define ext4_handle_dirty_metadata(handle, inode, bh) \
__ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh)) __ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh))
#define ext4_handle_dirty_super(handle, sb) \
__ext4_handle_dirty_super(__func__, (handle), (sb))
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
int __ext4_journal_stop(const char *where, handle_t *handle); int __ext4_journal_stop(const char *where, handle_t *handle);
......
...@@ -123,7 +123,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) ...@@ -123,7 +123,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
if (!IS_ERR(cp)) { if (!IS_ERR(cp)) {
memcpy(sbi->s_es->s_last_mounted, cp, memcpy(sbi->s_es->s_last_mounted, cp,
sizeof(sbi->s_es->s_last_mounted)); sizeof(sbi->s_es->s_last_mounted));
sb->s_dirt = 1; ext4_mark_super_dirty(sb);
} }
} }
return dquot_file_open(inode, filp); return dquot_file_open(inode, filp);
......
...@@ -279,7 +279,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) ...@@ -279,7 +279,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
if (!fatal) if (!fatal)
fatal = err; fatal = err;
sb->s_dirt = 1; ext4_mark_super_dirty(sb);
} else } else
ext4_error(sb, "bit already cleared for inode %lu", ino); ext4_error(sb, "bit already cleared for inode %lu", ino);
...@@ -965,7 +965,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode, ...@@ -965,7 +965,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
percpu_counter_dec(&sbi->s_freeinodes_counter); percpu_counter_dec(&sbi->s_freeinodes_counter);
if (S_ISDIR(mode)) if (S_ISDIR(mode))
percpu_counter_inc(&sbi->s_dirs_counter); percpu_counter_inc(&sbi->s_dirs_counter);
sb->s_dirt = 1; ext4_mark_super_dirty(sb);
if (sbi->s_log_groups_per_flex) { if (sbi->s_log_groups_per_flex) {
flex_group = ext4_flex_group(sbi, group); flex_group = ext4_flex_group(sbi, group);
......
...@@ -2812,7 +2812,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, ...@@ -2812,7 +2812,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh); err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh);
out_err: out_err:
sb->s_dirt = 1; ext4_mark_super_dirty(sb);
brelse(bitmap_bh); brelse(bitmap_bh);
return err; return err;
} }
...@@ -4680,7 +4680,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, ...@@ -4680,7 +4680,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
put_bh(bitmap_bh); put_bh(bitmap_bh);
goto do_more; goto do_more;
} }
sb->s_dirt = 1; ext4_mark_super_dirty(sb);
error_return: error_return:
if (freed) if (freed)
dquot_free_block(inode, freed); dquot_free_block(inode, freed);
......
...@@ -921,8 +921,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) ...@@ -921,8 +921,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
&sbi->s_flex_groups[flex_group].free_inodes); &sbi->s_flex_groups[flex_group].free_inodes);
} }
ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); ext4_handle_dirty_super(handle, sb);
sb->s_dirt = 1;
exit_journal: exit_journal:
mutex_unlock(&sbi->s_resize_lock); mutex_unlock(&sbi->s_resize_lock);
...@@ -1045,13 +1044,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, ...@@ -1045,13 +1044,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
goto exit_put; goto exit_put;
} }
ext4_blocks_count_set(es, o_blocks_count + add); ext4_blocks_count_set(es, o_blocks_count + add);
ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
sb->s_dirt = 1;
mutex_unlock(&EXT4_SB(sb)->s_resize_lock); mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add); o_blocks_count + add);
/* We add the blocks to the bitmap and set the group need init bit */ /* We add the blocks to the bitmap and set the group need init bit */
ext4_add_groupblocks(handle, sb, o_blocks_count, add); ext4_add_groupblocks(handle, sb, o_blocks_count, add);
ext4_handle_dirty_super(handle, sb);
ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add); o_blocks_count + add);
if ((err = ext4_journal_stop(handle))) if ((err = ext4_journal_stop(handle)))
......
...@@ -458,8 +458,7 @@ static void ext4_xattr_update_super_block(handle_t *handle, ...@@ -458,8 +458,7 @@ static void ext4_xattr_update_super_block(handle_t *handle,
if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR); EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR);
sb->s_dirt = 1; ext4_handle_dirty_super(handle, sb);
ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment