mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
nilfs2: call nilfs_error inside bmap routines
Some functions using nilfs bmap routines can wrongly return invalid argument error (i.e. -EINVAL) that bmap returns as an internal code for btree corruption. This fixes the issue by catching and converting the internal EINVAL to EIO and calling nilfs_error function inside bmap routines. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
This commit is contained in:
parent
b004a5eb0b
commit
e828949e5b
@ -38,6 +38,19 @@ struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
|
|||||||
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
|
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nilfs_bmap_convert_error(struct nilfs_bmap *bmap,
|
||||||
|
const char *fname, int err)
|
||||||
|
{
|
||||||
|
struct inode *inode = bmap->b_inode;
|
||||||
|
|
||||||
|
if (err == -EINVAL) {
|
||||||
|
nilfs_error(inode->i_sb, fname,
|
||||||
|
"broken bmap (inode number=%lu)\n", inode->i_ino);
|
||||||
|
err = -EIO;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nilfs_bmap_lookup_at_level - find a data block or node block
|
* nilfs_bmap_lookup_at_level - find a data block or node block
|
||||||
* @bmap: bmap
|
* @bmap: bmap
|
||||||
@ -66,8 +79,10 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
|
|||||||
|
|
||||||
down_read(&bmap->b_sem);
|
down_read(&bmap->b_sem);
|
||||||
ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
|
ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
ret = nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
if (NILFS_BMAP_USE_VBN(bmap)) {
|
if (NILFS_BMAP_USE_VBN(bmap)) {
|
||||||
ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
|
ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
|
||||||
&blocknr);
|
&blocknr);
|
||||||
@ -88,7 +103,8 @@ int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
|
|||||||
down_read(&bmap->b_sem);
|
down_read(&bmap->b_sem);
|
||||||
ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
|
ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
|
||||||
up_read(&bmap->b_sem);
|
up_read(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
|
static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
|
||||||
@ -144,7 +160,8 @@ int nilfs_bmap_insert(struct nilfs_bmap *bmap,
|
|||||||
down_write(&bmap->b_sem);
|
down_write(&bmap->b_sem);
|
||||||
ret = nilfs_bmap_do_insert(bmap, key, rec);
|
ret = nilfs_bmap_do_insert(bmap, key, rec);
|
||||||
up_write(&bmap->b_sem);
|
up_write(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
|
static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
|
||||||
@ -180,9 +197,12 @@ int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key)
|
|||||||
|
|
||||||
down_read(&bmap->b_sem);
|
down_read(&bmap->b_sem);
|
||||||
ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
|
ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
|
||||||
if (!ret)
|
|
||||||
*key = lastkey;
|
|
||||||
up_read(&bmap->b_sem);
|
up_read(&bmap->b_sem);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
ret = nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
|
else
|
||||||
|
*key = lastkey;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +230,8 @@ int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key)
|
|||||||
down_write(&bmap->b_sem);
|
down_write(&bmap->b_sem);
|
||||||
ret = nilfs_bmap_do_delete(bmap, key);
|
ret = nilfs_bmap_do_delete(bmap, key);
|
||||||
up_write(&bmap->b_sem);
|
up_write(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
|
static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key)
|
||||||
@ -261,7 +282,8 @@ int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key)
|
|||||||
down_write(&bmap->b_sem);
|
down_write(&bmap->b_sem);
|
||||||
ret = nilfs_bmap_do_truncate(bmap, key);
|
ret = nilfs_bmap_do_truncate(bmap, key);
|
||||||
up_write(&bmap->b_sem);
|
up_write(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -300,7 +322,8 @@ int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh)
|
|||||||
down_write(&bmap->b_sem);
|
down_write(&bmap->b_sem);
|
||||||
ret = bmap->b_ops->bop_propagate(bmap, bh);
|
ret = bmap->b_ops->bop_propagate(bmap, bh);
|
||||||
up_write(&bmap->b_sem);
|
up_write(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -344,7 +367,8 @@ int nilfs_bmap_assign(struct nilfs_bmap *bmap,
|
|||||||
down_write(&bmap->b_sem);
|
down_write(&bmap->b_sem);
|
||||||
ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
|
ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
|
||||||
up_write(&bmap->b_sem);
|
up_write(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -373,7 +397,8 @@ int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level)
|
|||||||
down_write(&bmap->b_sem);
|
down_write(&bmap->b_sem);
|
||||||
ret = bmap->b_ops->bop_mark(bmap, key, level);
|
ret = bmap->b_ops->bop_mark(bmap, key, level);
|
||||||
up_write(&bmap->b_sem);
|
up_write(&bmap->b_sem);
|
||||||
return ret;
|
|
||||||
|
return nilfs_bmap_convert_error(bmap, __func__, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,14 +149,9 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino,
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh);
|
err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh);
|
||||||
if (unlikely(err)) {
|
if (unlikely(err))
|
||||||
if (err == -EINVAL)
|
nilfs_warning(sb, __func__, "unable to read inode: %lu",
|
||||||
nilfs_error(sb, __func__, "ifile is broken");
|
(unsigned long) ino);
|
||||||
else
|
|
||||||
nilfs_warning(sb, __func__,
|
|
||||||
"unable to read inode: %lu",
|
|
||||||
(unsigned long) ino);
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,11 +96,6 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
|
|||||||
inode->i_ino,
|
inode->i_ino,
|
||||||
(unsigned long long)blkoff);
|
(unsigned long long)blkoff);
|
||||||
err = 0;
|
err = 0;
|
||||||
} else if (err == -EINVAL) {
|
|
||||||
nilfs_error(inode->i_sb, __func__,
|
|
||||||
"broken bmap (inode=%lu)\n",
|
|
||||||
inode->i_ino);
|
|
||||||
err = -EIO;
|
|
||||||
}
|
}
|
||||||
nilfs_transaction_abort(inode->i_sb);
|
nilfs_transaction_abort(inode->i_sb);
|
||||||
goto out;
|
goto out;
|
||||||
@ -629,7 +624,7 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii,
|
|||||||
|
|
||||||
if (!test_bit(NILFS_I_BMAP, &ii->i_state))
|
if (!test_bit(NILFS_I_BMAP, &ii->i_state))
|
||||||
return;
|
return;
|
||||||
repeat:
|
repeat:
|
||||||
ret = nilfs_bmap_last_key(ii->i_bmap, &b);
|
ret = nilfs_bmap_last_key(ii->i_bmap, &b);
|
||||||
if (ret == -ENOENT)
|
if (ret == -ENOENT)
|
||||||
return;
|
return;
|
||||||
@ -646,14 +641,10 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii,
|
|||||||
nilfs_bmap_truncate(ii->i_bmap, b) == 0))
|
nilfs_bmap_truncate(ii->i_bmap, b) == 0))
|
||||||
goto repeat;
|
goto repeat;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
if (ret == -EINVAL)
|
nilfs_warning(ii->vfs_inode.i_sb, __func__,
|
||||||
nilfs_error(ii->vfs_inode.i_sb, __func__,
|
"failed to truncate bmap (ino=%lu, err=%d)",
|
||||||
"bmap is broken (ino=%lu)", ii->vfs_inode.i_ino);
|
ii->vfs_inode.i_ino, ret);
|
||||||
else
|
|
||||||
nilfs_warning(ii->vfs_inode.i_sb, __func__,
|
|
||||||
"failed to truncate bmap (ino=%lu, err=%d)",
|
|
||||||
ii->vfs_inode.i_ino, ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nilfs_truncate(struct inode *inode)
|
void nilfs_truncate(struct inode *inode)
|
||||||
|
@ -237,8 +237,6 @@ static int nilfs_mdt_read_block(struct inode *inode, unsigned long block,
|
|||||||
*
|
*
|
||||||
* %-ENOENT - the specified block does not exist (hole block)
|
* %-ENOENT - the specified block does not exist (hole block)
|
||||||
*
|
*
|
||||||
* %-EINVAL - bmap is broken. (the caller should call nilfs_error())
|
|
||||||
*
|
|
||||||
* %-EROFS - Read only filesystem (for create mode)
|
* %-EROFS - Read only filesystem (for create mode)
|
||||||
*/
|
*/
|
||||||
int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create,
|
int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create,
|
||||||
@ -273,8 +271,6 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create,
|
|||||||
* %-ENOMEM - Insufficient memory available.
|
* %-ENOMEM - Insufficient memory available.
|
||||||
*
|
*
|
||||||
* %-EIO - I/O error
|
* %-EIO - I/O error
|
||||||
*
|
|
||||||
* %-EINVAL - bmap is broken. (the caller should call nilfs_error())
|
|
||||||
*/
|
*/
|
||||||
int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
|
int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
|
||||||
{
|
{
|
||||||
@ -350,8 +346,6 @@ int nilfs_mdt_forget_block(struct inode *inode, unsigned long block)
|
|||||||
* %-EIO - I/O error
|
* %-EIO - I/O error
|
||||||
*
|
*
|
||||||
* %-ENOENT - the specified block does not exist (hole block)
|
* %-ENOENT - the specified block does not exist (hole block)
|
||||||
*
|
|
||||||
* %-EINVAL - bmap is broken. (the caller should call nilfs_error())
|
|
||||||
*/
|
*/
|
||||||
int nilfs_mdt_mark_block_dirty(struct inode *inode, unsigned long block)
|
int nilfs_mdt_mark_block_dirty(struct inode *inode, unsigned long block)
|
||||||
{
|
{
|
||||||
|
@ -504,17 +504,6 @@ static int nilfs_segctor_add_file_block(struct nilfs_sc_info *sci,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nilfs_handle_bmap_error(int err, const char *fname,
|
|
||||||
struct inode *inode, struct super_block *sb)
|
|
||||||
{
|
|
||||||
if (err == -EINVAL) {
|
|
||||||
nilfs_error(sb, fname, "broken bmap (inode=%lu)\n",
|
|
||||||
inode->i_ino);
|
|
||||||
err = -EIO;
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback functions that enumerate, mark, and collect dirty blocks
|
* Callback functions that enumerate, mark, and collect dirty blocks
|
||||||
*/
|
*/
|
||||||
@ -524,9 +513,8 @@ static int nilfs_collect_file_data(struct nilfs_sc_info *sci,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
|
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
|
||||||
if (unlikely(err < 0))
|
if (err < 0)
|
||||||
return nilfs_handle_bmap_error(err, __func__, inode,
|
return err;
|
||||||
sci->sc_super);
|
|
||||||
|
|
||||||
err = nilfs_segctor_add_file_block(sci, bh, inode,
|
err = nilfs_segctor_add_file_block(sci, bh, inode,
|
||||||
sizeof(struct nilfs_binfo_v));
|
sizeof(struct nilfs_binfo_v));
|
||||||
@ -539,13 +527,7 @@ static int nilfs_collect_file_node(struct nilfs_sc_info *sci,
|
|||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
struct inode *inode)
|
struct inode *inode)
|
||||||
{
|
{
|
||||||
int err;
|
return nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
|
||||||
|
|
||||||
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
|
|
||||||
if (unlikely(err < 0))
|
|
||||||
return nilfs_handle_bmap_error(err, __func__, inode,
|
|
||||||
sci->sc_super);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci,
|
static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci,
|
||||||
@ -588,9 +570,8 @@ static int nilfs_collect_dat_data(struct nilfs_sc_info *sci,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
|
err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);
|
||||||
if (unlikely(err < 0))
|
if (err < 0)
|
||||||
return nilfs_handle_bmap_error(err, __func__, inode,
|
return err;
|
||||||
sci->sc_super);
|
|
||||||
|
|
||||||
err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64));
|
err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64));
|
||||||
if (!err)
|
if (!err)
|
||||||
@ -1563,7 +1544,6 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_bmap:
|
failed_bmap:
|
||||||
err = nilfs_handle_bmap_error(err, __func__, inode, sci->sc_super);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user