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

Commit e828949e authored by Ryusuke Konishi's avatar Ryusuke Konishi
Browse files

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: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
parent b004a5eb
Loading
Loading
Loading
Loading
+35 −10
Original line number Original line Diff line number Diff line
@@ -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);
}
}


/**
/**
+3 −8
Original line number Original line Diff line number Diff line
@@ -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");
		else
			nilfs_warning(sb, __func__,
				      "unable to read inode: %lu",
			      (unsigned long) ino);
			      (unsigned long) ino);
	}
	return err;
	return err;
}
}


+5 −14
Original line number Original line Diff line number Diff line
@@ -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;
@@ -647,10 +642,6 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii,
		goto repeat;
		goto repeat;


failed:
failed:
	if (ret == -EINVAL)
		nilfs_error(ii->vfs_inode.i_sb, __func__,
			    "bmap is broken (ino=%lu)", ii->vfs_inode.i_ino);
	else
	nilfs_warning(ii->vfs_inode.i_sb, __func__,
	nilfs_warning(ii->vfs_inode.i_sb, __func__,
		      "failed to truncate bmap (ino=%lu, err=%d)",
		      "failed to truncate bmap (ino=%lu, err=%d)",
		      ii->vfs_inode.i_ino, ret);
		      ii->vfs_inode.i_ino, ret);
+0 −6
Original line number Original line Diff line number Diff line
@@ -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)
{
{
+5 −25
Original line number Original line Diff line number Diff line
@@ -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;
}
}