You need to sign in or sign up before continuing.
提交 d6cf3853 编写于 作者: J Jan Kara 提交者: Yang Yingliang

ext4: Avoid unnecessary revokes in ext4_alloc_branch()

mainline inclusion
from mainline-5.5-rc1
commit f2890730f8292831b7741d89a65b9c6834d85ee6
category: bugfix
bugzilla: 25031
CVE: NA
---------------------------

Error cleanup path in ext4_alloc_branch() calls ext4_forget() on freshly
allocated indirect blocks with 'metadata' set to 1. This results in
generating revoke records for these blocks. However this is unnecessary
as the freed blocks are only allocated in the current transaction and
thus they will never be journalled. Make this cleanup path similar to
e.g. cleanup in ext4_splice_branch() and use ext4_free_blocks() to
handle block forgetting by passing EXT4_FREE_BLOCKS_FORGET and not
EXT4_FREE_BLOCKS_METADATA to ext4_free_blocks(). This also allows
allocating transaction not to reserve any credits for revoke records.
Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
Signed-off-by: NJan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20191105164437.32602-9-jack@suse.czSigned-off-by: NTheodore Ts'o <tytso@mit.edu>
Signed-off-by: Nzhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: NYang Erkun <yangerkun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 1a5d37a8
...@@ -333,11 +333,14 @@ static int ext4_alloc_branch(handle_t *handle, ...@@ -333,11 +333,14 @@ static int ext4_alloc_branch(handle_t *handle,
for (i = 0; i <= indirect_blks; i++) { for (i = 0; i <= indirect_blks; i++) {
if (i == indirect_blks) { if (i == indirect_blks) {
new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err); new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err);
} else } else {
ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle, ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle,
ar->inode, ar->goal, ar->inode, ar->goal,
ar->flags & EXT4_MB_DELALLOC_RESERVED, ar->flags & EXT4_MB_DELALLOC_RESERVED,
NULL, &err); NULL, &err);
/* Simplify error cleanup... */
branch[i+1].bh = NULL;
}
if (err) { if (err) {
i--; i--;
goto failed; goto failed;
...@@ -379,18 +382,25 @@ static int ext4_alloc_branch(handle_t *handle, ...@@ -379,18 +382,25 @@ static int ext4_alloc_branch(handle_t *handle,
} }
return 0; return 0;
failed: failed:
if (i == indirect_blks) {
/* Free data blocks */
ext4_free_blocks(handle, ar->inode, NULL, new_blocks[i],
ar->len, 0);
i--;
}
for (; i >= 0; i--) { for (; i >= 0; i--) {
/* /*
* We want to ext4_forget() only freshly allocated indirect * We want to ext4_forget() only freshly allocated indirect
* blocks. Buffer for new_blocks[i-1] is at branch[i].bh and * blocks. Buffer for new_blocks[i] is at branch[i+1].bh
* buffer at branch[0].bh is indirect block / inode already * (buffer at branch[0].bh is indirect block / inode already
* existing before ext4_alloc_branch() was called. * existing before ext4_alloc_branch() was called). Also
* because blocks are freshly allocated, we don't need to
* revoke them which is why we don't set
* EXT4_FREE_BLOCKS_METADATA.
*/ */
if (i > 0 && i != indirect_blks && branch[i].bh) ext4_free_blocks(handle, ar->inode, branch[i+1].bh,
ext4_forget(handle, 1, ar->inode, branch[i].bh, new_blocks[i], 1,
branch[i].bh->b_blocknr); branch[i+1].bh ? EXT4_FREE_BLOCKS_FORGET : 0);
ext4_free_blocks(handle, ar->inode, NULL, new_blocks[i],
(i == indirect_blks) ? ar->len : 1, 0);
} }
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册