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

Commit 728b4ac0 authored by Jaegeuk Kim's avatar Jaegeuk Kim Committed by Ritesh Harjani
Browse files

f2fs: avoid f2fs_bug_on if f2fs_get_meta_page_nofail got EIO



This patch avoids BUG_ON when f2fs_get_meta_page_nofail got EIO during
xfstests/generic/475.

Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
Change-Id: Ie1e9ed9acb6413fec869c3f7ca8ba1f9d7e964c7
Git-commit: edc55aaf0d1712b54a3704dd58423c7e495534fe
Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git


Signed-off-by: default avatarRitesh Harjani <riteshh@codeaurora.org>
parent 35387179
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -121,11 +121,8 @@ struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index)
		if (PTR_ERR(page) == -EIO &&
				++count <= DEFAULT_RETRY_IO_COUNT)
			goto retry;

		f2fs_stop_checkpoint(sbi, false);
		f2fs_bug_on(sbi, 1);
	}

	return page;
}

@@ -1492,7 +1489,10 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
	ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);

	/* write cached NAT/SIT entries to NAT/SIT area */
	flush_nat_entries(sbi, cpc);
	err = flush_nat_entries(sbi, cpc);
	if (err)
		goto stop;

	flush_sit_entries(sbi, cpc);

	/* unlock all the fs_lock[] in do_checkpoint() */
@@ -1501,7 +1501,7 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
		release_discard_addrs(sbi);
	else
		clear_prefree_segments(sbi, cpc);

stop:
	unblock_operations(sbi);
	stat_inc_cp_count(sbi->stat_info);

+1 −1
Original line number Diff line number Diff line
@@ -2786,7 +2786,7 @@ int recover_xattr_data(struct inode *inode, struct page *page);
int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
int restore_node_summary(struct f2fs_sb_info *sbi,
			unsigned int segno, struct f2fs_summary_block *sum);
void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
int flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
int build_node_manager(struct f2fs_sb_info *sbi);
void destroy_node_manager(struct f2fs_sb_info *sbi);
int __init create_node_manager_caches(void);
+12 −0
Original line number Diff line number Diff line
@@ -998,6 +998,18 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
	/* reference all summary page */
	while (segno < end_segno) {
		sum_page = get_sum_page(sbi, segno++);
		if (IS_ERR(sum_page)) {
			int err = PTR_ERR(sum_page);

			end_segno = segno - 1;
			for (segno = start_segno; segno < end_segno; segno++) {
				sum_page = find_get_page(META_MAPPING(sbi),
						GET_SUM_BLOCK(sbi, segno));
				f2fs_put_page(sum_page, 0);
				f2fs_put_page(sum_page, 0);
			}
			return err;
		}
		unlock_page(sum_page);
	}

+23 −8
Original line number Diff line number Diff line
@@ -139,6 +139,8 @@ static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)

	/* get current nat block page with lock */
	src_page = get_meta_page(sbi, src_off);
	if (IS_ERR(src_page))
		return src_page;
	dst_page = grab_meta_page(sbi, dst_off);
	f2fs_bug_on(sbi, PageDirty(src_page));

@@ -2150,15 +2152,19 @@ static int __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
						nm_i->nat_block_bitmap)) {
			struct page *page = get_current_nat_page(sbi, nid);

			if (IS_ERR(page)) {
				ret = PTR_ERR(page);
			} else {
				ret = scan_nat_page(sbi, page, nid);
				f2fs_put_page(page, 1);
			}

			if (ret) {
				up_read(&nm_i->nat_tree_lock);
				f2fs_bug_on(sbi, !mount);
				f2fs_msg(sbi->sb, KERN_ERR,
					"NAT is corrupt, run fsck to fix it");
				return -EINVAL;
				return ret;
			}
		}

@@ -2582,7 +2588,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
		__clear_bit_le(nat_index, nm_i->full_nat_bits);
}

static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
static int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
		struct nat_entry_set *set, struct cp_control *cpc)
{
	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
@@ -2606,6 +2612,8 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
		down_write(&curseg->journal_rwsem);
	} else {
		page = get_next_nat_page(sbi, start_nid);
		if (IS_ERR(page))
			return PTR_ERR(page);
		nat_blk = page_address(page);
		f2fs_bug_on(sbi, !nat_blk);
	}
@@ -2651,12 +2659,13 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
		radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set);
		kmem_cache_free(nat_entry_set_slab, set);
	}
	return 0;
}

/*
 * This function is called during the checkpointing process.
 */
void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
int flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{
	struct f2fs_nm_info *nm_i = NM_I(sbi);
	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
@@ -2666,9 +2675,10 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
	unsigned int found;
	nid_t set_idx = 0;
	LIST_HEAD(sets);
	int err = 0;

	if (!nm_i->dirty_nat_cnt)
		return;
		return 0;

	down_write(&nm_i->nat_tree_lock);

@@ -2691,11 +2701,16 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
	}

	/* flush dirty nats in nat entry set */
	list_for_each_entry_safe(set, tmp, &sets, set_list)
		__flush_nat_entry_set(sbi, set, cpc);
	list_for_each_entry_safe(set, tmp, &sets, set_list) {
		err = __flush_nat_entry_set(sbi, set, cpc);
		if (err)
			break;
	}

	up_write(&nm_i->nat_tree_lock);
	/* Allow dirty nats by node block allocation in write_begin */

	return err;
}

static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
+2 −0
Original line number Diff line number Diff line
@@ -361,6 +361,8 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
	}

	sum_page = get_sum_page(sbi, segno);
	if (IS_ERR(sum_page))
		return PTR_ERR(sum_page);
	sum_node = (struct f2fs_summary_block *)page_address(sum_page);
	sum = sum_node->entries[blkoff];
	f2fs_put_page(sum_page, 1);
Loading