ext4: Clean up s_dirt handling
authorTheodore Ts'o <tytso@mit.edu>
Sat, 12 Jun 2010 03:14:04 +0000 (23:14 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 12 Jun 2010 03:14:04 +0000 (23:14 -0400)
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>
fs/ext4/balloc.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/ext4_jbd2.h
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/mballoc.c
fs/ext4/resize.c
fs/ext4/xattr.c

index 95b7594c76f909d5b029e9d80001f90ef99e45a4..bd30799a43ed0c527a80b024c356eb55e457f953 100644 (file)
@@ -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);
@@ -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);
index 19a4de57128ad7e493ec7843050d1fccc7bda8a4..8b56b53328ebfa8a2f27e7b0830eb96da9f86335 100644 (file)
@@ -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
  */
index 53d2764d71caee518c5a3639c65d5708456ed25c..cfd27b38fa15f6dbe4a2e526397cf65f2b2a2541 100644 (file)
@@ -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;
+}
index dade0c024797f7fed6082ea4dff6de927d698afd..8ae8168900bf8e9588dd9b9b6761e33003fb9049 100644 (file)
@@ -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) \
@@ -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);
index 5313ae4cda2d2149d58efc5f228e4973f1e8f33f..bd411c12d63d8362b520c520790ceb4662eabd77 100644 (file)
@@ -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);
index 25c4b3173fd935f1550ce89116344a72f9f02374..ac377505ed57a2aa4b319cd868ffcd90db29dc5d 100644 (file)
@@ -279,7 +279,7 @@ out:
                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);
 
@@ -965,7 +965,7 @@ got:
        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);
index 12b3bc026a683cd7b321fbae0e32839e8764e571..d9d267181ddca771bcde0b694f6d56ad16b615cd 100644 (file)
@@ -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;
 }
@@ -4680,7 +4680,7 @@ do_more:
                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);
index 6df797eb9aeb60ab1504298f266edb0977d10be9..27527ae466ea38bbdba55fd8dda8a05486dc44b1 100644 (file)
@@ -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);
@@ -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)))
index 04338009793abcfbfa384d1c0f9528cc3236adc6..a6f314249574d1605337aa3cb4844f1cc188e0a0 100644 (file)
@@ -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);
        }
 }