Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 654b4908 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Theodore Ts'o
Browse files

ext4: cleanup block allocator



Move the code related to block allocation to a single function and add helper
funtions to differient allocation for data and meta data blocks

Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarMingming Cao <cmm@us.ibm.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 7061eba7
Loading
Loading
Loading
Loading
+74 −53
Original line number Original line Diff line number Diff line
@@ -1640,20 +1640,24 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
}
}


/**
/**
 * ext4_new_blocks_old() -- core block(s) allocation function
 * ext4_old_new_blocks() -- core block bitmap based block allocation function
 *
 * @handle:		handle to this transaction
 * @handle:		handle to this transaction
 * @inode:		file inode
 * @inode:		file inode
 * @goal:		given target block(filesystem wide)
 * @goal:		given target block(filesystem wide)
 * @count:		target number of blocks to allocate
 * @count:		target number of blocks to allocate
 * @errp:		error code
 * @errp:		error code
 *
 *
 * ext4_new_blocks uses a goal block to assist allocation.  It tries to
 * ext4_old_new_blocks uses a goal block to assist allocation and look up
 * allocate block(s) from the block group contains the goal block first. If that
 * the block bitmap directly to do block allocation.  It tries to
 * fails, it will try to allocate block(s) from other block groups without
 * allocate block(s) from the block group contains the goal block first. If
 * any specific goal block.
 * that fails, it will try to allocate block(s) from other block groups
 * without any specific goal block.
 *
 * This function is called when -o nomballoc mount option is enabled
 *
 *
 */
 */
ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
			ext4_fsblk_t goal, unsigned long *count, int *errp)
			ext4_fsblk_t goal, unsigned long *count, int *errp)
{
{
	struct buffer_head *bitmap_bh = NULL;
	struct buffer_head *bitmap_bh = NULL;
@@ -1923,78 +1927,95 @@ ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
	return 0;
	return 0;
}
}


ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
#define EXT4_META_BLOCK 0x1
		ext4_fsblk_t goal, int *errp)
{
	struct ext4_allocation_request ar;
	ext4_fsblk_t ret;

	if (!test_opt(inode->i_sb, MBALLOC)) {
		unsigned long count = 1;
		ret = ext4_new_blocks_old(handle, inode, goal, &count, errp);
		return ret;
	}

	memset(&ar, 0, sizeof(ar));
	ar.inode = inode;
	ar.goal = goal;
	ar.len = 1;
	ret = ext4_mb_new_blocks(handle, &ar, errp);
	return ret;
}
ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
		ext4_fsblk_t goal, unsigned long *count, int *errp)
{
	struct ext4_allocation_request ar;
	ext4_fsblk_t ret;

	if (!test_opt(inode->i_sb, MBALLOC)) {
		ret = ext4_new_blocks_old(handle, inode, goal, count, errp);
		return ret;
	}

	memset(&ar, 0, sizeof(ar));
	ar.inode = inode;
	ar.goal = goal;
	ar.len = *count;
	ret = ext4_mb_new_blocks(handle, &ar, errp);
	*count = ar.len;
	return ret;
}


ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode,
				ext4_lblk_t iblock, ext4_fsblk_t goal,
				ext4_lblk_t iblock, ext4_fsblk_t goal,
				unsigned long *count, int *errp)
				unsigned long *count, int *errp, int flags)
{
{
	struct ext4_allocation_request ar;
	struct ext4_allocation_request ar;
	ext4_fsblk_t ret;
	ext4_fsblk_t ret;


	if (!test_opt(inode->i_sb, MBALLOC)) {
	if (!test_opt(inode->i_sb, MBALLOC)) {
		ret = ext4_new_blocks_old(handle, inode, goal, count, errp);
		return ext4_old_new_blocks(handle, inode, goal, count, errp);
		return ret;
	}
	}


	memset(&ar, 0, sizeof(ar));
	memset(&ar, 0, sizeof(ar));
	/* Fill with neighbour allocated blocks */
	/* Fill with neighbour allocated blocks */
	ar.lleft  = 0;
	ar.pleft  = 0;
	ar.lright = 0;
	ar.pright = 0;


	ar.inode = inode;
	ar.inode = inode;
	ar.goal = goal;
	ar.goal = goal;
	ar.len = *count;
	ar.len = *count;
	ar.logical = iblock;
	ar.logical = iblock;
	if (S_ISREG(inode->i_mode))

	if (S_ISREG(inode->i_mode) && !(flags & EXT4_META_BLOCK))
		/* enable in-core preallocation for data block allocation */
		ar.flags = EXT4_MB_HINT_DATA;
		ar.flags = EXT4_MB_HINT_DATA;
	else
	else
		/* disable in-core preallocation for non-regular files */
		/* disable in-core preallocation for non-regular files */
		ar.flags = 0;
		ar.flags = 0;

	ret = ext4_mb_new_blocks(handle, &ar, errp);
	ret = ext4_mb_new_blocks(handle, &ar, errp);
	*count = ar.len;
	*count = ar.len;
	return ret;
	return ret;
}
}


