Commit 6e9606d2 authored by Zhao Lei's avatar Zhao Lei Committed by Chris Mason

Btrfs: add ref_count and free function for btrfs_bio

1: ref_count is simple than current RBIO_HOLD_BBIO_MAP_BIT flag
   to keep btrfs_bio's memory in raid56 recovery implement.
2: free function for bbio will make code clean and flexible, plus
   forced data type checking in compile.

Changelog v1->v2:
 Rename following by David Sterba's suggestion:
 put_btrfs_bio() -> btrfs_put_bio()
 get_btrfs_bio() -> btrfs_get_bio()
 bbio->ref_count -> bbio->refs
Signed-off-by: default avatarZhao Lei <zhaolei@cn.fujitsu.com>
Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 8e5cfb55
...@@ -1926,7 +1926,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, ...@@ -1926,7 +1926,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
*/ */
ret = 0; ret = 0;
} }
kfree(bbio); btrfs_put_bbio(bbio);
} }
if (actual_bytes) if (actual_bytes)
......
...@@ -2058,7 +2058,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, ...@@ -2058,7 +2058,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
sector = bbio->stripes[mirror_num-1].physical >> 9; sector = bbio->stripes[mirror_num-1].physical >> 9;
bio->bi_iter.bi_sector = sector; bio->bi_iter.bi_sector = sector;
dev = bbio->stripes[mirror_num-1].dev; dev = bbio->stripes[mirror_num-1].dev;
kfree(bbio); btrfs_put_bbio(bbio);
if (!dev || !dev->bdev || !dev->writeable) { if (!dev || !dev->bdev || !dev->writeable) {
bio_put(bio); bio_put(bio);
return -EIO; return -EIO;
......
...@@ -58,15 +58,6 @@ ...@@ -58,15 +58,6 @@
*/ */
#define RBIO_CACHE_READY_BIT 3 #define RBIO_CACHE_READY_BIT 3
/*
* bbio and raid_map is managed by the caller, so we shouldn't free
* them here. And besides that, all rbios with this flag should not
* be cached, because we need raid_map to check the rbios' stripe
* is the same or not, but it is very likely that the caller has
* free raid_map, so don't cache those rbios.
*/
#define RBIO_HOLD_BBIO_MAP_BIT 4
#define RBIO_CACHE_SIZE 1024 #define RBIO_CACHE_SIZE 1024
enum btrfs_rbio_ops { enum btrfs_rbio_ops {
...@@ -834,19 +825,6 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio) ...@@ -834,19 +825,6 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio)
remove_rbio_from_cache(rbio); remove_rbio_from_cache(rbio);
} }
static inline void
__free_bbio(struct btrfs_bio *bbio, int need)
{
if (need)
kfree(bbio);
}
static inline void free_bbio(struct btrfs_raid_bio *rbio)
{
__free_bbio(rbio->bbio,
!test_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags));
}
static void __free_raid_bio(struct btrfs_raid_bio *rbio) static void __free_raid_bio(struct btrfs_raid_bio *rbio)
{ {
int i; int i;
...@@ -866,8 +844,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio) ...@@ -866,8 +844,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio)
} }
} }
free_bbio(rbio); btrfs_put_bbio(rbio->bbio);
kfree(rbio); kfree(rbio);
} }
...@@ -1774,7 +1751,7 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio, ...@@ -1774,7 +1751,7 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio,
rbio = alloc_rbio(root, bbio, stripe_len); rbio = alloc_rbio(root, bbio, stripe_len);
if (IS_ERR(rbio)) { if (IS_ERR(rbio)) {
__free_bbio(bbio, 1); btrfs_put_bbio(bbio);
return PTR_ERR(rbio); return PTR_ERR(rbio);
} }
bio_list_add(&rbio->bio_list, bio); bio_list_add(&rbio->bio_list, bio);
...@@ -1990,8 +1967,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio) ...@@ -1990,8 +1967,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
cleanup_io: cleanup_io:
if (rbio->operation == BTRFS_RBIO_READ_REBUILD) { if (rbio->operation == BTRFS_RBIO_READ_REBUILD) {
if (err == 0 && if (err == 0)
!test_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags))
cache_rbio_pages(rbio); cache_rbio_pages(rbio);
else else
clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags); clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
...@@ -2153,7 +2129,8 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, ...@@ -2153,7 +2129,8 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
rbio = alloc_rbio(root, bbio, stripe_len); rbio = alloc_rbio(root, bbio, stripe_len);
if (IS_ERR(rbio)) { if (IS_ERR(rbio)) {
__free_bbio(bbio, generic_io); if (generic_io)
btrfs_put_bbio(bbio);
return PTR_ERR(rbio); return PTR_ERR(rbio);
} }
...@@ -2164,7 +2141,8 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, ...@@ -2164,7 +2141,8 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
rbio->faila = find_logical_bio_stripe(rbio, bio); rbio->faila = find_logical_bio_stripe(rbio, bio);
if (rbio->faila == -1) { if (rbio->faila == -1) {
BUG(); BUG();
__free_bbio(bbio, generic_io); if (generic_io)
btrfs_put_bbio(bbio);
kfree(rbio); kfree(rbio);
return -EIO; return -EIO;
} }
...@@ -2173,7 +2151,7 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio, ...@@ -2173,7 +2151,7 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
btrfs_bio_counter_inc_noblocked(root->fs_info); btrfs_bio_counter_inc_noblocked(root->fs_info);
rbio->generic_bio_cnt = 1; rbio->generic_bio_cnt = 1;
} else { } else {
set_bit(RBIO_HOLD_BBIO_MAP_BIT, &rbio->flags); btrfs_get_bbio(bbio);
} }
/* /*
......
...@@ -461,7 +461,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root, ...@@ -461,7 +461,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
spin_unlock(&fs_info->reada_lock); spin_unlock(&fs_info->reada_lock);
btrfs_dev_replace_unlock(&fs_info->dev_replace); btrfs_dev_replace_unlock(&fs_info->dev_replace);
kfree(bbio); btrfs_put_bbio(bbio);
return re; return re;
error: error:
...@@ -486,7 +486,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root, ...@@ -486,7 +486,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
kref_put(&zone->refcnt, reada_zone_release); kref_put(&zone->refcnt, reada_zone_release);
spin_unlock(&fs_info->reada_lock); spin_unlock(&fs_info->reada_lock);
} }
kfree(bbio); btrfs_put_bbio(bbio);
kfree(re); kfree(re);
return re_exist; return re_exist;
} }
......
...@@ -855,7 +855,7 @@ static inline void scrub_get_recover(struct scrub_recover *recover) ...@@ -855,7 +855,7 @@ static inline void scrub_get_recover(struct scrub_recover *recover)
static inline void scrub_put_recover(struct scrub_recover *recover) static inline void scrub_put_recover(struct scrub_recover *recover)
{ {
if (atomic_dec_and_test(&recover->refs)) { if (atomic_dec_and_test(&recover->refs)) {
kfree(recover->bbio); btrfs_put_bbio(recover->bbio);
kfree(recover); kfree(recover);
} }
} }
...@@ -1373,13 +1373,13 @@ static int scrub_setup_recheck_block(struct scrub_ctx *sctx, ...@@ -1373,13 +1373,13 @@ static int scrub_setup_recheck_block(struct scrub_ctx *sctx,
ret = btrfs_map_sblock(fs_info, REQ_GET_READ_MIRRORS, logical, ret = btrfs_map_sblock(fs_info, REQ_GET_READ_MIRRORS, logical,
&mapped_length, &bbio, 0, 1); &mapped_length, &bbio, 0, 1);
if (ret || !bbio || mapped_length < sublen) { if (ret || !bbio || mapped_length < sublen) {
kfree(bbio); btrfs_put_bbio(bbio);
return -EIO; return -EIO;
} }
recover = kzalloc(sizeof(struct scrub_recover), GFP_NOFS); recover = kzalloc(sizeof(struct scrub_recover), GFP_NOFS);
if (!recover) { if (!recover) {
kfree(bbio); btrfs_put_bbio(bbio);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2748,7 +2748,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity) ...@@ -2748,7 +2748,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
rbio_out: rbio_out:
bio_put(bio); bio_put(bio);
bbio_out: bbio_out:
kfree(bbio); btrfs_put_bbio(bbio);
bitmap_or(sparity->ebitmap, sparity->ebitmap, sparity->dbitmap, bitmap_or(sparity->ebitmap, sparity->ebitmap, sparity->dbitmap,
sparity->nsectors); sparity->nsectors);
spin_lock(&sctx->stat_lock); spin_lock(&sctx->stat_lock);
...@@ -3879,14 +3879,14 @@ static void scrub_remap_extent(struct btrfs_fs_info *fs_info, ...@@ -3879,14 +3879,14 @@ static void scrub_remap_extent(struct btrfs_fs_info *fs_info,
&mapped_length, &bbio, 0); &mapped_length, &bbio, 0);
if (ret || !bbio || mapped_length < extent_len || if (ret || !bbio || mapped_length < extent_len ||
!bbio->stripes[0].dev->bdev) { !bbio->stripes[0].dev->bdev) {
kfree(bbio); btrfs_put_bbio(bbio);
return; return;
} }
*extent_physical = bbio->stripes[0].physical; *extent_physical = bbio->stripes[0].physical;
*extent_mirror_num = bbio->mirror_num; *extent_mirror_num = bbio->mirror_num;
*extent_dev = bbio->stripes[0].dev; *extent_dev = bbio->stripes[0].dev;
kfree(bbio); btrfs_put_bbio(bbio);
} }
static int scrub_setup_wr_ctx(struct scrub_ctx *sctx, static int scrub_setup_wr_ctx(struct scrub_ctx *sctx,
......
...@@ -4901,6 +4901,37 @@ static void sort_parity_stripes(struct btrfs_bio *bbio, int num_stripes) ...@@ -4901,6 +4901,37 @@ static void sort_parity_stripes(struct btrfs_bio *bbio, int num_stripes)
} }
} }
static struct btrfs_bio *alloc_btrfs_bio(int total_stripes, int real_stripes)
{
struct btrfs_bio *bbio = kzalloc(
sizeof(struct btrfs_bio) +
sizeof(struct btrfs_bio_stripe) * (total_stripes) +
sizeof(int) * (real_stripes) +
sizeof(u64) * (real_stripes),
GFP_NOFS);
if (!bbio)
return NULL;
atomic_set(&bbio->error, 0);
atomic_set(&bbio->refs, 1);
return bbio;
}
void btrfs_get_bbio(struct btrfs_bio *bbio)
{
WARN_ON(!atomic_read(&bbio->refs));
atomic_inc(&bbio->refs);
}
void btrfs_put_bbio(struct btrfs_bio *bbio)
{
if (!bbio)
return;
if (atomic_dec_and_test(&bbio->refs))
kfree(bbio);
}
static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_bio **bbio_ret, struct btrfs_bio **bbio_ret,
...@@ -5052,7 +5083,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, ...@@ -5052,7 +5083,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
* is not left of the left cursor * is not left of the left cursor
*/ */
ret = -EIO; ret = -EIO;
kfree(tmp_bbio); btrfs_put_bbio(tmp_bbio);
goto out; goto out;
} }
...@@ -5087,11 +5118,11 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, ...@@ -5087,11 +5118,11 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
} else { } else {
WARN_ON(1); WARN_ON(1);
ret = -EIO; ret = -EIO;
kfree(tmp_bbio); btrfs_put_bbio(tmp_bbio);
goto out; goto out;
} }
kfree(tmp_bbio); btrfs_put_bbio(tmp_bbio);
} else if (mirror_num > map->num_stripes) { } else if (mirror_num > map->num_stripes) {
mirror_num = 0; mirror_num = 0;
} }
...@@ -5213,13 +5244,11 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, ...@@ -5213,13 +5244,11 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
tgtdev_indexes = num_stripes; tgtdev_indexes = num_stripes;
} }
bbio = kzalloc(btrfs_bio_size(num_alloc_stripes, tgtdev_indexes), bbio = alloc_btrfs_bio(num_alloc_stripes, tgtdev_indexes);
GFP_NOFS);
if (!bbio) { if (!bbio) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
atomic_set(&bbio->error, 0);
if (dev_replace_is_ongoing) if (dev_replace_is_ongoing)
bbio->tgtdev_map = (int *)(bbio->stripes + num_alloc_stripes); bbio->tgtdev_map = (int *)(bbio->stripes + num_alloc_stripes);
...@@ -5558,7 +5587,7 @@ static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int e ...@@ -5558,7 +5587,7 @@ static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int e
bio_endio_nodec(bio, err); bio_endio_nodec(bio, err);
else else
bio_endio(bio, err); bio_endio(bio, err);
kfree(bbio); btrfs_put_bbio(bbio);
} }
static void btrfs_end_bio(struct bio *bio, int err) static void btrfs_end_bio(struct bio *bio, int err)
......
...@@ -295,6 +295,7 @@ typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err); ...@@ -295,6 +295,7 @@ typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
#define BTRFS_BIO_ORIG_BIO_SUBMITTED (1 << 0) #define BTRFS_BIO_ORIG_BIO_SUBMITTED (1 << 0)
struct btrfs_bio { struct btrfs_bio {
atomic_t refs;
atomic_t stripes_pending; atomic_t stripes_pending;
struct btrfs_fs_info *fs_info; struct btrfs_fs_info *fs_info;
bio_end_io_t *end_io; bio_end_io_t *end_io;
...@@ -394,13 +395,8 @@ struct btrfs_balance_control { ...@@ -394,13 +395,8 @@ struct btrfs_balance_control {
int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
u64 end, u64 *length); u64 end, u64 *length);
void btrfs_get_bbio(struct btrfs_bio *bbio);
#define btrfs_bio_size(total_stripes, real_stripes) \ void btrfs_put_bbio(struct btrfs_bio *bbio);
(sizeof(struct btrfs_bio) + \
(sizeof(struct btrfs_bio_stripe) * (total_stripes)) + \
(sizeof(int) * (real_stripes)) + \
(sizeof(u64) * (real_stripes)))
int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_bio **bbio_ret, int mirror_num); struct btrfs_bio **bbio_ret, int mirror_num);
......
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