Commit 1850d76c authored by Zhang Yi's avatar Zhang Yi Committed by Theodore Ts'o
Browse files

ext4: make ext4_insert_delayed_block() insert multi-blocks



Rename ext4_insert_delayed_block() to ext4_insert_delayed_blocks(),
pass length parameter to make it insert multiple delalloc blocks at a
time. For non-bigalloc case, just reserve len blocks and insert delalloc
extent. For bigalloc case, we can ensure that the clusters in the middle
of a extent must be unallocated, we only need to check whether the start
and end clusters are delayed/allocated. We should subtract the space for
the start and/or end block(s) if they are allocated.

Signed-off-by: default avatarZhang Yi <yi.zhang@huawei.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20240517124005.347221-10-yi.zhang@huaweicloud.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 49bf6ab4
Loading
Loading
Loading
Loading
+36 −15
Original line number Diff line number Diff line
@@ -1679,24 +1679,29 @@ static int ext4_clu_alloc_state(struct inode *inode, ext4_lblk_t lblk)
}

/*
 * ext4_insert_delayed_block - adds a delayed block to the extents status
 *                             tree, incrementing the reserved cluster/block
 *                             count or making a pending reservation
 *                             where needed
 * ext4_insert_delayed_blocks - adds a multiple delayed blocks to the extents
 *                              status tree, incrementing the reserved
 *                              cluster/block count or making pending
 *                              reservations where needed
 *
 * @inode - file containing the newly added block
 * @lblk - logical block to be added
 * @lblk - start logical block to be added
 * @len - length of blocks to be added
 *
 * Returns 0 on success, negative error code on failure.
 */
static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
static int ext4_insert_delayed_blocks(struct inode *inode, ext4_lblk_t lblk,
				      ext4_lblk_t len)
{
	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
	int ret;
	bool allocated = false;
	bool lclu_allocated = false;
	bool end_allocated = false;
	ext4_lblk_t resv_clu;
	ext4_lblk_t end = lblk + len - 1;

	/*
	 * If the cluster containing lblk is shared with a delayed,
	 * If the cluster containing lblk or end is shared with a delayed,
	 * written, or unwritten extent in a bigalloc file system, it's
	 * already been accounted for and does not need to be reserved.
	 * A pending reservation must be made for the cluster if it's
@@ -1707,23 +1712,39 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
	 * extents status tree doesn't get a match.
	 */
	if (sbi->s_cluster_ratio == 1) {
		ret = ext4_da_reserve_space(inode, 1);
		ret = ext4_da_reserve_space(inode, len);
		if (ret != 0)   /* ENOSPC */
			return ret;
	} else {   /* bigalloc */
		resv_clu = EXT4_B2C(sbi, end) - EXT4_B2C(sbi, lblk) + 1;

		ret = ext4_clu_alloc_state(inode, lblk);
		if (ret < 0)
			return ret;
		if (ret == 2)
			allocated = true;
		if (ret == 0) {
			ret = ext4_da_reserve_space(inode, 1);
		if (ret > 0) {
			resv_clu--;
			lclu_allocated = (ret == 2);
		}

		if (EXT4_B2C(sbi, lblk) != EXT4_B2C(sbi, end)) {
			ret = ext4_clu_alloc_state(inode, end);
			if (ret < 0)
				return ret;
			if (ret > 0) {
				resv_clu--;
				end_allocated = (ret == 2);
			}
		}

		if (resv_clu) {
			ret = ext4_da_reserve_space(inode, resv_clu);
			if (ret != 0)   /* ENOSPC */
				return ret;
		}
	}

	ext4_es_insert_delayed_extent(inode, lblk, 1, allocated, false);
	ext4_es_insert_delayed_extent(inode, lblk, len, lclu_allocated,
				      end_allocated);
	return 0;
}

@@ -1828,7 +1849,7 @@ static int ext4_da_map_blocks(struct inode *inode, struct ext4_map_blocks *map,
		}
	}

	retval = ext4_insert_delayed_block(inode, map->m_lblk);
	retval = ext4_insert_delayed_blocks(inode, map->m_lblk, map->m_len);
	up_write(&EXT4_I(inode)->i_data_sem);
	if (retval)
		return retval;