Skip to content

Commit

Permalink
ext4: Clean up s_dirt handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tytso committed Jun 12, 2010
1 parent 7e27d6e commit a037515
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 16 deletions.
6 changes: 1 addition & 5 deletions fs/ext4/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,14 +377,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
ext4_grpblk_t bit;
unsigned int i;
struct ext4_group_desc *desc;
struct ext4_super_block *es;
struct ext4_sb_info *sbi;
struct ext4_sb_info *sbi = EXT4_SB(sb);
int err = 0, ret, blk_free_count;
ext4_grpblk_t blocks_freed;
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_get_group_no_and_offset(sb, block, &block_group, &bit);
Expand Down Expand Up @@ -477,7 +474,6 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
if (!err)
err = ret;
sb->s_dirt = 1;

error_return:
brelse(bitmap_bh);
Expand Down
6 changes: 6 additions & 0 deletions fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1860,6 +1860,12 @@ static inline void ext4_unlock_group(struct super_block *sb,
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
*/
Expand Down
16 changes: 16 additions & 0 deletions fs/ext4/ext4_jbd2.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,19 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
}
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;
}
5 changes: 5 additions & 0 deletions fs/ext4/ext4_jbd2.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ int __ext4_journal_get_create_access(const char *where,
int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
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) \
__ext4_journal_get_undo_access(__func__, (handle), (bh))
#define ext4_journal_get_write_access(handle, bh) \
Expand All @@ -152,6 +155,8 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
__ext4_journal_get_create_access(__func__, (handle), (bh))
#define ext4_handle_dirty_metadata(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);
int __ext4_journal_stop(const char *where, handle_t *handle);
Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
if (!IS_ERR(cp)) {
memcpy(sbi->s_es->s_last_mounted, cp,
sizeof(sbi->s_es->s_last_mounted));
sb->s_dirt = 1;
ext4_mark_super_dirty(sb);
}
}
return dquot_file_open(inode, filp);
Expand Down
4 changes: 2 additions & 2 deletions fs/ext4/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
if (!fatal)
fatal = err;
sb->s_dirt = 1;
ext4_mark_super_dirty(sb);
} else
ext4_error(sb, "bit already cleared for inode %lu", ino);

Expand Down Expand Up @@ -965,7 +965,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
percpu_counter_dec(&sbi->s_freeinodes_counter);
if (S_ISDIR(mode))
percpu_counter_inc(&sbi->s_dirs_counter);
sb->s_dirt = 1;
ext4_mark_super_dirty(sb);

if (sbi->s_log_groups_per_flex) {
flex_group = ext4_flex_group(sbi, group);
Expand Down
4 changes: 2 additions & 2 deletions fs/ext4/mballoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh);

out_err:
sb->s_dirt = 1;
ext4_mark_super_dirty(sb);
brelse(bitmap_bh);
return err;
}
Expand Down Expand Up @@ -4680,7 +4680,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
put_bh(bitmap_bh);
goto do_more;
}
sb->s_dirt = 1;
ext4_mark_super_dirty(sb);
error_return:
if (freed)
dquot_free_block(inode, freed);
Expand Down
6 changes: 2 additions & 4 deletions fs/ext4/resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
sb->s_dirt = 1;
ext4_handle_dirty_super(handle, sb);

exit_journal:
mutex_unlock(&sbi->s_resize_lock);
Expand Down Expand Up @@ -1045,13 +1044,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
goto exit_put;
}
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);
ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add);
/* We add the blocks to the bitmap and set the group need init bit */
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,
o_blocks_count + add);
if ((err = ext4_journal_stop(handle)))
Expand Down
3 changes: 1 addition & 2 deletions fs/ext4/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR);
sb->s_dirt = 1;
ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
ext4_handle_dirty_super(handle, sb);
}
}

Expand Down

0 comments on commit a037515

Please sign in to comment.