Commit 227c4d50 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull f2fs updates from Jaegeuk Kim:
 "In this round, we've improved the compression support especially for
  Android such as allowing compression for mmap files, replacing the
  immutable bit with internal bit to prohibits data writes explicitly,
  and adding a mount option, "compress_cache", to improve random reads.
  And, we added "readonly" feature to compact the partition w/
  compression enabled, which will be useful for Android RO partitions.

  Enhancements:
   - support compression for mmap file
   - use an f2fs flag instead of IMMUTABLE bit for compression
   - support RO feature w/ extent_cache
   - fully support swapfile with file pinning
   - improve atgc tunability
   - add nocompress extensions to unselect files for compression

  Bug fixes:
   - fix false alaram on iget failure during GC
   - fix race condition on global pointers when there are multiple f2fs
     instances
   - add MODULE_SOFTDEP for initramfs

  As usual, we've also cleaned up some places for better code
  readability (e.g., sysfs/feature, debugging messages, slab cache
  name, and docs)"

* tag 'f2fs-for-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (32 commits)
  f2fs: drop dirty node pages when cp is in error status
  f2fs: initialize page->private when using for our internal use
  f2fs: compress: add nocompress extensions support
  MAINTAINERS: f2fs: update my email address
  f2fs: remove false alarm on iget failure during GC
  f2fs: enable extent cache for compression files in read-only
  f2fs: fix to avoid adding tab before doc section
  f2fs: introduce f2fs_casefolded_name slab cache
  f2fs: swap: support migrating swapfile in aligned write mode
  f2fs: swap: remove dead codes
  f2fs: compress: add compress_inode to cache compressed blocks
  f2fs: clean up /sys/fs/f2fs/<disk>/features
  f2fs: add pin_file in feature list
  f2fs: Advertise encrypted casefolding in sysfs
  f2fs: Show casefolding support only when supported
  f2fs: support RO feature
  f2fs: logging neatening
  f2fs: introduce FI_COMPRESS_RELEASED instead of using IMMUTABLE bit
  f2fs: compress: remove unneeded preallocation
  f2fs: atgc: export entries for better tunability via sysfs
  ...
parents bd9c3506 28607bf3
Loading
Loading
Loading
Loading
+56 −1
Original line number Diff line number Diff line
@@ -203,7 +203,34 @@ Description: Shows total written kbytes issued to disk.
What:		/sys/fs/f2fs/<disk>/features
Date:		July 2017
Contact:	"Jaegeuk Kim" <jaegeuk@kernel.org>
Description:	Shows all enabled features in current device.
Description:	<deprecated: should use /sys/fs/f2fs/<disk>/feature_list/
		Shows all enabled features in current device.
		Supported features:
		encryption, blkzoned, extra_attr, projquota, inode_checksum,
		flexible_inline_xattr, quota_ino, inode_crtime, lost_found,
		verity, sb_checksum, casefold, readonly, compression, pin_file.

What:		/sys/fs/f2fs/<disk>/feature_list/
Date:		June 2021
Contact:	"Jaegeuk Kim" <jaegeuk@kernel.org>
Description:	Expand /sys/fs/f2fs/<disk>/features to meet sysfs rule.
		Supported on-disk features:
		encryption, block_zoned (aka blkzoned), extra_attr,
		project_quota (aka projquota), inode_checksum,
		flexible_inline_xattr, quota_ino, inode_crtime, lost_found,
		verity, sb_checksum, casefold, readonly, compression.
		Note that, pin_file is moved into /sys/fs/f2fs/features/.

What:		/sys/fs/f2fs/features/
Date:		July 2017
Contact:	"Jaegeuk Kim" <jaegeuk@kernel.org>
Description:	Shows all enabled kernel features.
		Supported features:
		encryption, block_zoned, extra_attr, project_quota,
		inode_checksum, flexible_inline_xattr, quota_ino,
		inode_crtime, lost_found, verity, sb_checksum,
		casefold, readonly, compression, test_dummy_encryption_v2,
		atomic_write, pin_file, encrypted_casefold.

What:		/sys/fs/f2fs/<disk>/inject_rate
Date:		May 2016
@@ -438,3 +465,31 @@ Description: Show the count of inode newly enabled for compression since mount.
		Note that when the compression is disabled for the files, this count
		doesn't decrease. If you write "0" here, you can initialize
		compr_new_inode to "0".

What:		/sys/fs/f2fs/<disk>/atgc_candidate_ratio
Date:		May 2021
Contact:	"Chao Yu" <yuchao0@huawei.com>
Description:	When ATGC is on, it controls candidate ratio in order to limit total
		number of potential victim in all candidates, the value should be in
		range of [0, 100], by default it was initialized as 20(%).

What:		/sys/fs/f2fs/<disk>/atgc_candidate_count
Date:		May 2021
Contact:	"Chao Yu" <yuchao0@huawei.com>
Description:	When ATGC is on, it controls candidate count in order to limit total
		number of potential victim in all candidates, by default it was
		initialized as 10 (sections).

What:		/sys/fs/f2fs/<disk>/atgc_age_weight
Date:		May 2021
Contact:	"Chao Yu" <yuchao0@huawei.com>
Description:	When ATGC is on, it controls age weight to balance weight proportion
		in between aging and valid blocks, the value should be in range of
		[0, 100], by default it was initialized as 60(%).

What:		/sys/fs/f2fs/<disk>/atgc_age_threshold
Date:		May 2021
Contact:	"Chao Yu" <yuchao0@huawei.com>
Description:	When ATGC is on, it controls age threshold to bypass GCing young
		candidates whose age is not beyond the threshold, by default it was
		initialized as 604800 seconds (equals to 7 days).
+41 −9
Original line number Diff line number Diff line
@@ -281,6 +281,18 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
			 For other files, we can still enable compression via ioctl.
			 Note that, there is one reserved special extension '*', it
			 can be set to enable compression for all files.
nocompress_extension=%s	   Support adding specified extension, so that f2fs can disable
			 compression on those corresponding files, just contrary to compression extension.
			 If you know exactly which files cannot be compressed, you can use this.
			 The same extension name can't appear in both compress and nocompress
			 extension at the same time.
			 If the compress extension specifies all files, the types specified by the
			 nocompress extension will be treated as special cases and will not be compressed.
			 Don't allow use '*' to specifie all file in nocompress extension.
			 After add nocompress_extension, the priority should be:
			 dir_flag < comp_extention,nocompress_extension < comp_file_flag,no_comp_file_flag.
			 See more in compression sections.

compress_chksum		 Support verifying chksum of raw data in compressed cluster.
compress_mode=%s	 Control file compression mode. This supports "fs" and "user"
			 modes. In "fs" mode (default), f2fs does automatic compression
@@ -289,6 +301,9 @@ compress_mode=%s Control file compression mode. This supports "fs" and "user"
			 choosing the target file and the timing. The user can do manual
			 compression/decompression on the compression enabled files using
			 ioctls.
compress_cache		 Support to use address space of a filesystem managed inode to
			 cache compressed block, in order to improve cache hit ratio of
			 random read.
inlinecrypt		 When possible, encrypt/decrypt the contents of encrypted
			 files using the blk-crypto framework rather than
			 filesystem-layer encryption. This allows the use of
@@ -717,10 +732,10 @@ users.
===================== ======================== ===================
User                  F2FS                     Block
===================== ======================== ===================
                      META                     WRITE_LIFE_NOT_SET
                      HOT_NODE                 "
                      WARM_NODE                "
                      COLD_NODE                "
N/A                   META                     WRITE_LIFE_NOT_SET
N/A                   HOT_NODE                 "
N/A                   WARM_NODE                "
N/A                   COLD_NODE                "
ioctl(COLD)           COLD_DATA                WRITE_LIFE_EXTREME
extension list        "                        "

@@ -746,10 +761,10 @@ WRITE_LIFE_LONG " WRITE_LIFE_LONG
===================== ======================== ===================
User                  F2FS                     Block
===================== ======================== ===================
                      META                     WRITE_LIFE_MEDIUM;
                      HOT_NODE                 WRITE_LIFE_NOT_SET
                      WARM_NODE                "
                      COLD_NODE                WRITE_LIFE_NONE
