Skip to content

Commit 3258386

Browse files
Eric Whitneytytso
authored andcommitted
ext4: reset retry counter when ext4_alloc_file_blocks() makes progress
Change the retry policy in ext4_alloc_file_blocks() to allow for a full retry cycle whenever a portion of an allocation request has been fulfilled. A large allocation request often results in multiple calls to ext4_map_blocks(), each of which is potentially subject to a temporary ENOSPC condition and retry cycle. The current code only allows for a single retry cycle. This patch does not address a known bug or reported complaint. However, it should make block allocation for fallocate and zero range more robust. In addition, simplify the conditional controlling the allocation while loop, where testing len alone is sufficient. Remove the assignment to ret2 in the error path after the call to ext4_map_blocks() since its value isn't subsequently used. Signed-off-by: Eric Whitney <enwlinux@gmail.com> Link: https://lore.kernel.org/r/20210113221403.18258-1-enwlinux@gmail.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1 parent b5776e7 commit 3258386

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

fs/ext4/extents.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4382,8 +4382,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
43824382
{
43834383
struct inode *inode = file_inode(file);
43844384
handle_t *handle;
4385-
int ret = 0;
4386-
int ret2 = 0, ret3 = 0;
4385+
int ret, ret2 = 0, ret3 = 0;
43874386
int retries = 0;
43884387
int depth = 0;
43894388
struct ext4_map_blocks map;
@@ -4408,7 +4407,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
44084407
depth = ext_depth(inode);
44094408

44104409
retry:
4411-
while (ret >= 0 && len) {
4410+
while (len) {
44124411
/*
44134412
* Recalculate credits when extent tree depth changes.
44144413
*/
@@ -4430,9 +4429,13 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
44304429
inode->i_ino, map.m_lblk,
44314430
map.m_len, ret);
44324431
ext4_mark_inode_dirty(handle, inode);
4433-
ret2 = ext4_journal_stop(handle);
4432+
ext4_journal_stop(handle);
44344433
break;
44354434
}
4435+
/*
4436+
* allow a full retry cycle for any remaining allocations
4437+
*/
4438+
retries = 0;
44364439
map.m_lblk += ret;
44374440
map.m_len = len = len - ret;
44384441
epos = (loff_t)map.m_lblk << inode->i_blkbits;
@@ -4450,11 +4453,8 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
44504453
if (unlikely(ret2))
44514454
break;
44524455
}
4453-
if (ret == -ENOSPC &&
4454-
ext4_should_retry_alloc(inode->i_sb, &retries)) {
4455-
ret = 0;
4456+
if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
44564457
goto retry;
4457-
}
44584458

44594459
return ret > 0 ? ret2 : ret;
44604460
}

0 commit comments

Comments
 (0)