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:
Родитель
c1c6338786
Коммит
5e6bbde959
|
@ -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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче