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

Commit b87c6286 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "f2fs: avoid wrong decrypted data from disk"

parents 5ff8147c 6fbc7be4
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -587,9 +587,6 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
		ctx->bio = bio;
		ctx->enabled_steps = post_read_steps;
		bio->bi_private = ctx;

		/* wait the page to be moved by cleaning */
		f2fs_wait_on_block_writeback(sbi, blkaddr);
	}

	return bio;
@@ -607,6 +604,9 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
	if (f2fs_may_encrypt_bio(inode, NULL))
		fscrypt_set_ice_dun(inode, bio, PG_DUN(inode, page));

	/* wait for GCed page writeback via META_MAPPING */
	f2fs_wait_on_block_writeback(inode, blkaddr);

	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
		bio_put(bio);
		return -EFAULT;
@@ -1562,6 +1562,12 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
			if (bio_encrypted)
				fscrypt_set_ice_dun(inode, bio, dun);
		}
		/*
		 * If the page is under writeback, we need to wait for
		 * its completion to see the correct decrypted data.
		 */
		f2fs_wait_on_block_writeback(inode, block_nr);

		if (bio_add_page(bio, page, blocksize, 0) < blocksize)
			goto submit_and_realloc;

@@ -1628,7 +1634,7 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
		return 0;

	/* wait for GCed page writeback via META_MAPPING */
	f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr);
	f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);

retry_encrypt:
	if (fscrypt_using_hardware_encryption(inode))
@@ -2371,10 +2377,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,

	f2fs_wait_on_page_writeback(page, DATA, false);

	/* wait for GCed page writeback via META_MAPPING */
	if (f2fs_post_read_required(inode))
		f2fs_wait_on_block_writeback(sbi, blkaddr);

	if (len == PAGE_SIZE || PageUptodate(page))
		return 0;

+2 −2
Original line number Diff line number Diff line
@@ -2733,7 +2733,7 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs);
void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid);
struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid);
struct page *get_node_page_ra(struct page *parent, int start);
void move_node_page(struct page *node_page, int gc_type);
int move_node_page(struct page *node_page, int gc_type);
int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
			struct writeback_control *wbc, bool atomic);
int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc,
@@ -2800,7 +2800,7 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
			struct f2fs_io_info *fio, bool add_list);
void f2fs_wait_on_page_writeback(struct page *page,
			enum page_type type, bool ordered);
void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr);
void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr);
void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
int lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
+1 −2
Original line number Diff line number Diff line
@@ -111,8 +111,7 @@ static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)
	f2fs_wait_on_page_writeback(page, DATA, false);

	/* wait for GCed page writeback via META_MAPPING */
	if (f2fs_post_read_required(inode))
		f2fs_wait_on_block_writeback(sbi, dn.data_blkaddr);
	f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);

out_sem:
	up_read(&F2FS_I(inode)->i_mmap_sem);
+52 −22
Original line number Diff line number Diff line
@@ -477,13 +477,14 @@ static int check_valid_map(struct f2fs_sb_info *sbi,
 * On validity, copy that node with cold status, otherwise (invalid node)
 * ignore that.
 */
static void gc_node_segment(struct f2fs_sb_info *sbi,
static int gc_node_segment(struct f2fs_sb_info *sbi,
		struct f2fs_summary *sum, unsigned int segno, int gc_type)
{
	struct f2fs_summary *entry;
	block_t start_addr;
	int off;
	int phase = 0;
	int submitted = 0;

	start_addr = START_BLOCK(sbi, segno);

@@ -494,10 +495,11 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
		nid_t nid = le32_to_cpu(entry->nid);
		struct page *node_page;
		struct node_info ni;
		int err;

		/* stop BG_GC if there is not enough free sections. */
		if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
			return;
			return submitted;

		if (check_valid_map(sbi, segno, off) == 0)
			continue;
@@ -530,12 +532,15 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
			continue;
		}

		move_node_page(node_page, gc_type);
		err = move_node_page(node_page, gc_type);
		if (!err && gc_type == FG_GC)
			submitted++;
		stat_inc_node_blk_count(sbi, 1, gc_type);
	}

	if (++phase < 3)
		goto next_step;
	return submitted;
}

/*
@@ -602,7 +607,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 * Move data block via META_MAPPING while keeping locked data page.
 * This can be used to move blocks, aka LBAs, directly on disk.
 */
