Hi Chao, I think this should be sent to linux-stable. Thoughts?
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