N/A                   META                     WRITE_LIFE_MEDIUM;
N/A                   HOT_NODE                 WRITE_LIFE_NOT_SET
N/A                   WARM_NODE                "
N/A                   COLD_NODE                WRITE_LIFE_NONE
ioctl(COLD)           COLD_DATA                WRITE_LIFE_EXTREME
extension list        "                        "

@@ -814,13 +829,30 @@ Compression implementation
  all logical blocks in cluster contain valid data and compress ratio of
  cluster data is lower than specified threshold.

- To enable compression on regular inode, there are three ways:
- To enable compression on regular inode, there are four ways:

  * chattr +c file
  * chattr +c dir; touch dir/file
  * mount w/ -o compress_extension=ext; touch file.ext
  * mount w/ -o compress_extension=*; touch any_file

- To disable compression on regular inode, there are two ways:

  * chattr -c file
  * mount w/ -o nocompress_extension=ext; touch file.ext

- Priority in between FS_COMPR_FL, FS_NOCOMP_FS, extensions:

  * compress_extension=so; nocompress_extension=zip; chattr +c dir; touch
    dir/foo.so; touch dir/bar.zip; touch dir/baz.txt; then foo.so and baz.txt
    should be compresse, bar.zip should be non-compressed. chattr +c dir/bar.zip
    can enable compress on bar.zip.
  * compress_extension=so; nocompress_extension=zip; chattr -c dir; touch
    dir/foo.so; touch dir/bar.zip; touch dir/baz.txt; then foo.so should be
    compresse, bar.zip and baz.txt should be non-compressed.
    chattr+c dir/bar.zip; chattr+c dir/baz.txt; can enable compress on bar.zip
    and baz.txt.

- At this point, compression feature doesn't expose compressed space to user
  directly in order to guarantee potential data updates later to the space.
  Instead, the main goal is to reduce data writes to flash disk as much as
+1 −1
Original line number Diff line number Diff line
@@ -7010,7 +7010,7 @@ F: drivers/iommu/exynos-iommu.c
F2FS FILE SYSTEM
M:	Jaegeuk Kim <jaegeuk@kernel.org>
M:	Chao Yu <yuchao0@huawei.com>
M:	Chao Yu <chao@kernel.org>
L:	linux-f2fs-devel@lists.sourceforge.net
S:	Maintained
W:	https://f2fs.wiki.kernel.org/
+2 −2
Original line number Diff line number Diff line
@@ -444,7 +444,7 @@ static int f2fs_set_meta_page_dirty(struct page *page)
	if (!PageDirty(page)) {
		__set_page_dirty_nobuffers(page);
		inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
		f2fs_set_page_private(page, 0);
		set_page_private_reference(page);
		return 1;
	}
	return 0;
@@ -1018,7 +1018,7 @@ void f2fs_update_dirty_page(struct inode *inode, struct page *page)
	inode_inc_dirty_pages(inode);
	spin_unlock(&sbi->inode_lock[type]);

	f2fs_set_page_private(page, 0);
	set_page_private_reference(page);
}

void f2fs_remove_dirty_inode(struct inode *inode)
+197 −58
Original line number Diff line number Diff line
@@ -12,9 +12,11 @@
#include <linux/lzo.h>
#include <linux/lz4.h>
#include <linux/zstd.h>
#include <linux/pagevec.h>

#include "f2fs.h"
#include "node.h"
#include "segment.h"
#include <trace/events/f2fs.h>

static struct kmem_cache *cic_entry_slab;
@@ -74,7 +76,7 @@ bool f2fs_is_compressed_page(struct page *page)
		return false;
	if (!page_private(page))
		return false;
	if (IS_ATOMIC_WRITTEN_PAGE(page) || IS_DUMMY_WRITTEN_PAGE(page))
	if (page_private_nonpointer(page))
		return false;

	f2fs_bug_on(F2FS_M_SB(page->mapping),
@@ -85,8 +87,7 @@ bool f2fs_is_compressed_page(struct page *page)
static void f2fs_set_compressed_page(struct page *page,
		struct inode *inode, pgoff_t index, void *data)
{
	SetPagePrivate(page);
	set_page_private(page, (unsigned long)data);
	attach_page_private(page, (void *)data);

	/* i_crypto_info and iv index */
	page->index = index;
@@ -589,8 +590,7 @@ static void f2fs_compress_free_page(struct page *page)
{
	if (!page)
		return;
	set_page_private(page, (unsigned long)NULL);
	ClearPagePrivate(page);
	detach_page_private(page);
	page->mapping = NULL;
	unlock_page(page);
	mempool_free(page, compress_page_pool);
@@ -738,7 +738,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
	return ret;
}

static void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(dic->inode);
	struct f2fs_inode_info *fi = F2FS_I(dic->inode);
@@ -837,7 +837,8 @@ static void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
 * page being waited on in the cluster, and if so, it decompresses the cluster
 * (or in the case of a failure, cleans up without actually decompressing).
 */
void f2fs_end_read_compressed_page(struct page *page, bool failed)
void f2fs_end_read_compressed_page(struct page *page, bool failed,
						block_t blkaddr)
{
	struct decompress_io_ctx *dic =
			(struct decompress_io_ctx *)page_private(page);
@@ -847,6 +848,9 @@ void f2fs_end_read_compressed_page(struct page *page, bool failed)

	if (failed)
		WRITE_ONCE(dic->failed, true);
	else if (blkaddr)
		f2fs_cache_compressed_page(sbi, page,
					dic->inode->i_ino, blkaddr);

	if (atomic_dec_and_test(&dic->remaining_pages))
		f2fs_decompress_cluster(dic);
@@ -876,7 +880,7 @@ bool f2fs_cluster_can_merge_page(struct compress_ctx *cc, pgoff_t index)
	return is_page_in_cluster(cc, index);
}

static bool __cluster_may_compress(struct compress_ctx *cc)
static bool cluster_has_invalid_data(struct compress_ctx *cc)
{
	loff_t i_size = i_size_read(cc->inode);
	unsigned nr_pages = DIV_ROUND_UP(i_size, PAGE_SIZE);
@@ -889,19 +893,22 @@ static bool __cluster_may_compress(struct compress_ctx *cc)

		/* beyond EOF */
		if (page->index >= nr_pages)
			return false;
	}
			return true;
	}
	return false;
}

static int __f2fs_cluster_blocks(struct compress_ctx *cc, bool compr)
static int __f2fs_cluster_blocks(struct inode *inode,
				unsigned int cluster_idx, bool compr)
{
	struct dnode_of_data dn;
	unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
	unsigned int start_idx = cluster_idx <<
				F2FS_I(inode)->i_log_cluster_size;
	int ret;

	set_new_dnode(&dn, cc->inode, NULL, NULL, 0);
	ret = f2fs_get_dnode_of_data(&dn, start_idx_of_cluster(cc),
							LOOKUP_NODE);
	set_new_dnode(&dn, inode, NULL, NULL, 0);
	ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE);
	if (ret) {
		if (ret == -ENOENT)
			ret = 0;
@@ -912,7 +919,7 @@ static int __f2fs_cluster_blocks(struct compress_ctx *cc, bool compr)
		int i;

		ret = 1;
		for (i = 1; i < cc->cluster_size; i++) {
		for (i = 1; i < cluster_size; i++) {
			block_t blkaddr;

			blkaddr = data_blkaddr(dn.inode,
@@ -925,6 +932,10 @@ static int __f2fs_cluster_blocks(struct compress_ctx *cc, bool compr)
					ret++;
			}
		}

		f2fs_bug_on(F2FS_I_SB(inode),
			!compr && ret != cluster_size &&
			!is_inode_flag_set(inode, FI_COMPRESS_RELEASED));
	}
fail:
	f2fs_put_dnode(&dn);
@@ -934,25 +945,15 @@ static int __f2fs_cluster_blocks(struct compress_ctx *cc, bool compr)
/* return # of compressed blocks in compressed cluster */
static int f2fs_compressed_blocks(struct compress_ctx *cc)
{
	return __f2fs_cluster_blocks(cc, true);
	return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, true);
}

