提交 fe752c6c 编写于 作者: J Jan Kara 提交者: sanglipeng

udf: Fix preallocation discarding at indirect extent boundary

stable inclusion
from stable-v5.10.161
commit 1a075f4a549481ce6e8518d8379f193ccec6b746
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7P7OH

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=1a075f4a549481ce6e8518d8379f193ccec6b746

--------------------------------

commit cfe4c1b2 upstream.

When preallocation extent is the first one in the extent block, the
code would corrupt extent tree header instead. Fix the problem and use
udf_delete_aext() for deleting extent to avoid some code duplication.

CC: stable@vger.kernel.org
Signed-off-by: NJan Kara <jack@suse.cz>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Nsanglipeng <sanglipeng1@jd.com>
上级 aadf61de
...@@ -120,60 +120,41 @@ void udf_truncate_tail_extent(struct inode *inode) ...@@ -120,60 +120,41 @@ void udf_truncate_tail_extent(struct inode *inode)
void udf_discard_prealloc(struct inode *inode) void udf_discard_prealloc(struct inode *inode)
{ {
struct extent_position epos = { NULL, 0, {0, 0} }; struct extent_position epos = {};
struct extent_position prev_epos = {};
struct kernel_lb_addr eloc; struct kernel_lb_addr eloc;
uint32_t elen; uint32_t elen;
uint64_t lbcount = 0; uint64_t lbcount = 0;
int8_t etype = -1, netype; int8_t etype = -1, netype;
int adsize;
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB || if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ||
inode->i_size == iinfo->i_lenExtents) inode->i_size == iinfo->i_lenExtents)
return; return;
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(struct short_ad);
else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
adsize = sizeof(struct long_ad);
else
adsize = 0;
epos.block = iinfo->i_location; epos.block = iinfo->i_location;
/* Find the last extent in the file */ /* Find the last extent in the file */
while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 0)) != -1) {
etype = netype; brelse(prev_epos.bh);
prev_epos = epos;
if (prev_epos.bh)
get_bh(prev_epos.bh);
etype = udf_next_aext(inode, &epos, &eloc, &elen, 1);
lbcount += elen; lbcount += elen;
} }
if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
epos.offset -= adsize;
lbcount -= elen; lbcount -= elen;
extent_trunc(inode, &epos, &eloc, etype, elen, 0); udf_delete_aext(inode, prev_epos);
if (!epos.bh) { udf_free_blocks(inode->i_sb, inode, &eloc, 0,
iinfo->i_lenAlloc = DIV_ROUND_UP(elen, 1 << inode->i_blkbits));
epos.offset -
udf_file_entry_alloc_offset(inode);
mark_inode_dirty(inode);
} else {
struct allocExtDesc *aed =
(struct allocExtDesc *)(epos.bh->b_data);
aed->lengthAllocDescs =
cpu_to_le32(epos.offset -
sizeof(struct allocExtDesc));
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
udf_update_tag(epos.bh->b_data, epos.offset);
else
udf_update_tag(epos.bh->b_data,
sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(epos.bh, inode);
}
} }
/* This inode entry is in-memory only and thus we don't have to mark /* This inode entry is in-memory only and thus we don't have to mark
* the inode dirty */ * the inode dirty */
iinfo->i_lenExtents = lbcount; iinfo->i_lenExtents = lbcount;
brelse(epos.bh); brelse(epos.bh);
brelse(prev_epos.bh);
} }
static void udf_update_alloc_ext_desc(struct inode *inode, static void udf_update_alloc_ext_desc(struct inode *inode,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册