ext4: Use struct flex_groups to calculate get_orlov_stats()
authorTheodore Ts'o <tytso@mit.edu>
Thu, 5 Mar 2009 00:31:53 +0000 (19:31 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 5 Mar 2009 00:31:53 +0000 (19:31 -0500)
Instead of looping over all of the block groups in a flex group
summing their summary statistics, start tracking used_dirs in struct
flex_groups, and use struct flex_groups instead.  This should save a
bit of CPU for mkdir-heavy workloads.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/ialloc.c
fs/ext4/super.c

index e52b48f..46aaaa2 100644 (file)
@@ -172,6 +172,7 @@ struct ext4_group_desc
 struct flex_groups {
        atomic_t free_inodes;
        atomic_t free_blocks;
+       atomic_t used_dirs;
 };
 
 #define EXT4_BG_INODE_UNINIT   0x0001 /* Inode table/bitmap not in use */
index 5f39392..47b84e8 100644 (file)
@@ -267,6 +267,13 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
                        if (is_directory) {
                                count = ext4_used_dirs_count(sb, gdp) - 1;
                                ext4_used_dirs_set(sb, gdp, count);
+                               if (sbi->s_log_groups_per_flex) {
+                                       ext4_group_t f;
+
+                                       f = ext4_flex_group(sbi, block_group);
+                                       atomic_dec(&sbi->s_flex_groups[f].free_inodes);
+                               }
+
                        }
                        gdp->bg_checksum = ext4_group_desc_csum(sbi,
                                                        block_group, gdp);
@@ -424,25 +431,24 @@ void get_orlov_stats(struct super_block *sb, ext4_group_t g,
                       int flex_size, struct orlov_stats *stats)
 {
        struct ext4_group_desc *desc;
-       ext4_group_t            ngroups = EXT4_SB(sb)->s_groups_count;
-       int                     i;
-
-       stats->free_inodes = 0;
-       stats->free_blocks = 0;
-       stats->used_dirs = 0;
+       struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups;
 
-       g *= flex_size;
-
-       for (i = 0; i < flex_size; i++) {
-               if (g >= ngroups)
-                       break;
-               desc = ext4_get_group_desc(sb, g++, NULL);
-               if (!desc)
-                       continue;
+       if (flex_size > 1) {
+               stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
+               stats->free_blocks = atomic_read(&flex_group[g].free_blocks);
+               stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
+               return;
+       }
 
-               stats->free_inodes += ext4_free_inodes_count(sb, desc);
-               stats->free_blocks += ext4_free_blks_count(sb, desc);
-               stats->used_dirs += ext4_used_dirs_count(sb, desc);
+       desc = ext4_get_group_desc(sb, g, NULL);
+       if (desc) {
+               stats->free_inodes = ext4_free_inodes_count(sb, desc);
+               stats->free_blocks = ext4_free_blks_count(sb, desc);
+               stats->used_dirs = ext4_used_dirs_count(sb, desc);
+       } else {
+               stats->free_inodes = 0;
+               stats->free_blocks = 0;
+               stats->used_dirs = 0;
        }
 }
 
@@ -765,6 +771,11 @@ static int ext4_claim_inode(struct super_block *sb,
        if (S_ISDIR(mode)) {
                count = ext4_used_dirs_count(sb, gdp) + 1;
                ext4_used_dirs_set(sb, gdp, count);
+               if (sbi->s_log_groups_per_flex) {
+                       ext4_group_t f = ext4_flex_group(sbi, group);
+
+                       atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+               }
        }
        gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
 err_ret:
index 6b5d5c6..b9aefce 100644 (file)
@@ -1634,6 +1634,8 @@ static int ext4_fill_flex_info(struct super_block *sb)
                           ext4_free_inodes_count(sb, gdp));
                atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
                           ext4_free_blks_count(sb, gdp));
+               atomic_set(&sbi->s_flex_groups[flex_group].used_dirs,
+                          ext4_used_dirs_count(sb, gdp));
        }
 
        return 1;