/*
 * ext4_new_meta_block() -- allocate block for meta data (indexing) blocks
 *
 * @handle:             handle to this transaction
 * @inode:              file inode
 * @goal:               given target block(filesystem wide)
 * @errp:               error code
 *
 * Return allocated block number on success
 */
ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
		ext4_fsblk_t goal, int *errp)
{
	unsigned long count = 1;
	return do_blk_alloc(handle, inode, 0, goal,
			&count, errp, EXT4_META_BLOCK);
}

/*
 * ext4_new_meta_blocks() -- allocate block for meta data (indexing) blocks
 *
 * @handle:             handle to this transaction
 * @inode:              file inode
 * @goal:               given target block(filesystem wide)
 * @count:		total number of blocks need
 * @errp:               error code
 *
 * Return 1st allocated block numberon success, *count stores total account
 * error stores in errp pointer
 */
ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
		ext4_fsblk_t goal, unsigned long *count, int *errp)
{
	return do_blk_alloc(handle, inode, 0, goal,
			count, errp, EXT4_META_BLOCK);
}

/*
 * ext4_new_blocks() -- allocate data blocks
 *
 * @handle:             handle to this transaction
 * @inode:              file inode
 * @goal:               given target block(filesystem wide)
 * @count:		total number of blocks need
 * @errp:               error code
 *
 * Return 1st allocated block numberon success, *count stores total account
 * error stores in errp pointer
 */

ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
				ext4_lblk_t iblock, ext4_fsblk_t goal,
				unsigned long *count, int *errp)
{
	return do_blk_alloc(handle, inode, iblock, goal, count, errp, 0);
}


/**
/**
 * ext4_count_free_blocks() -- count filesystem free blocks
 * ext4_count_free_blocks() -- count filesystem free blocks
+1 −1
Original line number Original line Diff line number Diff line
@@ -977,7 +977,7 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
					ext4_lblk_t iblock, ext4_fsblk_t goal,
					ext4_lblk_t iblock, ext4_fsblk_t goal,
					unsigned long *count, int *errp);
					unsigned long *count, int *errp);
extern ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
			ext4_fsblk_t goal, unsigned long *count, int *errp);
			ext4_fsblk_t goal, unsigned long *count, int *errp);
extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
			ext4_fsblk_t block, unsigned long count, int metadata);
			ext4_fsblk_t block, unsigned long count, int metadata);
+7 −3
Original line number Original line Diff line number Diff line
@@ -179,8 +179,11 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
	return bg_start + colour + block;
	return bg_start + colour + block;
}
}


/*
 * Allocation for a meta data block
 */
static ext4_fsblk_t
static ext4_fsblk_t
ext4_ext_new_block(handle_t *handle, struct inode *inode,
ext4_ext_new_meta_block(handle_t *handle, struct inode *inode,
			struct ext4_ext_path *path,
			struct ext4_ext_path *path,
			struct ext4_extent *ex, int *err)
			struct ext4_extent *ex, int *err)
{
{
@@ -690,7 +693,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
	/* allocate all needed blocks */
	/* allocate all needed blocks */
	ext_debug("allocate %d blocks for indexes/leaf\n", depth - at);
	ext_debug("allocate %d blocks for indexes/leaf\n", depth - at);
	for (a = 0; a < depth - at; a++) {
	for (a = 0; a < depth - at; a++) {
		newblock = ext4_ext_new_block(handle, inode, path, newext, &err);
		newblock = ext4_ext_new_meta_block(handle, inode, path,
						   newext, &err);
		if (newblock == 0)
		if (newblock == 0)
			goto cleanup;
			goto cleanup;
		ablocks[a] = newblock;
		ablocks[a] = newblock;
@@ -886,7 +890,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
	ext4_fsblk_t newblock;
	ext4_fsblk_t newblock;
	int err = 0;
	int err = 0;


	newblock = ext4_ext_new_block(handle, inode, path, newext, &err);
	newblock = ext4_ext_new_meta_block(handle, inode, path, newext, &err);
	if (newblock == 0)
	if (newblock == 0)
		return err;
		return err;


+1 −1
Original line number Original line Diff line number Diff line
@@ -561,7 +561,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
		goto allocated;
		goto allocated;
	/* Now allocate data blocks */
	/* Now allocate data blocks */
	count = target;
	count = target;
	/* allocating blocks for indirect blocks and direct blocks */
	/* allocating blocks for data blocks */
	current_block = ext4_new_blocks(handle, inode, iblock,
	current_block = ext4_new_blocks(handle, inode, iblock,
						goal, &count, err);
						goal, &count, err);
	if (*err && (target == blks)) {
	if (*err && (target == blks)) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -4041,7 +4041,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
	sbi = EXT4_SB(sb);
	sbi = EXT4_SB(sb);


	if (!test_opt(sb, MBALLOC)) {
	if (!test_opt(sb, MBALLOC)) {
		block = ext4_new_blocks_old(handle, ar->inode, ar->goal,
		block = ext4_old_new_blocks(handle, ar->inode, ar->goal,
					    &(ar->len), errp);
					    &(ar->len), errp);
		return block;
		return block;
	}
	}