Commit 5e6bbde9 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

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: default avatarHulk Robot <hulkci@huawei.com>
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarMa Feng <mafeng.ma@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent c1c63387
Loading
Loading
Loading
Loading
+42 −22
Original line number Diff line number Diff line
@@ -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 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
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);
	}
+4 −0
Original line number Diff line number Diff line
@@ -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)
+6 −0
Original line number Diff line number Diff line
@@ -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 @@ static int __init init_f2fs_fs(void)

static void __exit exit_f2fs_fs(void)
{
	f2fs_destroy_compress_mempool();
	f2fs_destroy_bioset();
	f2fs_destroy_bio_entry_cache();
	f2fs_destroy_post_read_processing();