Skip to content

Commit af4b6b8

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: introduce check_swap_activate_fast()
check_swap_activate() will lookup block mapping via bmap() one by one, so its performance is very bad, this patch introduces check_swap_activate_fast() to use f2fs_fiemap() to boost this process, since f2fs_fiemap() will lookup block mappings in batch, therefore, it can improve swapon()'s performance significantly. Note that this enhancement only works when page size is equal to f2fs' block size. Testcase: (backend device: zram) - touch file - pin & fallocate file to 8GB - mkswap file - swapon file Before: real 0m2.999s user 0m0.000s sys 0m2.980s After: real 0m0.081s user 0m0.000s sys 0m0.064s Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 6ed29fe commit af4b6b8

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

fs/f2fs/data.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,6 +3883,83 @@ int f2fs_migrate_page(struct address_space *mapping,
38833883
#endif
38843884

38853885
#ifdef CONFIG_SWAP
3886+
static int check_swap_activate_fast(struct swap_info_struct *sis,
3887+
struct file *swap_file, sector_t *span)
3888+
{
3889+
struct address_space *mapping = swap_file->f_mapping;
3890+
struct inode *inode = mapping->host;
3891+
sector_t cur_lblock;
3892+
sector_t last_lblock;
3893+
sector_t pblock;
3894+
sector_t lowest_pblock = -1;
3895+
sector_t highest_pblock = 0;
3896+
int nr_extents = 0;
3897+
unsigned long nr_pblocks;
3898+
unsigned long len;
3899+
int ret;
3900+
3901+
/*
3902+
* Map all the blocks into the extent list. This code doesn't try
3903+
* to be very smart.
3904+
*/
3905+
cur_lblock = 0;
3906+
last_lblock = logical_to_blk(inode, i_size_read(inode));
3907+
len = i_size_read(inode);
3908+
3909+
while (cur_lblock <= last_lblock && cur_lblock < sis->max) {
3910+
struct buffer_head map_bh;
3911+
pgoff_t next_pgofs;
3912+
3913+
cond_resched();
3914+
3915+
memset(&map_bh, 0, sizeof(struct buffer_head));
3916+
map_bh.b_size = len - cur_lblock;
3917+
3918+
ret = get_data_block(inode, cur_lblock, &map_bh, 0,
3919+
F2FS_GET_BLOCK_FIEMAP, &next_pgofs);
3920+
if (ret)
3921+
goto err_out;
3922+
3923+
/* hole */
3924+
if (!buffer_mapped(&map_bh))
3925+
goto err_out;
3926+
3927+
pblock = map_bh.b_blocknr;
3928+
nr_pblocks = logical_to_blk(inode, map_bh.b_size);
3929+
3930+
if (cur_lblock + nr_pblocks >= sis->max)
3931+
nr_pblocks = sis->max - cur_lblock;
3932+
3933+
if (cur_lblock) { /* exclude the header page */
3934+
if (pblock < lowest_pblock)
3935+
lowest_pblock = pblock;
3936+
if (pblock + nr_pblocks - 1 > highest_pblock)
3937+
highest_pblock = pblock + nr_pblocks - 1;
3938+
}
3939+
3940+
/*
3941+
* We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks
3942+
*/
3943+
ret = add_swap_extent(sis, cur_lblock, nr_pblocks, pblock);
3944+
if (ret < 0)
3945+
goto out;
3946+
nr_extents += ret;
3947+
cur_lblock += nr_pblocks;
3948+
}
3949+
ret = nr_extents;
3950+
*span = 1 + highest_pblock - lowest_pblock;
3951+
if (cur_lblock == 0)
3952+
cur_lblock = 1; /* force Empty message */
3953+
sis->max = cur_lblock;
3954+
sis->pages = cur_lblock - 1;
3955+
sis->highest_bit = cur_lblock - 1;
3956+
out:
3957+
return ret;
3958+
err_out:
3959+
pr_err("swapon: swapfile has holes\n");
3960+
return -EINVAL;
3961+
}
3962+
38863963
/* Copied from generic_swapfile_activate() to check any holes */
38873964
static int check_swap_activate(struct swap_info_struct *sis,
38883965
struct file *swap_file, sector_t *span)
@@ -3899,6 +3976,9 @@ static int check_swap_activate(struct swap_info_struct *sis,
38993976
int nr_extents = 0;
39003977
int ret;
39013978

3979+
if (PAGE_SIZE == F2FS_BLKSIZE)
3980+
return check_swap_activate_fast(sis, swap_file, span);
3981+
39023982
blkbits = inode->i_blkbits;
39033983
blocks_per_page = PAGE_SIZE >> blkbits;
39043984

0 commit comments

Comments
 (0)