Hi Ju Hyung, On 2020/2/7 14:42, Ju Hyung Park wrote: > Hi Chao, > > I think this should be sent to linux-stable. > Thoughts?
Yup, I forgot to Cc stable mailing list, let me resend it. Thanks for reminding me that. Thanks, > > Thanks. > > On Fri, Dec 27, 2019 at 7:45 PM Chao Yu <[email protected]> wrote: >> >> As Youling reported in mailing list: >> >> https://www.linuxquestions.org/questions/linux-newbie-8/the-file-system-f2fs-is-broken-4175666043/ >> >> https://www.linux.org/threads/the-file-system-f2fs-is-broken.26490/ >> >> There is a test case can corrupt f2fs image: >> - dd if=/dev/zero of=/swapfile bs=1M count=4096 >> - chmod 600 /swapfile >> - mkswap /swapfile >> - swapon --discard /swapfile >> >> The root cause is f2fs_swap_activate() intends to return zero value >> to setup_swap_extents() to enable SWP_FS mode (swap file goes through >> fs), in this flow, setup_swap_extents() setups swap extent with wrong >> block address range, result in discard_swap() erasing incorrect address. >> >> Because f2fs_swap_activate() has pinned swapfile, its data block >> address will not change, it's safe to let swap to handle IO through >> raw device, so we can get rid of SWAP_FS mode and initial swap extents >> inside f2fs_swap_activate(), by this way, later discard_swap() can trim >> in right address range. >> >> Fixes: 4969c06a0d83 ("f2fs: support swap file w/ DIO") >> Signed-off-by: Chao Yu <[email protected]> >> --- >> fs/f2fs/data.c | 32 +++++++++++++++++++++++++------- >> 1 file changed, 25 insertions(+), 7 deletions(-) >> >> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c >> index 19cd03450066..ee4d3d284379 100644 >> --- a/fs/f2fs/data.c >> +++ b/fs/f2fs/data.c >> @@ -3608,7 +3608,8 @@ int f2fs_migrate_page(struct address_space *mapping, >> >> #ifdef CONFIG_SWAP >> /* Copied from generic_swapfile_activate() to check any holes */ >> -static int check_swap_activate(struct file *swap_file, unsigned int max) >> +static int check_swap_activate(struct swap_info_struct *sis, >> + struct file *swap_file, sector_t *span) >> { >> struct address_space *mapping = swap_file->f_mapping; >> struct inode *inode = mapping->host; >> @@ -3619,6 +3620,8 @@ static int check_swap_activate(struct file *swap_file, >> unsigned int max) >> sector_t last_block; >> sector_t lowest_block = -1; >> sector_t highest_block = 0; >> + int nr_extents = 0; >> + int ret; >> >> blkbits = inode->i_blkbits; >> blocks_per_page = PAGE_SIZE >> blkbits; >> @@ -3630,7 +3633,8 @@ static int check_swap_activate(struct file *swap_file, >> unsigned int max) >> probe_block = 0; >> page_no = 0; >> last_block = i_size_read(inode) >> blkbits; >> - while ((probe_block + blocks_per_page) <= last_block && page_no < >> max) { >> + while ((probe_block + blocks_per_page) <= last_block && >> + page_no < sis->max) { >> unsigned block_in_page; >> sector_t first_block; >> >> @@ -3670,13 +3674,27 @@ static int check_swap_activate(struct file >> *swap_file, unsigned int max) >> highest_block = first_block; >> } >> >> + /* >> + * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of >> blocks >> + */ >> + ret = add_swap_extent(sis, page_no, 1, first_block); >> + if (ret < 0) >> + goto out; >> + nr_extents += ret; >> page_no++; >> probe_block += blocks_per_page; >> reprobe: >> continue; >> } >> - return 0; >> - >> + ret = nr_extents; >> + *span = 1 + highest_block - lowest_block; >> + if (page_no == 0) >> + page_no = 1; /* force Empty message */ >> + sis->max = page_no; >> + sis->pages = page_no - 1; >> + sis->highest_bit = page_no - 1; >> +out: >> + return ret; >> bad_bmap: >> pr_err("swapon: swapfile has holes\n"); >> return -EINVAL; >> @@ -3701,14 +3719,14 @@ static int f2fs_swap_activate(struct >> swap_info_struct *sis, struct file *file, >> if (f2fs_disable_compressed_file(inode)) >> return -EINVAL; >> >> - ret = check_swap_activate(file, sis->max); >> - if (ret) >> + ret = check_swap_activate(sis, file, span); >> + if (ret < 0) >> return ret; >> >> set_inode_flag(inode, FI_PIN_FILE); >> f2fs_precache_extents(inode); >> f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); >> - return 0; >> + return ret; >> } >> >> static void f2fs_swap_deactivate(struct file *file) >> -- >> 2.18.0.rc1 >> >> >> >> _______________________________________________ >> Linux-f2fs-devel mailing list >> [email protected] >> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel > . > _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
