Skip to content

Commit 9f24e42

Browse files
committed
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: "Theodore Ts'o" <tytso@mit.edu>
1 parent b713a5e commit 9f24e42

File tree

6 files changed

+30
-37
lines changed

6 files changed

+30
-37
lines changed

fs/ext4/balloc.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
470470

471471
if (sbi->s_log_groups_per_flex) {
472472
ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
473-
spin_lock(sb_bgl_lock(sbi, flex_group));
474-
sbi->s_flex_groups[flex_group].free_blocks += blocks_freed;
475-
spin_unlock(sb_bgl_lock(sbi, flex_group));
473+
atomic_add(blocks_freed,
474+
&sbi->s_flex_groups[flex_group].free_blocks);
476475
}
477476
/*
478477
* request to reload the buddy with the

fs/ext4/ext4.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ struct ext4_group_desc
170170
*/
171171

172172
struct flex_groups {
173-
__u32 free_inodes;
174-
__u32 free_blocks;
173+
atomic_t free_inodes;
174+
atomic_t free_blocks;
175175
};
176176

177177
#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */

fs/ext4/ialloc.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
189189
struct ext4_super_block *es;
190190
struct ext4_sb_info *sbi;
191191
int fatal = 0, err, count, cleared;
192-
ext4_group_t flex_group;
193192

194193
if (atomic_read(&inode->i_count) > 1) {
195194
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)
277276
percpu_counter_dec(&sbi->s_dirs_counter);
278277

279278
if (sbi->s_log_groups_per_flex) {
280-
flex_group = ext4_flex_group(sbi, block_group);
281-
spin_lock(sb_bgl_lock(sbi, flex_group));
282-
sbi->s_flex_groups[flex_group].free_inodes++;
283-
spin_unlock(sb_bgl_lock(sbi, flex_group));
279+
ext4_group_t f;
280+
281+
f = ext4_flex_group(sbi, block_group);
282+
atomic_inc(&sbi->s_flex_groups[f].free_inodes);
284283
}
285284
}
286285
BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
@@ -360,9 +359,9 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
360359
sbi->s_log_groups_per_flex;
361360

362361
find_close_to_parent:
363-
flexbg_free_blocks = flex_group[best_flex].free_blocks;
362+
flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
364363
flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
365-
if (flex_group[best_flex].free_inodes &&
364+
if (atomic_read(&flex_group[best_flex].free_inodes) &&
366365
flex_freeb_ratio > free_block_ratio)
367366
goto found_flexbg;
368367

@@ -375,24 +374,24 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,
375374
if (i == parent_fbg_group || i == parent_fbg_group - 1)
376375
continue;
377376

378-
flexbg_free_blocks = flex_group[i].free_blocks;
377+
flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
379378
flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
380379

381380
if (flex_freeb_ratio > free_block_ratio &&
382-
flex_group[i].free_inodes) {
381+
(atomic_read(&flex_group[i].free_inodes))) {
383382
best_flex = i;
384383
goto found_flexbg;
385384
}
386385

387-
if (flex_group[best_flex].free_inodes == 0 ||
388-
(flex_group[i].free_blocks >
389-
flex_group[best_flex].free_blocks &&
390-
flex_group[i].free_inodes))
386+
if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
387+
((atomic_read(&flex_group[i].free_blocks) >
388+
atomic_read(&flex_group[best_flex].free_blocks)) &&
389+
atomic_read(&flex_group[i].free_inodes)))
391390
best_flex = i;
392391
}
393392

394-
if (!flex_group[best_flex].free_inodes ||
395-
!flex_group[best_flex].free_blocks)
393+
if (!atomic_read(&flex_group[best_flex].free_inodes) ||
394+
!atomic_read(&flex_group[best_flex].free_blocks))
396395
return -1;
397396

398397
found_flexbg:
@@ -960,9 +959,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
960959

961960
if (sbi->s_log_groups_per_flex) {
962961
flex_group = ext4_flex_group(sbi, group);
963-
spin_lock(sb_bgl_lock(sbi, flex_group));
964-
sbi->s_flex_groups[flex_group].free_inodes--;
965-
spin_unlock(sb_bgl_lock(sbi, flex_group));
962+
atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
966963
}
967964

968965
inode->i_uid = current_fsuid();

fs/ext4/mballoc.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,9 +3044,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
30443044
if (sbi->s_log_groups_per_flex) {
30453045
ext4_group_t flex_group = ext4_flex_group(sbi,
30463046
ac->ac_b_ex.fe_group);
3047-
spin_lock(sb_bgl_lock(sbi, flex_group));
3048-
sbi->s_flex_groups[flex_group].free_blocks -= ac->ac_b_ex.fe_len;
3049-
spin_unlock(sb_bgl_lock(sbi, flex_group));
3047+
atomic_sub(ac->ac_b_ex.fe_len,
3048+
&sbi->s_flex_groups[flex_group].free_blocks);
30503049
}
30513050

30523051
err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -4884,9 +4883,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
48844883

48854884
if (sbi->s_log_groups_per_flex) {
48864885
ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
4887-
spin_lock(sb_bgl_lock(sbi, flex_group));
4888-
sbi->s_flex_groups[flex_group].free_blocks += count;
4889-
spin_unlock(sb_bgl_lock(sbi, flex_group));
4886+
atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
48904887
}
48914888

48924889
ext4_mb_release_desc(&e4b);

fs/ext4/resize.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -938,10 +938,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
938938
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
939939
ext4_group_t flex_group;
940940
flex_group = ext4_flex_group(sbi, input->group);
941-
sbi->s_flex_groups[flex_group].free_blocks +=
942-
input->free_blocks_count;
943-
sbi->s_flex_groups[flex_group].free_inodes +=
944-
EXT4_INODES_PER_GROUP(sb);
941+
atomic_add(input->free_blocks_count,
942+
&sbi->s_flex_groups[flex_group].free_blocks);
943+
atomic_add(EXT4_INODES_PER_GROUP(sb),
944+
&sbi->s_flex_groups[flex_group].free_inodes);
945945
}
946946

947947
ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);

fs/ext4/super.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,10 +1630,10 @@ static int ext4_fill_flex_info(struct super_block *sb)
16301630
gdp = ext4_get_group_desc(sb, i, &bh);
16311631

16321632
flex_group = ext4_flex_group(sbi, i);
1633-
sbi->s_flex_groups[flex_group].free_inodes +=
1634-
ext4_free_inodes_count(sb, gdp);
1635-
sbi->s_flex_groups[flex_group].free_blocks +=
1636-
ext4_free_blks_count(sb, gdp);
1633+
atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,
1634+
ext4_free_inodes_count(sb, gdp));
1635+
atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
1636+
ext4_free_blks_count(sb, gdp));
16371637
}
16381638

16391639
return 1;

0 commit comments

Comments
 (0)