Skip to content

Commit

Permalink
Merge tag 'f2fs-fix-6.2-rc3' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/jaegeuk/f2fs

Pull f2fs fixes from Jaegeuk Kim:

 - fix a null pointer dereference in f2fs_issue_flush, which occurs by
   the combination of mount/remount options.

 - fix a bug in per-block age-based extent_cache newly introduced in
   6.2-rc1, which reported a wrong age information in extent_cache.

 - fix a kernel panic if extent_tree was not created, which was caught
   by a wrong BUG_ON

* tag 'f2fs-fix-6.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs:
  f2fs: let's avoid panic if extent_tree is not created
  f2fs: should use a temp extent_info for lookup
  f2fs: don't mix to use union values in extent_info
  f2fs: initialize extent_cache parameter
  f2fs: fix to avoid NULL pointer dereference in f2fs_issue_flush()
  • Loading branch information
Linus Torvalds committed Jan 4, 2023
2 parents b61778f + df9d44b commit 2ac4482
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 26 deletions.
2 changes: 1 addition & 1 deletion fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
sector_t last_block_in_file;
const unsigned blocksize = blks_to_bytes(inode, 1);
struct decompress_io_ctx *dic = NULL;
struct extent_info ei = {0, };
struct extent_info ei = {};
bool from_dnode = true;
int i;
int ret = 0;
Expand Down
34 changes: 18 additions & 16 deletions fs/f2fs/extent_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
struct extent_node *en;
bool ret = false;

f2fs_bug_on(sbi, !et);
if (!et)
return false;

trace_f2fs_lookup_extent_tree_start(inode, pgofs, type);

Expand Down Expand Up @@ -881,48 +882,50 @@ static unsigned long long __calculate_block_age(unsigned long long new,
}

/* This returns a new age and allocated blocks in ei */
static int __get_new_block_age(struct inode *inode, struct extent_info *ei)
static int __get_new_block_age(struct inode *inode, struct extent_info *ei,
block_t blkaddr)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
loff_t f_size = i_size_read(inode);
unsigned long long cur_blocks =
atomic64_read(&sbi->allocated_data_blocks);
struct extent_info tei = *ei; /* only fofs and len are valid */

/*
* When I/O is not aligned to a PAGE_SIZE, update will happen to the last
* file block even in seq write. So don't record age for newly last file
* block here.
*/
if ((f_size >> PAGE_SHIFT) == ei->fofs && f_size & (PAGE_SIZE - 1) &&
ei->blk == NEW_ADDR)
blkaddr == NEW_ADDR)
return -EINVAL;

if (__lookup_extent_tree(inode, ei->fofs, ei, EX_BLOCK_AGE)) {
if (__lookup_extent_tree(inode, ei->fofs, &tei, EX_BLOCK_AGE)) {
unsigned long long cur_age;

if (cur_blocks >= ei->last_blocks)
cur_age = cur_blocks - ei->last_blocks;
if (cur_blocks >= tei.last_blocks)
cur_age = cur_blocks - tei.last_blocks;
else
/* allocated_data_blocks overflow */
cur_age = ULLONG_MAX - ei->last_blocks + cur_blocks;
cur_age = ULLONG_MAX - tei.last_blocks + cur_blocks;

if (ei->age)
ei->age = __calculate_block_age(cur_age, ei->age);
if (tei.age)
ei->age = __calculate_block_age(cur_age, tei.age);
else
ei->age = cur_age;
ei->last_blocks = cur_blocks;
WARN_ON(ei->age > cur_blocks);
return 0;
}

f2fs_bug_on(sbi, ei->blk == NULL_ADDR);
f2fs_bug_on(sbi, blkaddr == NULL_ADDR);

/* the data block was allocated for the first time */
if (ei->blk == NEW_ADDR)
if (blkaddr == NEW_ADDR)
goto out;

if (__is_valid_data_blkaddr(ei->blk) &&
!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE)) {
if (__is_valid_data_blkaddr(blkaddr) &&
!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
f2fs_bug_on(sbi, 1);
return -EINVAL;
}
Expand All @@ -938,7 +941,7 @@ static int __get_new_block_age(struct inode *inode, struct extent_info *ei)

static void __update_extent_cache(struct dnode_of_data *dn, enum extent_type type)
{
struct extent_info ei;
struct extent_info ei = {};

if (!__may_extent_tree(dn->inode, type))
return;
Expand All @@ -953,8 +956,7 @@ static void __update_extent_cache(struct dnode_of_data *dn, enum extent_type typ
else
ei.blk = dn->data_blkaddr;
} else if (type == EX_BLOCK_AGE) {
ei.blk = dn->data_blkaddr;
if (__get_new_block_age(dn->inode, &ei))
if (__get_new_block_age(dn->inode, &ei, dn->data_blkaddr))
return;
}
__update_extent_tree_range(dn->inode, &ei, type);
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2559,7 +2559,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
struct f2fs_map_blocks map = { .m_next_extent = NULL,
.m_seg_type = NO_CHECK_TYPE,
.m_may_create = false };
struct extent_info ei = {0, };
struct extent_info ei = {};
pgoff_t pg_start, pg_end, next_pgofs;
unsigned int blk_per_seg = sbi->blocks_per_seg;
unsigned int total = 0, sec_num;
Expand Down
13 changes: 5 additions & 8 deletions fs/f2fs/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,7 @@ int f2fs_create_flush_cmd_control(struct f2fs_sb_info *sbi)
if (IS_ERR(fcc->f2fs_issue_flush)) {
int err = PTR_ERR(fcc->f2fs_issue_flush);

kfree(fcc);
SM_I(sbi)->fcc_info = NULL;
fcc->f2fs_issue_flush = NULL;
return err;
}

Expand Down Expand Up @@ -3161,7 +3160,7 @@ static int __get_segment_type_4(struct f2fs_io_info *fio)
static int __get_age_segment_type(struct inode *inode, pgoff_t pgofs)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct extent_info ei;
struct extent_info ei = {};

if (f2fs_lookup_age_extent_cache(inode, pgofs, &ei)) {
if (!ei.age)
Expand Down Expand Up @@ -5138,11 +5137,9 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)

init_f2fs_rwsem(&sm_info->curseg_lock);

if (!f2fs_readonly(sbi->sb)) {
err = f2fs_create_flush_cmd_control(sbi);
if (err)
return err;
}
err = f2fs_create_flush_cmd_control(sbi);
if (err)
return err;

err = create_discard_cmd_control(sbi);
if (err)
Expand Down

0 comments on commit 2ac4482

Please sign in to comment.