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

Commit 15a84cf4 authored by Baokun Li's avatar Baokun Li Committed by Greg Kroah-Hartman
Browse files

ext4: using nofail preallocation in ext4_es_insert_extent()



[ Upstream commit 2a69c450083db164596c75c0f5b4d9c4c0e18eba ]

Similar to in ext4_es_insert_delayed_block(), we use preallocations that
do not fail to avoid inconsistencies, but we do not care about es that are
not must be kept, and we return 0 even if such es memory allocation fails.

Suggested-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20230424033846.4732-9-libaokun1@huawei.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Stable-dep-of: 8e387c89e96b ("ext4: make sure allocate pending entry not fail")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 80c8dcb0
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -832,8 +832,11 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
{
	struct extent_status newes;
	ext4_lblk_t end = lblk + len - 1;
	int err = 0;
	int err1 = 0;
	int err2 = 0;
	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
	struct extent_status *es1 = NULL;
	struct extent_status *es2 = NULL;

	es_debug("add [%u/%u) %llu %x to extent status tree of inode %lu\n",
		 lblk, len, pblk, status, inode->i_ino);
@@ -858,29 +861,40 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,

	ext4_es_insert_extent_check(inode, &newes);

retry:
	if (err1 && !es1)
		es1 = __es_alloc_extent(true);
	if ((err1 || err2) && !es2)
		es2 = __es_alloc_extent(true);
	write_lock(&EXT4_I(inode)->i_es_lock);
	err = __es_remove_extent(inode, lblk, end, NULL, NULL);
	if (err != 0)

	err1 = __es_remove_extent(inode, lblk, end, NULL, es1);
	if (err1 != 0)
		goto error;

	err2 = __es_insert_extent(inode, &newes, es2);
	if (err2 == -ENOMEM && !ext4_es_must_keep(&newes))
		err2 = 0;
	if (err2 != 0)
		goto error;
retry:
	err = __es_insert_extent(inode, &newes, NULL);
	if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb),
					  128, EXT4_I(inode)))
		goto retry;
	if (err == -ENOMEM && !ext4_es_must_keep(&newes))
		err = 0;

	if (sbi->s_cluster_ratio > 1 && test_opt(inode->i_sb, DELALLOC) &&
	    (status & EXTENT_STATUS_WRITTEN ||
	     status & EXTENT_STATUS_UNWRITTEN))
		__revise_pending(inode, lblk, len);

	/* es is pre-allocated but not used, free it. */
	if (es1 && !es1->es_len)
		__es_free_extent(es1);
	if (es2 && !es2->es_len)
		__es_free_extent(es2);
error:
	write_unlock(&EXT4_I(inode)->i_es_lock);
	if (err1 || err2)
		goto retry;

	ext4_es_print_tree(inode);

	return err;
	return 0;
}

/*