/* return # of valid blocks in compressed cluster */
static int f2fs_cluster_blocks(struct compress_ctx *cc)
{
	return __f2fs_cluster_blocks(cc, false);
}

int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index)
{
	struct compress_ctx cc = {
		.inode = inode,
		.log_cluster_size = F2FS_I(inode)->i_log_cluster_size,
		.cluster_size = F2FS_I(inode)->i_cluster_size,
		.cluster_idx = index >> F2FS_I(inode)->i_log_cluster_size,
	};

	return f2fs_cluster_blocks(&cc);
	return __f2fs_cluster_blocks(inode,
		index >> F2FS_I(inode)->i_log_cluster_size,
		false);
}

static bool cluster_may_compress(struct compress_ctx *cc)
@@ -961,13 +962,11 @@ static bool cluster_may_compress(struct compress_ctx *cc)
		return false;
	if (f2fs_is_atomic_file(cc->inode))
		return false;
	if (f2fs_is_mmap_file(cc->inode))
		return false;
	if (!f2fs_cluster_is_full(cc))
		return false;
	if (unlikely(f2fs_cp_error(F2FS_I_SB(cc->inode))))
		return false;
	return __cluster_may_compress(cc);
	return !cluster_has_invalid_data(cc);
}

static void set_cluster_writeback(struct compress_ctx *cc)
@@ -995,21 +994,16 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
	struct f2fs_sb_info *sbi = F2FS_I_SB(cc->inode);
	struct address_space *mapping = cc->inode->i_mapping;
	struct page *page;
	struct dnode_of_data dn;
	sector_t last_block_in_bio;
	unsigned fgp_flag = FGP_LOCK | FGP_WRITE | FGP_CREAT;
	pgoff_t start_idx = start_idx_of_cluster(cc);
	int i, ret;
	bool prealloc;

retry:
	ret = f2fs_cluster_blocks(cc);
	ret = f2fs_is_compressed_cluster(cc->inode, start_idx);
	if (ret <= 0)
		return ret;

	/* compressed case */
	prealloc = (ret < cc->cluster_size);

	ret = f2fs_init_compress_ctx(cc);
	if (ret)
		return ret;
