Re: [PATCH] ext4: stop return ENOSPC from ext4_issue_zeroout
From: Jan Kara <jack@suse.cz>
Date: 2021-08-16 10:05:53
On Fri 13-08-21 11:18:01, Theodore Ts'o wrote:
On Wed, Aug 04, 2021 at 03:35:29PM +0200, Jan Kara wrote:quoted
On Wed 04-08-21 20:50:44, yangerkun wrote:quoted
Our testcase(briefly described as fsstress on dm thin-provisioning which ext4 see volume size with 100G but actual size 10G) trigger a hungtask bug since ext4_writepages fall into a infinite loop: Got ENOSPC with follow stack: ... ext4_ext_map_blocks ext4_ext_convert_to_initialized ext4_ext_zeroout ext4_issue_zeroout ... submit_bio_wait <-- bio to thinpool will return ENOSPCThanks for the patch. As a quick fix for the problem this is probably fine. But longer term we might need to implement a configurable behavior for this because just dropping data on the floor (which is what would happen here) need not be what sysadmin wants and blocking until space is provisioned may be actually a preferable behavior. Anyway for now feel free to add: Reviewed-by: Jan Kara <jack@suse.cz>Hmm, I wonder if this would be a better fix. (Not yet tested, may fry your file system, etc....) What do folks think?
Yes, that looks indeed better. I'd note that even splitting extent may fail due to ENOSPC on thin-provisioned storage but the chances are *much* lower. Honza
quoted hunk ↗ jump to hunk
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 92ad64b89d9b..501516cadc1b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c@@ -3569,7 +3569,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, split_map.m_len - ee_block); err = ext4_ext_zeroout(inode, &zero_ex1); if (err) - goto out; + goto fallback; split_map.m_len = allocated; } if (split_map.m_lblk - ee_block + split_map.m_len <@@ -3583,7 +3583,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, ext4_ext_pblock(ex)); err = ext4_ext_zeroout(inode, &zero_ex2); if (err) - goto out; + goto fallback; } split_map.m_len += split_map.m_lblk - ee_block;@@ -3592,6 +3592,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, } } +fallback: err = ext4_split_extent(handle, inode, ppath, &split_map, split_flag, flags); if (err > 0)
-- Jan Kara [off-list ref] SUSE Labs, CR