static void move_data_block(struct inode *inode, block_t bidx,
static int move_data_block(struct inode *inode, block_t bidx,
					unsigned int segno, int off)
{
	struct f2fs_io_info fio = {
@@ -620,21 +625,26 @@ static void move_data_block(struct inode *inode, block_t bidx,
	struct node_info ni;
	struct page *page;
	block_t newaddr;
	int err;
	int err = 0;

	/* do not read out */
	page = f2fs_grab_cache_page(inode->i_mapping, bidx, false);
	if (!page)
		return;
		return -ENOMEM;

	if (!check_valid_map(F2FS_I_SB(inode), segno, off))
	if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
		err = -ENOENT;
		goto out;
	}

	if (f2fs_is_atomic_file(inode))
	if (f2fs_is_atomic_file(inode)) {
		err = -EAGAIN;
		goto out;
	}

	if (f2fs_is_pinned_file(inode)) {
		f2fs_pin_file_control(inode, true);
		err = -EAGAIN;
		goto out;
	}

@@ -645,6 +655,7 @@ static void move_data_block(struct inode *inode, block_t bidx,

	if (unlikely(dn.data_blkaddr == NULL_ADDR)) {
		ClearPageUptodate(page);
		err = -ENOENT;
		goto put_out;
	}

@@ -724,31 +735,40 @@ static void move_data_block(struct inode *inode, block_t bidx,
	f2fs_put_dnode(&dn);
out:
	f2fs_put_page(page, 1);
	return err;
}

static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
static int move_data_page(struct inode *inode, block_t bidx, int gc_type,
							unsigned int segno, int off)
{
	struct page *page;
	int err = 0;

	page = get_lock_data_page(inode, bidx, true);
	if (IS_ERR(page))
		return;
		return PTR_ERR(page);

	if (!check_valid_map(F2FS_I_SB(inode), segno, off))
	if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
		err = -ENOENT;
		goto out;
	}

	if (f2fs_is_atomic_file(inode))
	if (f2fs_is_atomic_file(inode)) {
		err = -EAGAIN;
		goto out;
	}
	if (f2fs_is_pinned_file(inode)) {
		if (gc_type == FG_GC)
			f2fs_pin_file_control(inode, true);
		err = -EAGAIN;
		goto out;
	}

	if (gc_type == BG_GC) {
		if (PageWriteback(page))
		if (PageWriteback(page)) {
			err = -EAGAIN;
			goto out;
		}
		set_page_dirty(page);
		set_cold_data(page);
	} else {
@@ -766,7 +786,6 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
			.io_type = FS_GC_DATA_IO,
		};
		bool is_dirty = PageDirty(page);
		int err;

retry:
		set_page_dirty(page);
@@ -791,6 +810,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
	}
out:
	f2fs_put_page(page, 1);
	return err;
}

/*
@@ -800,7 +820,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
 * If the parent node is not valid or the data block address is different,
 * the victim data block is ignored.
 */
static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
		struct gc_inode_list *gc_list, unsigned int segno, int gc_type)
{
	struct super_block *sb = sbi->sb;
@@ -808,6 +828,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
	block_t start_addr;
	int off;
	int phase = 0;
	int submitted = 0;

	start_addr = START_BLOCK(sbi, segno);

@@ -824,7 +845,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,

		/* stop BG_GC if there is not enough free sections. */
		if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
			return;
			return submitted;

		if (check_valid_map(sbi, segno, off) == 0)
			continue;
@@ -888,6 +909,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
		if (inode) {
			struct f2fs_inode_info *fi = F2FS_I(inode);
			bool locked = false;
			int err;

			if (S_ISREG(inode->i_mode)) {
				if (!down_write_trylock(&fi->dio_rwsem[READ]))
@@ -906,11 +928,15 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
			start_bidx = start_bidx_of_node(nofs, inode)
								+ ofs_in_node;
			if (f2fs_post_read_required(inode))
				move_data_block(inode, start_bidx, segno, off);
				err = move_data_block(inode, start_bidx, segno, off);
			else
				move_data_page(inode, start_bidx, gc_type,
				err = move_data_page(inode, start_bidx, gc_type,
								segno, off);

			if (!err && (gc_type == FG_GC ||
					f2fs_post_read_required(inode)))
				submitted++;

			if (locked) {
				up_write(&fi->dio_rwsem[WRITE]);
				up_write(&fi->dio_rwsem[READ]);
@@ -922,6 +948,8 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,

	if (++phase < 5)
		goto next_step;

	return submitted;
}

static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
@@ -949,6 +977,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
	int seg_freed = 0;
	unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
						SUM_TYPE_DATA : SUM_TYPE_NODE;
	int submitted = 0;

	/* readahead multi ssa blocks those have contiguous address */
	if (sbi->segs_per_sec > 1)
@@ -992,10 +1021,11 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
		 *                                  - lock_page(sum_page)
		 */
		if (type == SUM_TYPE_NODE)
			gc_node_segment(sbi, sum->entries, segno, gc_type);
		else
			gc_data_segment(sbi, sum->entries, gc_list, segno,
			submitted += gc_node_segment(sbi, sum->entries, segno,
								gc_type);
		else
			submitted += gc_data_segment(sbi, sum->entries, gc_list,
							segno, gc_type);

		stat_inc_seg_count(sbi, type, gc_type);

@@ -1006,7 +1036,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
		f2fs_put_page(sum_page, 0);
	}

	if (gc_type == FG_GC)
	if (submitted)
		f2fs_submit_merged_write(sbi,
				(type == SUM_TYPE_NODE) ? NODE : DATA);

+10 −3
Original line number Diff line number Diff line
@@ -1446,8 +1446,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
	return AOP_WRITEPAGE_ACTIVATE;
}

void move_node_page(struct page *node_page, int gc_type)
int move_node_page(struct page *node_page, int gc_type)
{
	int err = 0;

	if (gc_type == FG_GC) {
		struct writeback_control wbc = {
			.sync_mode = WB_SYNC_ALL,
@@ -1459,12 +1461,16 @@ void move_node_page(struct page *node_page, int gc_type)
		f2fs_wait_on_page_writeback(node_page, NODE, true);

		f2fs_bug_on(F2FS_P_SB(node_page), PageWriteback(node_page));
		if (!clear_page_dirty_for_io(node_page))
		if (!clear_page_dirty_for_io(node_page)) {
			err = -EAGAIN;
			goto out_page;
		}

		if (__write_node_page(node_page, false, NULL,
					&wbc, false, FS_GC_NODE_IO))
					&wbc, false, FS_GC_NODE_IO)) {
			err = -EAGAIN;
			unlock_page(node_page);
		}
		goto release_page;
	} else {
		/* set page dirty and write it */
@@ -1475,6 +1481,7 @@ void move_node_page(struct page *node_page, int gc_type)
	unlock_page(node_page);
release_page:
	f2fs_put_page(node_page, 0);
	return err;
}

static int f2fs_write_node_page(struct page *page,
Loading