Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7eab0c0d authored by Hou Pengyang's avatar Hou Pengyang Committed by Jaegeuk Kim
Browse files

f2fs: reconstruct code to write a data page



This patch introduces encrypt_one_page which encrypts one data page before
submit_bio, and change the use of need_inplace_update.

Signed-off-by: default avatarHou Pengyang <houpengyang@huawei.com>
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 63a94fa1
Loading
Loading
Loading
Loading
+51 −30
Original line number Diff line number Diff line
@@ -1302,6 +1302,49 @@ static int f2fs_read_data_pages(struct file *file,
	return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages);
}

static int encrypt_one_page(struct f2fs_io_info *fio)
{
	struct inode *inode = fio->page->mapping->host;
	gfp_t gfp_flags = GFP_NOFS;

	if (!f2fs_encrypted_inode(inode) || !S_ISREG(inode->i_mode))
		return 0;

	/* wait for GCed encrypted page writeback */
	f2fs_wait_on_encrypted_page_writeback(fio->sbi, fio->old_blkaddr);

retry_encrypt:
	fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
			PAGE_SIZE, 0, fio->page->index, gfp_flags);
	if (!IS_ERR(fio->encrypted_page))
		return 0;

	/* flush pending IOs and wait for a while in the ENOMEM case */
	if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
		f2fs_flush_merged_bios(fio->sbi);
		congestion_wait(BLK_RW_ASYNC, HZ/50);
		gfp_flags |= __GFP_NOFAIL;
		goto retry_encrypt;
	}
	return PTR_ERR(fio->encrypted_page);
}

static inline bool need_inplace_update(struct f2fs_io_info *fio)
{
	struct inode *inode = fio->page->mapping->host;

	if (fio->old_blkaddr == NEW_ADDR)
		return false;
	if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
		return false;
	if (is_cold_data(fio->page))
		return false;
	if (IS_ATOMIC_WRITTEN_PAGE(fio->page))
		return false;

	return need_inplace_update_policy(inode, fio);
}

int do_write_data_page(struct f2fs_io_info *fio)
{
	struct page *page = fio->page;
@@ -1322,30 +1365,9 @@ int do_write_data_page(struct f2fs_io_info *fio)
		goto out_writepage;
	}

	if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
		gfp_t gfp_flags = GFP_NOFS;

		/* wait for GCed encrypted page writeback */
		f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode),
							fio->old_blkaddr);
retry_encrypt:
		fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
							PAGE_SIZE, 0,
							fio->page->index,
							gfp_flags);
		if (IS_ERR(fio->encrypted_page)) {
			err = PTR_ERR(fio->encrypted_page);
			if (err == -ENOMEM) {
				/* flush pending ios and wait for a while */
				f2fs_flush_merged_bios(F2FS_I_SB(inode));
				congestion_wait(BLK_RW_ASYNC, HZ/50);
				gfp_flags |= __GFP_NOFAIL;
				err = 0;
				goto retry_encrypt;
			}
	err = encrypt_one_page(fio);
	if (err)
		goto out_writepage;
		}
	}

	set_page_writeback(page);

@@ -1353,15 +1375,14 @@ int do_write_data_page(struct f2fs_io_info *fio)
	 * If current allocation needs SSR,
	 * it had better in-place writes for updated data.
	 */
	if (unlikely(fio->old_blkaddr != NEW_ADDR &&
			!is_cold_data(page) &&
			!IS_ATOMIC_WRITTEN_PAGE(page) &&
			need_inplace_update(inode, fio))) {
		f2fs_unlock_op(F2FS_I_SB(inode));
	if (need_inplace_update(fio)) {
		f2fs_bug_on(fio->sbi, !fio->cp_rwsem_locked);
		f2fs_unlock_op(fio->sbi);
		fio->cp_rwsem_locked = false;

		err = rewrite_data_page(fio);
		trace_f2fs_do_write_data_page(fio->page, IPU);
		set_inode_flag(inode, FI_UPDATE_WRITE);
		trace_f2fs_do_write_data_page(page, IPU);
	} else {
		write_data_page(&dn, fio);
		trace_f2fs_do_write_data_page(page, OPU);
+2 −2
Original line number Diff line number Diff line
@@ -1898,7 +1898,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
	int err;

	/* if in-place-update policy is enabled, don't waste time here */
	if (need_inplace_update(inode, NULL))
	if (need_inplace_update_policy(inode, NULL))
		return -EINVAL;

	pg_start = range->start >> PAGE_SHIFT;
@@ -2033,7 +2033,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (!S_ISREG(inode->i_mode))
	if (!S_ISREG(inode->i_mode) || f2fs_is_atomic_file(inode))
		return -EINVAL;

	if (f2fs_readonly(sbi->sb))
+1 −5
Original line number Diff line number Diff line
@@ -564,16 +564,12 @@ enum {
	F2FS_IPU_ASYNC,
};

static inline bool need_inplace_update(struct inode *inode,
static inline bool need_inplace_update_policy(struct inode *inode,
				struct f2fs_io_info *fio)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	unsigned int policy = SM_I(sbi)->ipu_policy;

	/* IPU can be done only for the user data */
	if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
		return false;

	if (test_opt(sbi, LFS))
		return false;