Commit ac524ece authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'f2fs-5.13-rc1-fix' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs

Pull f2fs fixes from Jaegeuk Kim:
 "This fixes some critical bugs such as memory leak in compression
  flows, kernel panic when handling errors, and swapon failure due to
  newly added condition check"

* tag 'f2fs-5.13-rc1-fix' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs:
  f2fs: return EINVAL for hole cases in swap file
  f2fs: avoid swapon failure by giving a warning first
  f2fs: compress: fix to assign cc.cluster_idx correctly
  f2fs: compress: fix race condition of overwrite vs truncate
  f2fs: compress: fix to free compress page correctly
  f2fs: support iflag change given the mask
  f2fs: avoid null pointer access when handling IPU error
parents b5304a4f f395183f
......@@ -117,19 +117,6 @@ static void f2fs_unlock_rpages(struct compress_ctx *cc, int len)
f2fs_drop_rpages(cc, len, true);
}
static void f2fs_put_rpages_mapping(struct address_space *mapping,
pgoff_t start, int len)
{
int i;
for (i = 0; i < len; i++) {
struct page *page = find_get_page(mapping, start + i);
put_page(page);
put_page(page);
}
}
static void f2fs_put_rpages_wbc(struct compress_ctx *cc,
struct writeback_control *wbc, bool redirty, int unlock)
{
......@@ -158,12 +145,13 @@ int f2fs_init_compress_ctx(struct compress_ctx *cc)
return cc->rpages ? 0 : -ENOMEM;
}
void f2fs_destroy_compress_ctx(struct compress_ctx *cc)
void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse)
{
page_array_free(cc->inode, cc->rpages, cc->cluster_size);
cc->rpages = NULL;
cc->nr_rpages = 0;
cc->nr_cpages = 0;
if (!reuse)
cc->cluster_idx = NULL_CLUSTER;
}
......@@ -1036,7 +1024,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
}
if (PageUptodate(page))
unlock_page(page);
f2fs_put_page(page, 1);
else
f2fs_compress_ctx_add_page(cc, page);
}
......@@ -1046,33 +1034,35 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
ret = f2fs_read_multi_pages(cc, &bio, cc->cluster_size,
&last_block_in_bio, false, true);
f2fs_destroy_compress_ctx(cc);
f2fs_put_rpages(cc);
f2fs_destroy_compress_ctx(cc, true);
if (ret)
goto release_pages;
goto out;
if (bio)
f2fs_submit_bio(sbi, bio, DATA);
ret = f2fs_init_compress_ctx(cc);
if (ret)
goto release_pages;
goto out;
}
for (i = 0; i < cc->cluster_size; i++) {
f2fs_bug_on(sbi, cc->rpages[i]);
page = find_lock_page(mapping, start_idx + i);
f2fs_bug_on(sbi, !page);
if (!page) {
/* page can be truncated */
goto release_and_retry;
}
f2fs_wait_on_page_writeback(page, DATA, true, true);
f2fs_compress_ctx_add_page(cc, page);
f2fs_put_page(page, 0);
if (!PageUptodate(page)) {
release_and_retry:
f2fs_put_rpages(cc);
f2fs_unlock_rpages(cc, i + 1);
f2fs_put_rpages_mapping(mapping, start_idx,
cc->cluster_size);
f2fs_destroy_compress_ctx(cc);
f2fs_destroy_compress_ctx(cc, true);
goto retry;
}
}
......@@ -1103,10 +1093,10 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
}
unlock_pages:
f2fs_put_rpages(cc);
f2fs_unlock_rpages(cc, i);
release_pages:
f2fs_put_rpages_mapping(mapping, start_idx, i);
f2fs_destroy_compress_ctx(cc);
f2fs_destroy_compress_ctx(cc, true);
out:
return ret;
}
......@@ -1141,7 +1131,7 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata,
set_cluster_dirty(&cc);
f2fs_put_rpages_wbc(&cc, NULL, false, 1);
f2fs_destroy_compress_ctx(&cc);
f2fs_destroy_compress_ctx(&cc, false);
return first_index;
}
......@@ -1361,7 +1351,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
f2fs_put_rpages(cc);
page_array_free(cc->inode, cc->cpages, cc->nr_cpages);
cc->cpages = NULL;
f2fs_destroy_compress_ctx(cc);
f2fs_destroy_compress_ctx(cc, false);
return 0;
out_destroy_crypt:
......@@ -1372,7 +1362,8 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
for (i = 0; i < cc->nr_cpages; i++) {
if (!cc->cpages[i])
continue;
f2fs_put_page(cc->cpages[i], 1);
f2fs_compress_free_page(cc->cpages[i]);
cc->cpages[i] = NULL;
}
out_put_cic:
kmem_cache_free(cic_entry_slab, cic);
......@@ -1522,7 +1513,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
err = f2fs_write_raw_pages(cc, submitted, wbc, io_type);
f2fs_put_rpages_wbc(cc, wbc, false, 0);
destroy_out:
f2fs_destroy_compress_ctx(cc);
f2fs_destroy_compress_ctx(cc, false);
return err;
}
......
......@@ -2287,7 +2287,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
max_nr_pages,
&last_block_in_bio,
rac != NULL, false);
f2fs_destroy_compress_ctx(&cc);
f2fs_destroy_compress_ctx(&cc, false);
if (ret)
goto set_error_page;
}
......@@ -2332,7 +2332,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
max_nr_pages,
&last_block_in_bio,
rac != NULL, false);
f2fs_destroy_compress_ctx(&cc);
f2fs_destroy_compress_ctx(&cc, false);
}
}
#endif
......@@ -3033,7 +3033,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
}
}
if (f2fs_compressed_file(inode))
f2fs_destroy_compress_ctx(&cc);
f2fs_destroy_compress_ctx(&cc, false);
#endif
if (retry) {
index = 0;
......@@ -3801,6 +3801,7 @@ static int f2fs_is_file_aligned(struct inode *inode)
block_t pblock;
unsigned long nr_pblocks;
unsigned int blocks_per_sec = BLKS_PER_SEC(sbi);
unsigned int not_aligned = 0;
int ret = 0;
cur_lblock = 0;
......@@ -3833,13 +3834,20 @@ static int f2fs_is_file_aligned(struct inode *inode)
if ((pblock - main_blkaddr) & (blocks_per_sec - 1) ||
nr_pblocks & (blocks_per_sec - 1)) {
if (f2fs_is_pinned_file(inode)) {
f2fs_err(sbi, "Swapfile does not align to section");
ret = -EINVAL;
goto out;
}
not_aligned++;
}
cur_lblock += nr_pblocks;
}
if (not_aligned)
f2fs_warn(sbi, "Swapfile (%u) is not align to section: \n"
"\t1) creat(), 2) ioctl(F2FS_IOC_SET_PIN_FILE), 3) fallocate()",
not_aligned);
out:
return ret;
}
......@@ -3858,6 +3866,7 @@ static int check_swap_activate_fast(struct swap_info_struct *sis,
int nr_extents = 0;
unsigned long nr_pblocks;
unsigned int blocks_per_sec = BLKS_PER_SEC(sbi);
unsigned int not_aligned = 0;
int ret = 0;
/*
......@@ -3887,7 +3896,7 @@ static int check_swap_activate_fast(struct swap_info_struct *sis,
/* hole */
if (!(map.m_flags & F2FS_MAP_FLAGS)) {
f2fs_err(sbi, "Swapfile has holes\n");
ret = -ENOENT;
ret = -EINVAL;
goto out;
}
......@@ -3896,10 +3905,13 @@ static int check_swap_activate_fast(struct swap_info_struct *sis,
if ((pblock - SM_I(sbi)->main_blkaddr) & (blocks_per_sec - 1) ||
nr_pblocks & (blocks_per_sec - 1)) {
if (f2fs_is_pinned_file(inode)) {
f2fs_err(sbi, "Swapfile does not align to section");
ret = -EINVAL;
goto out;
}
not_aligned++;
}
if (cur_lblock + nr_pblocks >= sis->max)
nr_pblocks = sis->max - cur_lblock;
......@@ -3927,6 +3939,11 @@ static int check_swap_activate_fast(struct swap_info_struct *sis,
sis->max = cur_lblock;
sis->pages = cur_lblock - 1;
sis->highest_bit = cur_lblock - 1;
if (not_aligned)
f2fs_warn(sbi, "Swapfile (%u) is not align to section: \n"
"\t1) creat(), 2) ioctl(F2FS_IOC_SET_PIN_FILE), 3) fallocate()",
not_aligned);
out:
return ret;
}
......@@ -4035,7 +4052,7 @@ static int check_swap_activate(struct swap_info_struct *sis,
return ret;
bad_bmap:
f2fs_err(sbi, "Swapfile has holes\n");
return -ENOENT;
return -EINVAL;
}
static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file,
......
......@@ -3956,7 +3956,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed);
void f2fs_put_page_dic(struct page *page);
int f2fs_init_compress_ctx(struct compress_ctx *cc);
void f2fs_destroy_compress_ctx(struct compress_ctx *cc);
void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
void f2fs_init_compress_info(struct f2fs_sb_info *sbi);
int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi);
void f2fs_destroy_page_array_cache(struct f2fs_sb_info *sbi);
......
......@@ -1817,7 +1817,8 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
struct f2fs_inode_info *fi = F2FS_I(inode);
u32 masked_flags = fi->i_flags & mask;
f2fs_bug_on(F2FS_I_SB(inode), (iflags & ~mask));
/* mask can be shrunk by flags_valid selector */
iflags &= mask;
/* Is it quota file? Do not allow user to mess with it */
if (IS_NOQUOTA(inode))
......
......@@ -3574,12 +3574,12 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
return err;
drop_bio:
if (fio->bio) {
if (fio->bio && *(fio->bio)) {
struct bio *bio = *(fio->bio);
bio->bi_status = BLK_STS_IOERR;
bio_endio(bio);
fio->bio = NULL;
*(fio->bio) = NULL;
}
return err;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment