Skip to content

Commit

Permalink
f2fs: fix to propagate error from __get_meta_page()
Browse files Browse the repository at this point in the history
If caller of __get_meta_page() can handle error, let's propagate error
from __get_meta_page().

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
  • Loading branch information
chaseyu authored and Jaegeuk Kim committed Aug 1, 2018
1 parent 18dd647 commit 7735730
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 56 deletions.
55 changes: 41 additions & 14 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 21 additions & 3 deletions fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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,
Expand Down Expand Up @@ -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) +
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions fs/f2fs/f2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion fs/f2fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 13 additions & 3 deletions fs/f2fs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down
14 changes: 13 additions & 1 deletion fs/f2fs/inline.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
.encrypted_page = NULL,
.io_type = FS_DATA_IO,
};
struct node_info ni;
int dirty, err;

if (!f2fs_exist_data(dn->inode))
Expand All @@ -130,6 +131,14 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
if (err)
return err;

err = f2fs_get_node_info(fio.sbi, dn->nid, &ni);
if (err) {
f2fs_put_dnode(dn);
return err;
}

fio.version = ni.version;

if (unlikely(dn->data_blkaddr != NEW_ADDR)) {
f2fs_put_dnode(dn);
set_sbi_flag(fio.sbi, SBI_NEED_FSCK);
Expand Down Expand Up @@ -690,7 +699,10 @@ int f2fs_inline_data_fiemap(struct inode *inode,
ilen = start + len;
ilen -= start;

f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
if (err)
goto out;

byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits;
byteaddr += (char *)inline_data_addr(inode, ipage) -
(char *)F2FS_INODE(ipage);
Expand Down
12 changes: 10 additions & 2 deletions fs/f2fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ void f2fs_handle_failed_inode(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct node_info ni;
int err;

/*
* clear nlink of inode in order to release resource of inode
Expand All @@ -721,10 +722,16 @@ void f2fs_handle_failed_inode(struct inode *inode)
* so we can prevent losing this orphan when encoutering checkpoint
* and following suddenly power-off.
*/
f2fs_get_node_info(sbi, inode->i_ino, &ni);
err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
if (err) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_msg(sbi->sb, KERN_WARNING,
"May loss orphan inode, run fsck to fix.");
goto out;
}

if (ni.blk_addr != NULL_ADDR) {
int err = f2fs_acquire_orphan_inode(sbi);
err = f2fs_acquire_orphan_inode(sbi);
if (err) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_msg(sbi->sb, KERN_WARNING,
Expand All @@ -737,6 +744,7 @@ void f2fs_handle_failed_inode(struct inode *inode)
set_inode_flag(inode, FI_FREE_NID);
}

out:
f2fs_unlock_op(sbi);

/* iput will drop the inode object */
Expand Down
Loading

0 comments on commit 7735730

Please sign in to comment.