f2fs: introduce mempool for {,de}compress intermediate page allocation

If compression feature is on, in scenario of no enough free memory,
page refault ratio is higher than before, the root cause is:
- {,de}compression flow needs to allocate intermediate pages to store
compressed data in cluster, so during their allocation, vm may reclaim
mmaped pages.
- if above reclaimed pages belong to compressed cluster, during its
refault, it may cause more intermediate pages allocation, result in
reclaiming more mmaped pages.

So this patch introduces a mempool for intermediate page allocation,
in order to avoid high refault ratio, by default, number of
preallocated page in pool is 512, user can change the number by
assigning 'num_compress_pages' parameter during module initialization.

Ma Feng found warnings in the original patch and fixed like below.

Fix the following sparse warning:
fs/f2fs/compress.c:501:5: warning: symbol 'num_compress_pages' was not declared.
 Should it be static?
fs/f2fs/compress.c:530:6: warning: symbol 'f2fs_compress_free_page' was not
declared. Should it be static?

Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Ma Feng <mafeng.ma@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Chao Yu 2020-04-08 19:56:05 +08:00 коммит произвёл Jaegeuk Kim
Родитель c1c6338786
Коммит 5e6bbde959
3 изменённых файлов: 52 добавлений и 22 удалений

Просмотреть файл

@ -65,15 +65,6 @@ static void f2fs_set_compressed_page(struct page *page,
page->mapping = inode->i_mapping;
}
static void f2fs_put_compressed_page(struct page *page)
{
set_page_private(page, (unsigned long)NULL);
ClearPagePrivate(page);
page->mapping = NULL;
unlock_page(page);
put_page(page);
}
static void f2fs_drop_rpages(struct compress_ctx *cc, int len, bool unlock)
{
int i;
@ -476,17 +467,47 @@ bool f2fs_is_compress_backend_ready(struct inode *inode)
return f2fs_cops[F2FS_I(inode)->i_compress_algorithm];
}
static struct page *f2fs_grab_page(void)
static mempool_t *compress_page_pool = NULL;
static int num_compress_pages = 512;
module_param(num_compress_pages, uint, 0444);
MODULE_PARM_DESC(num_compress_pages,
"Number of intermediate compress pages to preallocate");
int f2fs_init_compress_mempool(void)
{
compress_page_pool = mempool_create_page_pool(num_compress_pages, 0);
if (!compress_page_pool)
return -ENOMEM;
return 0;
}
void f2fs_destroy_compress_mempool(void)
{
mempool_destroy(compress_page_pool);
}
static struct page *f2fs_compress_alloc_page(void)
{
struct page *page;
page = alloc_page(GFP_NOFS);
if (!page)
return NULL;
page = mempool_alloc(compress_page_pool, GFP_NOFS);
lock_page(page);
return page;
}
static void f2fs_compress_free_page(struct page *page)
{
if (!page)
return;
set_page_private(page, (unsigned long)NULL);
ClearPagePrivate(page);
page->mapping = NULL;
unlock_page(page);
mempool_free(page, compress_page_pool);
}
static int f2fs_compress_pages(struct compress_ctx *cc)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(cc->inode);
@ -516,7 +537,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
}
for (i = 0; i < cc->nr_cpages; i++) {
cc->cpages[i] = f2fs_grab_page();
cc->cpages[i] = f2fs_compress_alloc_page();
if (!cc->cpages[i]) {
ret = -ENOMEM;
goto out_free_cpages;
@ -561,7 +582,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
vunmap(cc->rbuf);
for (i = nr_cpages; i < cc->nr_cpages; i++) {
f2fs_put_compressed_page(cc->cpages[i]);
f2fs_compress_free_page(cc->cpages[i]);
cc->cpages[i] = NULL;
}
@ -581,7 +602,7 @@ out_vunmap_rbuf:
out_free_cpages:
for (i = 0; i < cc->nr_cpages; i++) {
if (cc->cpages[i])
f2fs_put_compressed_page(cc->cpages[i]);
f2fs_compress_free_page(cc->cpages[i]);
}
kfree(cc->cpages);
cc->cpages = NULL;
@ -1183,7 +1204,7 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page)
if (unlikely(bio->bi_status))
mapping_set_error(cic->inode->i_mapping, -EIO);
f2fs_put_compressed_page(page);
f2fs_compress_free_page(page);
dec_page_count(sbi, F2FS_WB_DATA);
@ -1344,7 +1365,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
for (i = 0; i < dic->nr_cpages; i++) {
struct page *page;
page = f2fs_grab_page();
page = f2fs_compress_alloc_page();
if (!page)
goto out_free;
@ -1364,7 +1385,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
continue;
}
dic->tpages[i] = f2fs_grab_page();
dic->tpages[i] = f2fs_compress_alloc_page();
if (!dic->tpages[i])
goto out_free;
}
@ -1386,8 +1407,7 @@ void f2fs_free_dic(struct decompress_io_ctx *dic)
continue;
if (!dic->tpages[i])
continue;
unlock_page(dic->tpages[i]);
put_page(dic->tpages[i]);
f2fs_compress_free_page(dic->tpages[i]);
}
kfree(dic->tpages);
}
@ -1396,7 +1416,7 @@ void f2fs_free_dic(struct decompress_io_ctx *dic)
for (i = 0; i < dic->nr_cpages; i++) {
if (!dic->cpages[i])
continue;
f2fs_put_compressed_page(dic->cpages[i]);
f2fs_compress_free_page(dic->cpages[i]);
}
kfree(dic->cpages);
}

Просмотреть файл

@ -3829,6 +3829,8 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata,
int f2fs_truncate_partial_cluster(struct inode *inode, u64 from, bool lock);
void f2fs_compress_write_end_io(struct bio *bio, struct page *page);
bool f2fs_is_compress_backend_ready(struct inode *inode);
int f2fs_init_compress_mempool(void);
void f2fs_destroy_compress_mempool(void);
void f2fs_decompress_pages(struct bio *bio, struct page *page, bool verity);
bool f2fs_cluster_is_empty(struct compress_ctx *cc);
bool f2fs_cluster_can_merge_page(struct compress_ctx *cc, pgoff_t index);
@ -3862,6 +3864,8 @@ static inline struct page *f2fs_compress_control_page(struct page *page)
WARN_ON_ONCE(1);
return ERR_PTR(-EINVAL);
}
static inline int f2fs_init_compress_mempool(void) { return 0; }
static inline void f2fs_destroy_compress_mempool(void) { }
#endif
static inline void set_compress_context(struct inode *inode)

Просмотреть файл

@ -3879,7 +3879,12 @@ static int __init init_f2fs_fs(void)
err = f2fs_init_bioset();
if (err)
goto free_bio_enrty_cache;
err = f2fs_init_compress_mempool();
if (err)
goto free_bioset;
return 0;
free_bioset:
f2fs_destroy_bioset();
free_bio_enrty_cache:
f2fs_destroy_bio_entry_cache();
free_post_read:
@ -3907,6 +3912,7 @@ fail:
static void __exit exit_f2fs_fs(void)
{
f2fs_destroy_compress_mempool();
f2fs_destroy_bioset();
f2fs_destroy_bio_entry_cache();
f2fs_destroy_post_read_processing();