aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-03-04 19:09:10 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-03-04 19:09:10 -0500
commit9f24e4208f7ee2748f157368b63287dc903fcf60 (patch)
tree255989fe69ebfb2b031dc7cf6dbe975df67c711a
parentb713a5ec55bf73c833f9883cdd761b20ee61a1ab (diff)
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>
-rw-r--r--fs/ext4/balloc.c5
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/ialloc.c33
-rw-r--r--fs/ext4/mballoc.c9
-rw-r--r--fs/ext4/resize.c8
-rw-r--r--fs/ext4/super.c8
6 files changed, 30 insertions, 37 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index b37b12875582..53c72ad85877 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -470,9 +470,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
470 470
471 if (sbi->s_log_groups_per_flex) { 471 if (sbi->s_log_groups_per_flex) {
472 ext4_group_t flex_group = ext4_flex_group(sbi, block_group); 472 ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
473 spin_lock(sb_bgl_lock(sbi, flex_group)); 473 atomic_add(blocks_freed,
474 sbi->s_flex_groups[flex_group].free_blocks += blocks_freed; 474 &sbi->s_flex_groups[flex_group].free_blocks);
475 spin_unlock(sb_bgl_lock(sbi, flex_group));
476 } 475 }
477 /* 476 /*
478 * request to reload the buddy with the 477 * request to reload the buddy with the
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index e5c273ff928b..e52b48f86ed4 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -170,8 +170,8 @@ struct ext4_group_desc
170 */ 170 */
171 171
172struct flex_groups { 172struct flex_groups {
173 __u32 free_inodes; 173 atomic_t free_inodes;
174 __u32 free_blocks; 174 atomic_t free_blocks;
175}; 175};
176 176
177#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */ 177#define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 617f5a2d800a..5f393927fd25 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -189,7 +189,6 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
189 struct ext4_super_block *es; 189 struct ext4_super_block *es;
190 struct ext4_sb_info *sbi; 190 struct ext4_sb_info *sbi;
191 int fatal = 0, err, count, cleared; 191 int fatal = 0, err, count, cleared;
192 ext4_group_t flex_group;
193 192
194 if (atomic_read(&inode->i_count) > 1) { 193 if (atomic_read(&inode->i_count) > 1) {
195 printk(KERN_ERR "ext4_free_inode: inode has count=%d\n", 194 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 percpu_counter_dec(&sbi->s_dirs_counter); 276 percpu_counter_dec(&sbi->s_dirs_counter);
278 277
279 if (sbi->s_log_groups_per_flex) { 278 if (sbi->s_log_groups_per_flex) {
280 flex_group = ext4_flex_group(sbi, block_group); 279 ext4_group_t f;
281 spin_lock(sb_bgl_lock(sbi, flex_group)); 280
282 sbi->s_flex_groups[flex_group].free_inodes++; 281 f = ext4_flex_group(sbi, block_group);
283 spin_unlock(sb_bgl_lock(sbi, flex_group)); 282 atomic_inc(&sbi->s_flex_groups[f].free_inodes);
284 } 283 }
285 } 284 }
286 BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); 285 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 sbi->s_log_groups_per_flex; 359 sbi->s_log_groups_per_flex;
361 360
362find_close_to_parent: 361find_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);
364 flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex; 363 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) &&
366 flex_freeb_ratio > free_block_ratio) 365 flex_freeb_ratio > free_block_ratio)
367 goto found_flexbg; 366 goto found_flexbg;
368 367
@@ -375,24 +374,24 @@ find_close_to_parent:
375 if (i == parent_fbg_group || i == parent_fbg_group - 1) 374 if (i == parent_fbg_group || i == parent_fbg_group - 1)
376 continue; 375 continue;
377 376
378 flexbg_free_blocks = flex_group[i].free_blocks; 377 flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
379 flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex; 378 flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
380 379
381 if (flex_freeb_ratio > free_block_ratio && 380 if (flex_freeb_ratio > free_block_ratio &&
382 flex_group[i].free_inodes) { 381 (atomic_read(&flex_group[i].free_inodes))) {
383 best_flex = i; 382 best_flex = i;
384 goto found_flexbg; 383 goto found_flexbg;
385 } 384 }
386 385
387 if (flex_group[best_flex].free_inodes == 0 || 386 if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
388 (flex_group[i].free_blocks > 387 ((atomic_read(&flex_group[i].free_blocks) >
389 flex_group[best_flex].free_blocks && 388 atomic_read(&flex_group[best_flex].free_blocks)) &&
390 flex_group[i].free_inodes)) 389 atomic_read(&flex_group[i].free_inodes)))
391 best_flex = i; 390 best_flex = i;
392 } 391 }
393 392
394 if (!flex_group[best_flex].free_inodes || 393 if (!atomic_read(&flex_group[best_flex].free_inodes) ||
395 !flex_group[best_flex].free_blocks) 394 !atomic_read(&flex_group[best_flex].free_blocks))
396 return -1; 395 return -1;
397 396
398found_flexbg: 397found_flexbg:
@@ -960,9 +959,7 @@ got:
960 959
961 if (sbi->s_log_groups_per_flex) { 960 if (sbi->s_log_groups_per_flex) {
962 flex_group = ext4_flex_group(sbi, group); 961 flex_group = ext4_flex_group(sbi, group);
963 spin_lock(sb_bgl_lock(sbi, flex_group)); 962 atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
964 sbi->s_flex_groups[flex_group].free_inodes--;
965 spin_unlock(sb_bgl_lock(sbi, flex_group));
966 } 963 }
967 964
968 inode->i_uid = current_fsuid(); 965 inode->i_uid = current_fsuid();
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index c4c430977622..e72c72a0b807 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -3044,9 +3044,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
3044 if (sbi->s_log_groups_per_flex) { 3044 if (sbi->s_log_groups_per_flex) {
3045 ext4_group_t flex_group = ext4_flex_group(sbi, 3045 ext4_group_t flex_group = ext4_flex_group(sbi,
3046 ac->ac_b_ex.fe_group); 3046 ac->ac_b_ex.fe_group);
3047 spin_lock(sb_bgl_lock(sbi, flex_group)); 3047 atomic_sub(ac->ac_b_ex.fe_len,
3048 sbi->s_flex_groups[flex_group].free_blocks -= ac->ac_b_ex.fe_len; 3048 &sbi->s_flex_groups[flex_group].free_blocks);
3049 spin_unlock(sb_bgl_lock(sbi, flex_group));
3050 } 3049 }
3051 3050
3052 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); 3051 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -4884,9 +4883,7 @@ do_more:
4884 4883
4885 if (sbi->s_log_groups_per_flex) { 4884 if (sbi->s_log_groups_per_flex) {
4886 ext4_group_t flex_group = ext4_flex_group(sbi, block_group); 4885 ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
4887 spin_lock(sb_bgl_lock(sbi, flex_group)); 4886 atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
4888 sbi->s_flex_groups[flex_group].free_blocks += count;
4889 spin_unlock(sb_bgl_lock(sbi, flex_group));
4890 } 4887 }
4891 4888
4892 ext4_mb_release_desc(&e4b); 4889 ext4_mb_release_desc(&e4b);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index c06886abd658..546c7dd869e1 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -938,10 +938,10 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
938 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { 938 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
939 ext4_group_t flex_group; 939 ext4_group_t flex_group;
940 flex_group = ext4_flex_group(sbi, input->group); 940 flex_group = ext4_flex_group(sbi, input->group);
941 sbi->s_flex_groups[flex_group].free_blocks += 941 atomic_add(input->free_blocks_count,
942 input->free_blocks_count; 942 &sbi->s_flex_groups[flex_group].free_blocks);
943 sbi->s_flex_groups[flex_group].free_inodes += 943 atomic_add(EXT4_INODES_PER_GROUP(sb),
944 EXT4_INODES_PER_GROUP(sb); 944 &sbi->s_flex_groups[flex_group].free_inodes);
945 } 945 }
946 946
947 ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); 947 ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 1ec554cc107a..6b5d5c6399fa 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1630,10 +1630,10 @@ static int ext4_fill_flex_info(struct super_block *sb)
1630 gdp = ext4_get_group_desc(sb, i, &bh); 1630 gdp = ext4_get_group_desc(sb, i, &bh);
1631 1631
1632 flex_group = ext4_flex_group(sbi, i); 1632 flex_group = ext4_flex_group(sbi, i);
1633 sbi->s_flex_groups[flex_group].free_inodes += 1633 atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,
1634 ext4_free_inodes_count(sb, gdp); 1634 ext4_free_inodes_count(sb, gdp));
1635 sbi->s_flex_groups[flex_group].free_blocks += 1635 atomic_set(&sbi->s_flex_groups[flex_group].free_blocks,
1636 ext4_free_blks_count(sb, gdp); 1636 ext4_free_blks_count(sb, gdp));
1637 } 1637 }
1638 1638
1639 return 1; 1639 return 1;