mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									b713a5ec55
								
							
						
					
					
						commit
						9f24e4208f
					
				
					 6 changed files with 30 additions and 37 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
				
			||||||
	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)
 | 
				
			||||||
				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,
 | 
				
			||||||
		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,
 | 
				
			||||||
		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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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,
 | 
				
			||||||
	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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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)
 | 
				
			||||||
	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)
 | 
				
			||||||
		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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue