btrfs: raid56: use fixed stripe length everywhere

The raid56 code assumes a fixed stripe length BTRFS_STRIPE_LEN but there
are functions passing it as arguments, this is not necessary. The fixed
value has been used for a long time and though the stripe length should
be configurable by super block member stripesize, this hasn't been
implemented and would require more changes so we don't need to keep this
code around until then.

Partially based on a patch from Qu Wenruo.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Tested-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
[ update changelog ]
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Christoph Hellwig 2022-06-17 12:04:05 +02:00 committed by David Sterba
parent 0201fceb9f
commit ff18a4afeb
4 changed files with 39 additions and 56 deletions

View File

@ -474,9 +474,9 @@ static int rbio_is_full(struct btrfs_raid_bio *rbio)
int ret = 1; int ret = 1;
spin_lock_irqsave(&rbio->bio_list_lock, flags); spin_lock_irqsave(&rbio->bio_list_lock, flags);
if (size != rbio->nr_data * rbio->stripe_len) if (size != rbio->nr_data * BTRFS_STRIPE_LEN)
ret = 0; ret = 0;
BUG_ON(size > rbio->nr_data * rbio->stripe_len); BUG_ON(size > rbio->nr_data * BTRFS_STRIPE_LEN);
spin_unlock_irqrestore(&rbio->bio_list_lock, flags); spin_unlock_irqrestore(&rbio->bio_list_lock, flags);
return ret; return ret;
@ -913,18 +913,17 @@ static struct sector_ptr *sector_in_rbio(struct btrfs_raid_bio *rbio,
* this does not allocate any pages for rbio->pages. * this does not allocate any pages for rbio->pages.
*/ */
static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info, static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
struct btrfs_io_context *bioc, struct btrfs_io_context *bioc)
u32 stripe_len)
{ {
const unsigned int real_stripes = bioc->num_stripes - bioc->num_tgtdevs; const unsigned int real_stripes = bioc->num_stripes - bioc->num_tgtdevs;
const unsigned int stripe_npages = stripe_len >> PAGE_SHIFT; const unsigned int stripe_npages = BTRFS_STRIPE_LEN >> PAGE_SHIFT;
const unsigned int num_pages = stripe_npages * real_stripes; const unsigned int num_pages = stripe_npages * real_stripes;
const unsigned int stripe_nsectors = stripe_len >> fs_info->sectorsize_bits; const unsigned int stripe_nsectors =
BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits;
const unsigned int num_sectors = stripe_nsectors * real_stripes; const unsigned int num_sectors = stripe_nsectors * real_stripes;
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
void *p; void *p;
ASSERT(IS_ALIGNED(stripe_len, PAGE_SIZE));
/* PAGE_SIZE must also be aligned to sectorsize for subpage support */ /* PAGE_SIZE must also be aligned to sectorsize for subpage support */
ASSERT(IS_ALIGNED(PAGE_SIZE, fs_info->sectorsize)); ASSERT(IS_ALIGNED(PAGE_SIZE, fs_info->sectorsize));
/* /*
@ -948,7 +947,6 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
INIT_LIST_HEAD(&rbio->stripe_cache); INIT_LIST_HEAD(&rbio->stripe_cache);
INIT_LIST_HEAD(&rbio->hash_list); INIT_LIST_HEAD(&rbio->hash_list);
rbio->bioc = bioc; rbio->bioc = bioc;
rbio->stripe_len = stripe_len;
rbio->nr_pages = num_pages; rbio->nr_pages = num_pages;
rbio->nr_sectors = num_sectors; rbio->nr_sectors = num_sectors;
rbio->real_stripes = real_stripes; rbio->real_stripes = real_stripes;
@ -1020,7 +1018,6 @@ static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
struct sector_ptr *sector, struct sector_ptr *sector,
unsigned int stripe_nr, unsigned int stripe_nr,
unsigned int sector_nr, unsigned int sector_nr,
unsigned long bio_max_len,
unsigned int opf) unsigned int opf)
{ {
const u32 sectorsize = rbio->bioc->fs_info->sectorsize; const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
@ -1065,7 +1062,8 @@ static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
} }
/* put a new bio on the list */ /* put a new bio on the list */
bio = bio_alloc(stripe->dev->bdev, max(bio_max_len >> PAGE_SHIFT, 1UL), bio = bio_alloc(stripe->dev->bdev,
max(BTRFS_STRIPE_LEN >> PAGE_SHIFT, 1),
opf, GFP_NOFS); opf, GFP_NOFS);
bio->bi_iter.bi_sector = disk_start >> 9; bio->bi_iter.bi_sector = disk_start >> 9;
bio->bi_private = rbio; bio->bi_private = rbio;
@ -1287,8 +1285,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
} }
ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe, ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
sectornr, rbio->stripe_len, sectornr, REQ_OP_WRITE);
REQ_OP_WRITE);
if (ret) if (ret)
goto cleanup; goto cleanup;
} }
@ -1327,8 +1324,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
ret = rbio_add_io_sector(rbio, &bio_list, sector, ret = rbio_add_io_sector(rbio, &bio_list, sector,
rbio->bioc->tgtdev_map[stripe], rbio->bioc->tgtdev_map[stripe],
sectornr, rbio->stripe_len, sectornr, REQ_OP_WRITE);
REQ_OP_WRITE);
if (ret) if (ret)
goto cleanup; goto cleanup;
} }
@ -1373,7 +1369,7 @@ static int find_bio_stripe(struct btrfs_raid_bio *rbio,
for (i = 0; i < rbio->bioc->num_stripes; i++) { for (i = 0; i < rbio->bioc->num_stripes; i++) {
stripe = &rbio->bioc->stripes[i]; stripe = &rbio->bioc->stripes[i];
if (in_range(physical, stripe->physical, rbio->stripe_len) && if (in_range(physical, stripe->physical, BTRFS_STRIPE_LEN) &&
stripe->dev->bdev && bio->bi_bdev == stripe->dev->bdev) { stripe->dev->bdev && bio->bi_bdev == stripe->dev->bdev) {
return i; return i;
} }
@ -1395,7 +1391,7 @@ static int find_logical_bio_stripe(struct btrfs_raid_bio *rbio,
for (i = 0; i < rbio->nr_data; i++) { for (i = 0; i < rbio->nr_data; i++) {
u64 stripe_start = rbio->bioc->raid_map[i]; u64 stripe_start = rbio->bioc->raid_map[i];
if (in_range(logical, stripe_start, rbio->stripe_len)) if (in_range(logical, stripe_start, BTRFS_STRIPE_LEN))
return i; return i;
} }
return -1; return -1;
@ -1580,8 +1576,7 @@ static int raid56_rmw_stripe(struct btrfs_raid_bio *rbio)
continue; continue;
ret = rbio_add_io_sector(rbio, &bio_list, sector, ret = rbio_add_io_sector(rbio, &bio_list, sector,
stripe, sectornr, rbio->stripe_len, stripe, sectornr, REQ_OP_READ);
REQ_OP_READ);
if (ret) if (ret)
goto cleanup; goto cleanup;
} }
@ -1790,7 +1785,7 @@ static void rbio_add_bio(struct btrfs_raid_bio *rbio, struct bio *orig_bio)
ASSERT(orig_logical >= full_stripe_start && ASSERT(orig_logical >= full_stripe_start &&
orig_logical + orig_len <= full_stripe_start + orig_logical + orig_len <= full_stripe_start +
rbio->nr_data * rbio->stripe_len); rbio->nr_data * BTRFS_STRIPE_LEN);
bio_list_add(&rbio->bio_list, orig_bio); bio_list_add(&rbio->bio_list, orig_bio);
rbio->bio_list_bytes += orig_bio->bi_iter.bi_size; rbio->bio_list_bytes += orig_bio->bi_iter.bi_size;
@ -1808,7 +1803,7 @@ static void rbio_add_bio(struct btrfs_raid_bio *rbio, struct bio *orig_bio)
/* /*
* our main entry point for writes from the rest of the FS. * our main entry point for writes from the rest of the FS.
*/ */
int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc, u32 stripe_len) int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc)
{ {
struct btrfs_fs_info *fs_info = bioc->fs_info; struct btrfs_fs_info *fs_info = bioc->fs_info;
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
@ -1816,7 +1811,7 @@ int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc, u32 stri
struct blk_plug_cb *cb; struct blk_plug_cb *cb;
int ret; int ret;
rbio = alloc_rbio(fs_info, bioc, stripe_len); rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) { if (IS_ERR(rbio)) {
btrfs_put_bioc(bioc); btrfs_put_bioc(bioc);
return PTR_ERR(rbio); return PTR_ERR(rbio);
@ -2140,8 +2135,7 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
} }
sector = rbio_stripe_sector(rbio, stripe, sectornr); sector = rbio_stripe_sector(rbio, stripe, sectornr);
ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe, ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
sectornr, rbio->stripe_len, sectornr, REQ_OP_READ);
REQ_OP_READ);
if (ret < 0) if (ret < 0)
goto cleanup; goto cleanup;
} }
@ -2199,7 +2193,7 @@ cleanup:
* of the drive. * of the drive.
*/ */
int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc, int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
u32 stripe_len, int mirror_num, int generic_io) int mirror_num, int generic_io)
{ {
struct btrfs_fs_info *fs_info = bioc->fs_info; struct btrfs_fs_info *fs_info = bioc->fs_info;
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
@ -2210,7 +2204,7 @@ int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
btrfs_bio(bio)->mirror_num = mirror_num; btrfs_bio(bio)->mirror_num = mirror_num;
} }
rbio = alloc_rbio(fs_info, bioc, stripe_len); rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) { if (IS_ERR(rbio)) {
if (generic_io) if (generic_io)
btrfs_put_bioc(bioc); btrfs_put_bioc(bioc);
@ -2304,14 +2298,14 @@ static void read_rebuild_work(struct work_struct *work)
struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio, struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
struct btrfs_io_context *bioc, struct btrfs_io_context *bioc,
u32 stripe_len, struct btrfs_device *scrub_dev, struct btrfs_device *scrub_dev,
unsigned long *dbitmap, int stripe_nsectors) unsigned long *dbitmap, int stripe_nsectors)
{ {
struct btrfs_fs_info *fs_info = bioc->fs_info; struct btrfs_fs_info *fs_info = bioc->fs_info;
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
int i; int i;
rbio = alloc_rbio(fs_info, bioc, stripe_len); rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) if (IS_ERR(rbio))
return NULL; return NULL;
bio_list_add(&rbio->bio_list, bio); bio_list_add(&rbio->bio_list, bio);
@ -2356,7 +2350,7 @@ void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page,
ASSERT(logical >= rbio->bioc->raid_map[0]); ASSERT(logical >= rbio->bioc->raid_map[0]);
ASSERT(logical + sectorsize <= rbio->bioc->raid_map[0] + ASSERT(logical + sectorsize <= rbio->bioc->raid_map[0] +
rbio->stripe_len * rbio->nr_data); BTRFS_STRIPE_LEN * rbio->nr_data);
stripe_offset = (int)(logical - rbio->bioc->raid_map[0]); stripe_offset = (int)(logical - rbio->bioc->raid_map[0]);
index = stripe_offset / sectorsize; index = stripe_offset / sectorsize;
rbio->bio_sectors[index].page = page; rbio->bio_sectors[index].page = page;
@ -2512,7 +2506,7 @@ writeback:
sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr); sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
ret = rbio_add_io_sector(rbio, &bio_list, sector, rbio->scrubp, ret = rbio_add_io_sector(rbio, &bio_list, sector, rbio->scrubp,
sectornr, rbio->stripe_len, REQ_OP_WRITE); sectornr, REQ_OP_WRITE);
if (ret) if (ret)
goto cleanup; goto cleanup;
} }
@ -2526,7 +2520,7 @@ writeback:
sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr); sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
ret = rbio_add_io_sector(rbio, &bio_list, sector, ret = rbio_add_io_sector(rbio, &bio_list, sector,
bioc->tgtdev_map[rbio->scrubp], bioc->tgtdev_map[rbio->scrubp],
sectornr, rbio->stripe_len, REQ_OP_WRITE); sectornr, REQ_OP_WRITE);
if (ret) if (ret)
goto cleanup; goto cleanup;
} }
@ -2693,7 +2687,7 @@ static void raid56_parity_scrub_stripe(struct btrfs_raid_bio *rbio)
continue; continue;
ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe, ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
sectornr, rbio->stripe_len, REQ_OP_READ); sectornr, REQ_OP_READ);
if (ret) if (ret)
goto cleanup; goto cleanup;
} }
@ -2758,13 +2752,12 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio)
/* The following code is used for dev replace of a missing RAID 5/6 device. */ /* The following code is used for dev replace of a missing RAID 5/6 device. */
struct btrfs_raid_bio * struct btrfs_raid_bio *
raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc, raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc)
u64 length)
{ {
struct btrfs_fs_info *fs_info = bioc->fs_info; struct btrfs_fs_info *fs_info = bioc->fs_info;
struct btrfs_raid_bio *rbio; struct btrfs_raid_bio *rbio;
rbio = alloc_rbio(fs_info, bioc, length); rbio = alloc_rbio(fs_info, bioc);
if (IS_ERR(rbio)) if (IS_ERR(rbio))
return NULL; return NULL;

View File

@ -56,9 +56,6 @@ struct btrfs_raid_bio {
*/ */
enum btrfs_rbio_ops operation; enum btrfs_rbio_ops operation;
/* Size of each individual stripe on disk */
u32 stripe_len;
/* How many pages there are for the full stripe including P/Q */ /* How many pages there are for the full stripe including P/Q */
u16 nr_pages; u16 nr_pages;
@ -169,21 +166,20 @@ static inline int nr_data_stripes(const struct map_lookup *map)
struct btrfs_device; struct btrfs_device;
int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc, int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
u32 stripe_len, int mirror_num, int generic_io); int mirror_num, int generic_io);
int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc, u32 stripe_len); int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc);
void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page, void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page,
unsigned int pgoff, u64 logical); unsigned int pgoff, u64 logical);
struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio, struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
struct btrfs_io_context *bioc, u32 stripe_len, struct btrfs_io_context *bioc,
struct btrfs_device *scrub_dev, struct btrfs_device *scrub_dev,
unsigned long *dbitmap, int stripe_nsectors); unsigned long *dbitmap, int stripe_nsectors);
void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio); void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
struct btrfs_raid_bio * struct btrfs_raid_bio *
raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc, raid56_alloc_missing_rbio(struct bio *bio, struct btrfs_io_context *bioc);
u64 length);
void raid56_submit_missing_rbio(struct btrfs_raid_bio *rbio); void raid56_submit_missing_rbio(struct btrfs_raid_bio *rbio);
int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info); int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);

