Commit 9f24e420 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: Use atomic_t's in struct flex_groups

Reduce pressure on the sb_bgl_lock family of locks by using atomic_t's
to track the number of free blocks and inodes in each flex_group.
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent b713a5ec
...@@ -470,9 +470,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, ...@@ -470,9 +470,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
if (sbi->s_log_groups_per_flex) { if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, block_group); ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
spin_lock(sb_bgl_lock(sbi, flex_group)); atomic_add(blocks_freed,
sbi->s_flex_groups[flex_group].free_blocks += blocks_freed; &sbi->s_flex_groups[flex_group].free_blocks);
spin_unlock(sb_bgl_lock(sbi, flex_group));
} }
/* /*
* request to reload the buddy with the * request to reload the buddy with the
......
...@@ -170,8 +170,8 @@ struct ext4_group_desc ...@@ -170,8 +170,8 @@ struct ext4_group_desc
*/ */
struct flex_groups { struct flex_groups {
__u32 free_inodes; atomic_t free_inodes;
__u32 free_blocks; atomic_t free_blocks;
}; };
#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */ #define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */
......
...@@ -189,7 +189,6 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) ...@@ -189,7 +189,6 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
struct ext4_super_block *es; struct ext4_super_block *es;
struct ext4_sb_info *sbi; struct ext4_sb_info *sbi;
int fatal = 0, err, count, cleared; int fatal = 0, err, count, cleared;
ext4_group_t flex_group;
if (atomic_read(&inode->i_count) > 1) { if (atomic_read(&inode->i_count) > 1) {
printk(KERN_ERR "ext4_free_inode: inode has count=%d\n", printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
...@@ -277,10 +276,10 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) ...@@ -277,10 +276,10 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
percpu_counter_dec(&sbi->s_dirs_counter); percpu_counter_dec(&sbi->s_dirs_counter);
if (sbi->s_log_groups_per_flex) { if (sbi->s_log_groups_per_flex) {
flex_group = ext4_flex_group(sbi, block_group); ext4_group_t f;
spin_lock(sb_bgl_lock(sbi, flex_group));
sbi->s_flex_groups[flex_group].free_inodes++; f = ext4_flex_group(sbi, block_group);
spin_unlock(sb_bgl_lock(sbi, flex_group)); atomic_inc(&sbi->s_flex_groups[f].free_inodes);
} }
} }
BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
...@@ -360,9 +359,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent, ...@@ -360,9 +359,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
sbi->s_log_groups_per_flex; sbi->s_log_groups_per_flex;
find_close_to_parent: find_close_to_parent:
flexbg_free_blocks = flex_group[best_flex].free_blocks; flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex; flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
if (flex_group[best_flex].free_inodes && if (atomic_read(&flex_group[best_flex].free_inodes) &&
flex_freeb_ratio > free_block_ratio) flex_freeb_ratio > free_block_ratio)
goto found_flexbg; goto found_flexbg;
...@@ -375,24 +374,24 @@ static int find_group_flex(struct super_block *sb, struct inode *parent, ...@@ -375,24 +374,24 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
if (i == parent_fbg_group || i == parent_fbg_group - 1) if (i == parent_fbg_group || i == parent_fbg_group - 1)
continue; continue;
flexbg_free_blocks = flex_group[i].free_blocks; flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex; flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
if (flex_freeb_ratio > free_block_ratio && if (flex_freeb_ratio > free_block_ratio &&
flex_group[i].free_inodes) { (atomic_read(&flex_group[i].free_inodes))) {
best_flex = i; best_flex = i;
goto found_flexbg; goto found_flexbg;
} }
if (flex_group[best_flex].free_inodes == 0 || if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
(flex_group[i].free_blocks > ((atomic_read(&flex_group[i].free_blocks) >
flex_group[best_flex].free_blocks && atomic_read(&flex_group[best_flex].free_blocks)) &&
flex_group[i].free_inodes)) atomic_read(&flex_group[i].free_inodes)))
best_flex = i; best_flex = i;
} }
if (!flex_group[best_flex].free_inodes || if (!atomic_read(&flex_group[best_flex].free_inodes) ||
!flex_group[best_flex].free_blocks) !atomic_read(&flex_group[best_flex].free_blocks))
return -1; return -1;
found_flexbg: found_flexbg:
...@@ -960,9 +959,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) ...@@ -960,9 +959,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
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);
spin_lock(sb_bgl_lock(sbi, flex_group)); atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
sbi->s_flex_groups[flex_group].free_inodes--;
spin_unlock(sb_bgl_lock(sbi, flex_group));
} }
inode->i_uid = current_fsuid(); inode->i_uid = current_fsuid();
......
...@@ -3044,9 +3044,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, ...@@ -3044,9 +3044,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
if (sbi->s_log_groups_per_flex) { if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, ext4_group_t flex_group = ext4_flex_group(sbi,
ac->ac_b_ex.fe_group); ac->ac_b_ex.fe_group);
spin_lock(sb_bgl_lock(sbi, flex_group)); atomic_sub(ac->ac_b_ex.fe_len,
sbi->s_flex_groups[flex_group].free_blocks -= ac->ac_b_ex.fe_len; &sbi->s_flex_groups[flex_group].free_blocks);
spin_unlock(sb_bgl_lock(sbi, flex_group));
} }
err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
...@@ -4884,9 +4883,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, ...@@ -4884,9 +4883,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
if (sbi->s_log_groups_per_flex) { if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, block_group); ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
spin_lock(sb_bgl_lock(sbi, flex_group)); atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
sbi->s_flex_groups[flex_group].free_blocks += count;
spin_unlock(sb_bgl_lock(sbi, flex_group));
} }
ext4_mb_release_desc(&e4b); ext4_mb_release_desc(&e4b);
......
...@@ -938,10 +938,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) ...@@ -938,10 +938,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
ext4_group_t flex_group; ext4_group_t flex_group;
flex_group = ext4_flex_group(sbi, input->group); flex_group = ext4_flex_group(sbi, input->group);
sbi->s_flex_groups[flex_group].free_blocks += atomic_add(input->free_blocks_count,
input->free_blocks_count; &sbi->s_flex_groups[flex_group].free_blocks);
sbi->s_flex_groups[flex_group].free_inodes += atomic_add(EXT4_INODES_PER_GROUP(sb),
EXT4_INODES_PER_GROUP(sb); &sbi->s_flex_groups[flex_group].free_inodes);
} }
ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
......
...@@ -1630,10 +1630,10 @@ static int ext4_fill_flex_info(struct super_block *sb) ...@@ -1630,10 +1630,10 @@ static int ext4_fill_flex_info(struct super_block *sb)
gdp = ext4_get_group_desc(sb, i, &bh); gdp = ext4_get_group_desc(sb, i, &bh);
flex_group = ext4_flex_group(sbi, i); flex_group = ext4_flex_group(sbi, i);
sbi->s_flex_groups[flex_group].free_inodes += atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,
ext4_free_inodes_count(sb, gdp); ext4_free_inodes_count(sb, gdp));
sbi->s_flex_groups[flex_group].free_blocks += atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
ext4_free_blks_count(sb, gdp); ext4_free_blks_count(sb, gdp));
} }
return 1; return 1;
......
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