@@ -1067,25 +1061,6 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
		}
	}

	if (prealloc) {
		f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true);

		set_new_dnode(&dn, cc->inode, NULL, NULL, 0);

		for (i = cc->cluster_size - 1; i > 0; i--) {
			ret = f2fs_get_block(&dn, start_idx + i);
			if (ret) {
				i = cc->cluster_size;
				break;
			}

			if (dn.data_blkaddr != NEW_ADDR)
				break;
		}

		f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false);
	}

	if (likely(!ret)) {
		*fsdata = cc->rpages;
		*pagep = cc->rpages[offset_in_cluster(cc, index)];
@@ -1216,6 +1191,12 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
	loff_t psize;
	int i, err;

	/* we should bypass data pages to proceed the kworkder jobs */
	if (unlikely(f2fs_cp_error(sbi))) {
		mapping_set_error(cc->rpages[0]->mapping, -EIO);
		goto out_free;
	}

	if (IS_NOQUOTA(inode)) {
		/*
		 * We need to wait for node_write to avoid block allocation during
@@ -1399,7 +1380,7 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page)

	for (i = 0; i < cic->nr_rpages; i++) {
		WARN_ON(!cic->rpages[i]);
		clear_cold_data(cic->rpages[i]);
		clear_page_private_gcing(cic->rpages[i]);
		end_page_writeback(cic->rpages[i]);
	}

@@ -1685,6 +1666,164 @@ void f2fs_put_page_dic(struct page *page)
	f2fs_put_dic(dic);
}

const struct address_space_operations f2fs_compress_aops = {
	.releasepage = f2fs_release_page,
	.invalidatepage = f2fs_invalidate_page,
};

struct address_space *COMPRESS_MAPPING(struct f2fs_sb_info *sbi)
{
	return sbi->compress_inode->i_mapping;
}

void f2fs_invalidate_compress_page(struct f2fs_sb_info *sbi, block_t blkaddr)
{
	if (!sbi->compress_inode)
		return;
	invalidate_mapping_pages(COMPRESS_MAPPING(sbi), blkaddr, blkaddr);
}

void f2fs_cache_compressed_page(struct f2fs_sb_info *sbi, struct page *page,
						nid_t ino, block_t blkaddr)
{
	struct page *cpage;
	int ret;

	if (!test_opt(sbi, COMPRESS_CACHE))
		return;

	if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE_READ))
		return;

	if (!f2fs_available_free_memory(sbi, COMPRESS_PAGE))
		return;

	cpage = find_get_page(COMPRESS_MAPPING(sbi), blkaddr);
	if (cpage) {
		f2fs_put_page(cpage, 0);
		return;
	}

	cpage = alloc_page(__GFP_NOWARN | __GFP_IO);
	if (!cpage)
		return;

	ret = add_to_page_cache_lru(cpage, COMPRESS_MAPPING(sbi),
						blkaddr, GFP_NOFS);
	if (ret) {
		f2fs_put_page(cpage, 0);
		return;
	}

	set_page_private_data(cpage, ino);

	if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE_READ))
		goto out;

	memcpy(page_address(cpage), page_address(page), PAGE_SIZE);
	SetPageUptodate(cpage);
out:
	f2fs_put_page(cpage, 1);
}

bool f2fs_load_compressed_page(struct f2fs_sb_info *sbi, struct page *page,
								block_t blkaddr)
{
	struct page *cpage;
	bool hitted = false;

	if (!test_opt(sbi, COMPRESS_CACHE))
		return false;

	cpage = f2fs_pagecache_get_page(COMPRESS_MAPPING(sbi),
				blkaddr, FGP_LOCK | FGP_NOWAIT, GFP_NOFS);
	if (cpage) {
		if (PageUptodate(cpage)) {
			atomic_inc(&sbi->compress_page_hit);
			memcpy(page_address(page),
				page_address(cpage), PAGE_SIZE);
			hitted = true;
		}
		f2fs_put_page(cpage, 1);
	}

	return hitted;
}

void f2fs_invalidate_compress_pages(struct f2fs_sb_info *sbi, nid_t ino)
{
	struct address_space *mapping = sbi->compress_inode->i_mapping;
	struct pagevec pvec;
	pgoff_t index = 0;
	pgoff_t end = MAX_BLKADDR(sbi);

	if (!mapping->nrpages)
		return;

	pagevec_init(&pvec);

	do {
		unsigned int nr_pages;
		int i;

		nr_pages = pagevec_lookup_range(&pvec, mapping,
						&index, end - 1);
		if (!nr_pages)
			break;

		for (i = 0; i < nr_pages; i++) {
			struct page *page = pvec.pages[i];

			if (page->index > end)
				break;

			lock_page(page);
			if (page->mapping != mapping) {
				unlock_page(page);
				continue;
			}

			if (ino != get_page_private_data(page)) {
				unlock_page(page);
				continue;
			}

			generic_error_remove_page(mapping, page);
			unlock_page(page);
		}
		pagevec_release(&pvec);
		cond_resched();
	} while (index < end);
}

int f2fs_init_compress_inode(struct f2fs_sb_info *sbi)
{
	struct inode *inode;

	if (!test_opt(sbi, COMPRESS_CACHE))
		return 0;

	inode = f2fs_iget(sbi->sb, F2FS_COMPRESS_INO(sbi));
	if (IS_ERR(inode))
		return PTR_ERR(inode);
	sbi->compress_inode = inode;

	sbi->compress_percent = COMPRESS_PERCENT;
	sbi->compress_watermark = COMPRESS_WATERMARK;

	atomic_set(&sbi->compress_page_hit, 0);

	return 0;
}

void f2fs_destroy_compress_inode(struct f2fs_sb_info *sbi)
{
	if (!sbi->compress_inode)
		return;
	iput(sbi->compress_inode);
	sbi->compress_inode = NULL;
}

int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi)
{
	dev_t dev = sbi->sb->s_bdev->bd_dev;
Loading