View File

@ -1216,7 +1216,6 @@ static inline int scrub_nr_raid_mirrors(struct btrfs_io_context *bioc)
static inline void scrub_stripe_index_and_offset(u64 logical, u64 map_type, static inline void scrub_stripe_index_and_offset(u64 logical, u64 map_type,
u64 *raid_map, u64 *raid_map,
u64 mapped_length,
int nstripes, int mirror, int nstripes, int mirror,
int *stripe_index, int *stripe_index,
u64 *stripe_offset) u64 *stripe_offset)
@ -1231,7 +1230,7 @@ static inline void scrub_stripe_index_and_offset(u64 logical, u64 map_type,
continue; continue;
if (logical >= raid_map[i] && if (logical >= raid_map[i] &&
logical < raid_map[i] + mapped_length) logical < raid_map[i] + BTRFS_STRIPE_LEN)
break; break;
} }
@ -1335,7 +1334,6 @@ leave_nomem:
scrub_stripe_index_and_offset(logical, scrub_stripe_index_and_offset(logical,
bioc->map_type, bioc->map_type,
bioc->raid_map, bioc->raid_map,
mapped_length,
bioc->num_stripes - bioc->num_stripes -
bioc->num_tgtdevs, bioc->num_tgtdevs,
mirror_index, mirror_index,
@ -1387,7 +1385,6 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info,
mirror_num = sector->sblock->sectors[0]->mirror_num; mirror_num = sector->sblock->sectors[0]->mirror_num;
ret = raid56_parity_recover(bio, sector->recover->bioc, ret = raid56_parity_recover(bio, sector->recover->bioc,
sector->recover->map_length,
mirror_num, 0); mirror_num, 0);
if (ret) if (ret)
return ret; return ret;
@ -2195,7 +2192,7 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
bio->bi_private = sblock; bio->bi_private = sblock;
bio->bi_end_io = scrub_missing_raid56_end_io; bio->bi_end_io = scrub_missing_raid56_end_io;
rbio = raid56_alloc_missing_rbio(bio, bioc, length); rbio = raid56_alloc_missing_rbio(bio, bioc);
if (!rbio) if (!rbio)
goto rbio_out; goto rbio_out;
@ -2829,7 +2826,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
bio->bi_private = sparity; bio->bi_private = sparity;
bio->bi_end_io = scrub_parity_bio_endio; bio->bi_end_io = scrub_parity_bio_endio;
rbio = raid56_parity_alloc_scrub_rbio(bio, bioc, length, rbio = raid56_parity_alloc_scrub_rbio(bio, bioc,
sparity->scrub_dev, sparity->scrub_dev,
&sparity->dbitmap, &sparity->dbitmap,
sparity->nsectors); sparity->nsectors);

View File

@ -6461,6 +6461,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
} }
} else if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) { } else if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
ASSERT(map->stripe_len == BTRFS_STRIPE_LEN);
if (need_raid_map && (need_full_stripe(op) || mirror_num > 1)) { if (need_raid_map && (need_full_stripe(op) || mirror_num > 1)) {
/* push stripe_nr back to the start of the full stripe */ /* push stripe_nr back to the start of the full stripe */
stripe_nr = div64_u64(raid56_full_stripe_start, stripe_nr = div64_u64(raid56_full_stripe_start,
@ -6758,14 +6759,10 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
if ((bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) && if ((bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
((btrfs_op(bio) == BTRFS_MAP_WRITE) || (mirror_num > 1))) { ((btrfs_op(bio) == BTRFS_MAP_WRITE) || (mirror_num > 1))) {
/* In this case, map_length has been set to the length of if (btrfs_op(bio) == BTRFS_MAP_WRITE)
a single stripe; not the whole write */ ret = raid56_parity_write(bio, bioc);
if (btrfs_op(bio) == BTRFS_MAP_WRITE) { else
ret = raid56_parity_write(bio, bioc, map_length); ret = raid56_parity_recover(bio, bioc, mirror_num, 1);
} else {
ret = raid56_parity_recover(bio, bioc, map_length,
mirror_num, 1);
}
goto out_dec; goto out_dec;
} }