Commit 3526302f authored by Nikolay Borisov's avatar Nikolay Borisov Committed by David Sterba

btrfs: streamline btrfs_get_io_failure_record logic

Make the function directly return a pointer to a failure record and
adjust callers to handle it. Also refactor the logic inside so that
the case which allocates the failure record for the first time is not
handled in an 'if' arm, saving us a level of indentation. Finally make
the function static as it's not used outside of extent_io.c .
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 2279a270
......@@ -238,8 +238,6 @@ int set_state_failrec(struct extent_io_tree *tree, u64 start,
struct io_failure_record *failrec);
void btrfs_free_io_failure_record(struct btrfs_inode *inode, u64 start,
u64 end);
int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
struct io_failure_record **failrec_ret);
int free_io_failure(struct extent_io_tree *failure_tree,
struct extent_io_tree *io_tree,
struct io_failure_record *rec);
......
......@@ -2450,8 +2450,8 @@ void btrfs_free_io_failure_record(struct btrfs_inode *inode, u64 start, u64 end)
spin_unlock(&failure_tree->lock);
}
int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
struct io_failure_record **failrec_ret)
static struct io_failure_record *btrfs_get_io_failure_record(struct inode *inode,
u64 start, u64 end)
{
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct io_failure_record *failrec;
......@@ -2463,10 +2463,23 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
u64 logical;
failrec = get_state_failrec(failure_tree, start);
if (IS_ERR(failrec)) {
if (!IS_ERR(failrec)) {
btrfs_debug(fs_info,
"Get IO Failure Record: (found) logical=%llu, start=%llu, len=%llu, validation=%d",
failrec->logical, failrec->start, failrec->len,
failrec->in_validation);
/*
* when data can be on disk more than twice, add to failrec here
* (e.g. with a list for failed_mirror) to make
* clean_io_failure() clean all those errors at once.
*/
return failrec;
}
failrec = kzalloc(sizeof(*failrec), GFP_NOFS);
if (!failrec)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
failrec->start = start;
failrec->len = end - start + 1;
......@@ -2479,7 +2492,7 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
if (!em) {
read_unlock(&em_tree->lock);
kfree(failrec);
return -EIO;
return ERR_PTR(-EIO);
}
if (em->start > start || em->start + em->len <= start) {
......@@ -2489,7 +2502,7 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
read_unlock(&em_tree->lock);
if (!em) {
kfree(failrec);
return -EIO;
return ERR_PTR(-EIO);
}
logical = start - em->start;
......@@ -2497,8 +2510,7 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
logical = em->block_start;
failrec->bio_flags = EXTENT_BIO_COMPRESSED;
extent_set_compress_type(&failrec->bio_flags,
em->compress_type);
extent_set_compress_type(&failrec->bio_flags, em->compress_type);
}
btrfs_debug(fs_info,
......@@ -2508,33 +2520,19 @@ int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
failrec->logical = logical;
free_extent_map(em);
/* set the bits in the private failure tree */
/* Set the bits in the private failure tree */
ret = set_extent_bits(failure_tree, start, end,
EXTENT_LOCKED | EXTENT_DIRTY);
if (ret >= 0)
if (ret >= 0) {
ret = set_state_failrec(failure_tree, start, failrec);
/* set the bits in the inode's tree */
if (ret >= 0)
/* Set the bits in the inode's tree */
ret = set_extent_bits(tree, start, end, EXTENT_DAMAGED);
if (ret < 0) {
} else if (ret < 0) {
kfree(failrec);
return ret;
}
} else {
btrfs_debug(fs_info,
"Get IO Failure Record: (found) logical=%llu, start=%llu, len=%llu, validation=%d",
failrec->logical, failrec->start, failrec->len,
failrec->in_validation);
/*
* when data can be on disk more than twice, add to failrec here
* (e.g. with a list for failed_mirror) to make
* clean_io_failure() clean all those errors at once.
*/
return ERR_PTR(ret);
}
*failrec_ret = failrec;
return 0;
return failrec;
}
static bool btrfs_check_repairable(struct inode *inode, bool needs_validation,
......@@ -2659,16 +2657,15 @@ blk_status_t btrfs_submit_read_repair(struct inode *inode,
struct bio *repair_bio;
struct btrfs_io_bio *repair_io_bio;
blk_status_t status;
int ret;
btrfs_debug(fs_info,
"repair read error: read error at %llu", start);
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
ret = btrfs_get_io_failure_record(inode, start, end, &failrec);
if (ret)
return errno_to_blk_status(ret);
failrec = btrfs_get_io_failure_record(inode, start, end);
if (IS_ERR(failrec))
return errno_to_blk_status(PTR_ERR(failrec));
need_validation = btrfs_io_needs_validation(inode, failed_bio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment