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

Commit 7735730d authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: fix to propagate error from __get_meta_page()



If caller of __get_meta_page() can handle error, let's propagate error
from __get_meta_page().

Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 18dd6470
Loading
Loading
Loading
Loading
+41 −14
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
		.encrypted_page = NULL,
		.is_meta = is_meta,
	};
	int err;

	if (unlikely(!is_meta))
		fio.op_flags &= ~REQ_META;
@@ -85,11 +86,10 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,

	fio.page = page;

	if (f2fs_submit_page_bio(&fio)) {
		memset(page_address(page), 0, PAGE_SIZE);
		f2fs_stop_checkpoint(sbi, false);
		f2fs_bug_on(sbi, 1);
		return page;
	err = f2fs_submit_page_bio(&fio);
	if (err) {
		f2fs_put_page(page, 1);
		return ERR_PTR(err);
	}

	lock_page(page);
@@ -98,14 +98,9 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
		goto repeat;
	}

	/*
	 * if there is any IO error when accessing device, make our filesystem
	 * readonly and make sure do not write checkpoint with non-uptodate
	 * meta page.
	 */
	if (unlikely(!PageUptodate(page))) {
		memset(page_address(page), 0, PAGE_SIZE);
		f2fs_stop_checkpoint(sbi, false);
		f2fs_put_page(page, 1);
		return ERR_PTR(-EIO);
	}
out:
	return page;
@@ -116,6 +111,25 @@ struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
	return __get_meta_page(sbi, index, true);
}

struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index)
{
	struct page *page;
	int count = 0;

retry:
	page = __get_meta_page(sbi, index, true);
	if (IS_ERR(page)) {
		if (PTR_ERR(page) == -EIO &&
				++count <= DEFAULT_RETRY_IO_COUNT)
			goto retry;

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

	return page;
}

/* for POR only */
struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
{
@@ -607,7 +621,9 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
	/* truncate all the data during iput */
	iput(inode);

	f2fs_get_node_info(sbi, ino, &ni);
	err = f2fs_get_node_info(sbi, ino, &ni);
	if (err)
		goto err_out;

	/* ENOMEM was fully retried in f2fs_evict_inode. */
	if (ni.blk_addr != NULL_ADDR) {
@@ -655,9 +671,15 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
	f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);

	for (i = 0; i < orphan_blocks; i++) {
		struct page *page = f2fs_get_meta_page(sbi, start_blk + i);
		struct page *page;
		struct f2fs_orphan_block *orphan_blk;

		page = f2fs_get_meta_page(sbi, start_blk + i);
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			goto out;
		}

		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
@@ -748,6 +770,9 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
	__u32 crc = 0;

	*cp_page = f2fs_get_meta_page(sbi, cp_addr);
	if (IS_ERR(*cp_page))
		return PTR_ERR(*cp_page);

	*cp_block = (struct f2fs_checkpoint *)page_address(*cp_page);

	crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
@@ -873,6 +898,8 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
		unsigned char *ckpt = (unsigned char *)sbi->ckpt;

		cur_page = f2fs_get_meta_page(sbi, cp_blk_no + i);
		if (IS_ERR(cur_page))
			goto free_fail_no_cp;
		sit_bitmap_ptr = page_address(cur_page);
		memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
		f2fs_put_page(cur_page, 1);
+21 −3
Original line number Diff line number Diff line
@@ -879,6 +879,10 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
	if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
		return -EPERM;

	err = f2fs_get_node_info(sbi, dn->nid, &ni);
	if (err)
		return err;

	dn->data_blkaddr = datablock_addr(dn->inode,
				dn->node_page, dn->ofs_in_node);
	if (dn->data_blkaddr == NEW_ADDR)
@@ -888,7 +892,6 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
		return err;

alloc:
	f2fs_get_node_info(sbi, dn->nid, &ni);
	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);

	f2fs_allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
@@ -1291,7 +1294,11 @@ static int f2fs_xattr_fiemap(struct inode *inode,
		if (!page)
			return -ENOMEM;

		f2fs_get_node_info(sbi, inode->i_ino, &ni);
		err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
		if (err) {
			f2fs_put_page(page, 1);
			return err;
		}

		phys = (__u64)blk_to_logical(inode, ni.blk_addr);
		offset = offsetof(struct f2fs_inode, i_addr) +
@@ -1318,7 +1325,11 @@ static int f2fs_xattr_fiemap(struct inode *inode,
		if (!page)
			return -ENOMEM;

		f2fs_get_node_info(sbi, xnid, &ni);
		err = f2fs_get_node_info(sbi, xnid, &ni);
		if (err) {
			f2fs_put_page(page, 1);
			return err;
		}

		phys = (__u64)blk_to_logical(inode, ni.blk_addr);
		len = inode->i_sb->s_blocksize;
@@ -1705,6 +1716,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
	struct inode *inode = page->mapping->host;
	struct dnode_of_data dn;
	struct extent_info ei = {0,0,0};
	struct node_info ni;
	bool ipu_force = false;
	int err = 0;

@@ -1773,6 +1785,12 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
		fio->need_lock = LOCK_REQ;
	}

	err = f2fs_get_node_info(fio->sbi, dn.nid, &ni);
	if (err)
		goto out_writepage;

	fio->version = ni.version;

	err = encrypt_one_page(fio);
	if (err)
		goto out_writepage;
+6 −2
Original line number Diff line number Diff line
@@ -513,6 +513,8 @@ enum {
					 */
};

#define DEFAULT_RETRY_IO_COUNT	8	/* maximum retry read IO count */

#define F2FS_LINK_MAX	0xffffffff	/* maximum link count per file */

#define MAX_DIR_RA_PAGES	4	/* maximum ra pages of dir */
@@ -1020,6 +1022,7 @@ struct f2fs_io_info {
	bool retry;		/* need to reallocate block address */
	enum iostat_type io_type;	/* io type */
	struct writeback_control *io_wbc; /* writeback control */
	unsigned char version;		/* version of the node */
};

#define is_read_io(rw) ((rw) == READ)
@@ -2823,7 +2826,7 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type);
int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid);
bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid);
bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino);
void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
						struct node_info *ni);
pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs);
int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode);
@@ -2850,7 +2853,7 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink);
void f2fs_recover_inline_xattr(struct inode *inode, struct page *page);
int f2fs_recover_xattr_data(struct inode *inode, struct page *page);
int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
			unsigned int segno, struct f2fs_summary_block *sum);
void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
int f2fs_build_node_manager(struct f2fs_sb_info *sbi);
@@ -2928,6 +2931,7 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io);
struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index);
struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index);
bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
					block_t blkaddr, int type);
+6 −1
Original line number Diff line number Diff line
@@ -1067,7 +1067,12 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
			if (ret)
				return ret;

			f2fs_get_node_info(sbi, dn.nid, &ni);
			ret = f2fs_get_node_info(sbi, dn.nid, &ni);
			if (ret) {
				f2fs_put_dnode(&dn);
				return ret;
			}

			ilen = min((pgoff_t)
				ADDRS_PER_PAGE(dn.node_page, dst_inode) -
						dn.ofs_in_node, len - i);
+13 −3
Original line number Diff line number Diff line
@@ -517,7 +517,11 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
			continue;
		}

		f2fs_get_node_info(sbi, nid, &ni);
		if (f2fs_get_node_info(sbi, nid, &ni)) {
			f2fs_put_page(node_page, 1);
			continue;
		}

		if (ni.blk_addr != start_addr + off) {
			f2fs_put_page(node_page, 1);
			continue;
@@ -576,7 +580,10 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
	if (IS_ERR(node_page))
		return false;

	f2fs_get_node_info(sbi, nid, dni);
	if (f2fs_get_node_info(sbi, nid, dni)) {
		f2fs_put_page(node_page, 1);
		return false;
	}

	if (sum->version != dni->version) {
		f2fs_msg(sbi->sb, KERN_WARNING,
@@ -655,7 +662,10 @@ static void move_data_block(struct inode *inode, block_t bidx,
	 */
	f2fs_wait_on_page_writeback(page, DATA, true);

	f2fs_get_node_info(fio.sbi, dn.nid, &ni);
	err = f2fs_get_node_info(fio.sbi, dn.nid, &ni);
	if (err)
		goto put_out;

	set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);

	/* read page */
Loading