Commit 6486d21c authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: raid56: extract rwm write bios assembly into a helper

The helper will be later used to refactor the rmw write path.
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 509c27aa
...@@ -1237,65 +1237,23 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr) ...@@ -1237,65 +1237,23 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
kunmap_local(pointers[stripe]); kunmap_local(pointers[stripe]);
} }
/* static int rmw_assemble_write_bios(struct btrfs_raid_bio *rbio,
* this is called from one of two situations. We either struct bio_list *bio_list)
* have a full stripe from the higher layers, or we've read all
* the missing bits off disk.
*
* This will calculate the parity and then send down any
* changed blocks.
*/
static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
{ {
struct btrfs_io_context *bioc = rbio->bioc; struct bio *bio;
/* The total sector number inside the full stripe. */ /* The total sector number inside the full stripe. */
int total_sector_nr; int total_sector_nr;
int stripe;
/* Sector number inside a stripe. */
int sectornr; int sectornr;
struct bio_list bio_list; int stripe;
struct bio *bio;
int ret; int ret;
bio_list_init(&bio_list); ASSERT(bio_list_size(bio_list) == 0);
/* We should have at least one data sector. */ /* We should have at least one data sector. */
ASSERT(bitmap_weight(&rbio->dbitmap, rbio->stripe_nsectors)); ASSERT(bitmap_weight(&rbio->dbitmap, rbio->stripe_nsectors));
/* at this point we either have a full stripe,
* or we've read the full stripe from the drive.
* recalculate the parity and write the new results.
*
* We're not allowed to add any new bios to the
* bio list here, anyone else that wants to
* change this stripe needs to do their own rmw.
*/
spin_lock_irq(&rbio->bio_list_lock);
set_bit(RBIO_RMW_LOCKED_BIT, &rbio->flags);
spin_unlock_irq(&rbio->bio_list_lock);
atomic_set(&rbio->error, 0);
/* /*
* now that we've set rmw_locked, run through the * Start assembly. Make bios for everything from the higher layers (the
* bio list one last time and map the page pointers
*
* We don't cache full rbios because we're assuming
* the higher layers are unlikely to use this area of
* the disk again soon. If they do use it again,
* hopefully they will send another full bio.
*/
index_rbio_pages(rbio);
if (!rbio_is_full(rbio))
cache_rbio_pages(rbio);
else
clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++)
generate_pq_vertical(rbio, sectornr);
/*
* Start writing. Make bios for everything from the higher layers (the
* bio_list in our rbio) and our P/Q. Ignore everything else. * bio_list in our rbio) and our P/Q. Ignore everything else.
*/ */
for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors; for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
...@@ -1317,15 +1275,16 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio) ...@@ -1317,15 +1275,16 @@ static noinline void finish_rmw(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, REQ_OP_WRITE); sectornr, REQ_OP_WRITE);
if (ret) if (ret)
goto cleanup; goto error;
} }
if (likely(!bioc->num_tgtdevs)) if (likely(!rbio->bioc->num_tgtdevs))
goto write_data; return 0;
/* Make a copy for the replace target device. */
for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors; for (total_sector_nr = 0; total_sector_nr < rbio->nr_sectors;
total_sector_nr++) { total_sector_nr++) {
struct sector_ptr *sector; struct sector_ptr *sector;
...@@ -1333,7 +1292,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio) ...@@ -1333,7 +1292,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
stripe = total_sector_nr / rbio->stripe_nsectors; stripe = total_sector_nr / rbio->stripe_nsectors;
sectornr = total_sector_nr % rbio->stripe_nsectors; sectornr = total_sector_nr % rbio->stripe_nsectors;
if (!bioc->tgtdev_map[stripe]) { if (!rbio->bioc->tgtdev_map[stripe]) {
/* /*
* We can skip the whole stripe completely, note * We can skip the whole stripe completely, note
* total_sector_nr will be increased by one anyway. * total_sector_nr will be increased by one anyway.
...@@ -1355,14 +1314,78 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio) ...@@ -1355,14 +1314,78 @@ static noinline void finish_rmw(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, ret = rbio_add_io_sector(rbio, bio_list, sector,
rbio->bioc->tgtdev_map[stripe], rbio->bioc->tgtdev_map[stripe],
sectornr, REQ_OP_WRITE); sectornr, REQ_OP_WRITE);
if (ret) if (ret)
goto cleanup; goto error;
} }
write_data: return 0;
error:
while ((bio = bio_list_pop(bio_list)))
bio_put(bio);
return -EIO;
}
/*
* this is called from one of two situations. We either
* have a full stripe from the higher layers, or we've read all
* the missing bits off disk.
*
* This will calculate the parity and then send down any
* changed blocks.
*/
static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
{
/* The total sector number inside the full stripe. */
/* Sector number inside a stripe. */
int sectornr;
struct bio_list bio_list;
struct bio *bio;
int ret;
bio_list_init(&bio_list);
/* We should have at least one data sector. */
ASSERT(bitmap_weight(&rbio->dbitmap, rbio->stripe_nsectors));
/* at this point we either have a full stripe,
* or we've read the full stripe from the drive.
* recalculate the parity and write the new results.
*
* We're not allowed to add any new bios to the
* bio list here, anyone else that wants to
* change this stripe needs to do their own rmw.
*/
spin_lock_irq(&rbio->bio_list_lock);
set_bit(RBIO_RMW_LOCKED_BIT, &rbio->flags);
spin_unlock_irq(&rbio->bio_list_lock);
atomic_set(&rbio->error, 0);
/*
* now that we've set rmw_locked, run through the
* bio list one last time and map the page pointers
*
* We don't cache full rbios because we're assuming
* the higher layers are unlikely to use this area of
* the disk again soon. If they do use it again,
* hopefully they will send another full bio.
*/
index_rbio_pages(rbio);
if (!rbio_is_full(rbio))
cache_rbio_pages(rbio);
else
clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++)
generate_pq_vertical(rbio, sectornr);
ret = rmw_assemble_write_bios(rbio, &bio_list);
if (ret < 0)
goto cleanup;
atomic_set(&rbio->stripes_pending, bio_list_size(&bio_list)); atomic_set(&rbio->stripes_pending, bio_list_size(&bio_list));
BUG_ON(atomic_read(&rbio->stripes_pending) == 0); BUG_ON(atomic_read(&rbio->stripes_pending) == 0);
......
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