btrfs: raid56: make rbio_add_io_page() subpage compatible
Make rbio_add_io_page() subpage compatible, which involves: - Rename rbio_add_io_page() to rbio_add_io_sector() Although we still rely on PAGE_SIZE == sectorsize, so add a new ASSERT() inside rbio_add_io_sector() to make sure all pgoff is 0. - Introduce rbio_stripe_sector() helper The equivalent of rbio_stripe_page(). This new helper has extra ASSERT()s to validate the stripe and sector number. - Introduce sector_in_rbio() helper The equivalent of page_in_rbio(). - Rename @pagenr variables to @sectornr - Use rbio::stripe_nsectors when iterating the bitmap Please note that, this only changes the interface, the bios are still using full page for IO. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
@@ -666,6 +666,25 @@ static int rbio_can_merge(struct btrfs_raid_bio *last,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int rbio_stripe_sector_index(const struct btrfs_raid_bio *rbio,
|
||||||
|
unsigned int stripe_nr,
|
||||||
|
unsigned int sector_nr)
|
||||||
|
{
|
||||||
|
ASSERT(stripe_nr < rbio->real_stripes);
|
||||||
|
ASSERT(sector_nr < rbio->stripe_nsectors);
|
||||||
|
|
||||||
|
return stripe_nr * rbio->stripe_nsectors + sector_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a sector from rbio->stripe_sectors, not from the bio list */
|
||||||
|
static struct sector_ptr *rbio_stripe_sector(const struct btrfs_raid_bio *rbio,
|
||||||
|
unsigned int stripe_nr,
|
||||||
|
unsigned int sector_nr)
|
||||||
|
{
|
||||||
|
return &rbio->stripe_sectors[rbio_stripe_sector_index(rbio, stripe_nr,
|
||||||
|
sector_nr)];
|
||||||
|
}
|
||||||
|
|
||||||
static int rbio_stripe_page_index(struct btrfs_raid_bio *rbio, int stripe,
|
static int rbio_stripe_page_index(struct btrfs_raid_bio *rbio, int stripe,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
@@ -977,6 +996,45 @@ static void raid_write_end_io(struct bio *bio)
|
|||||||
rbio_orig_end_io(rbio, err);
|
rbio_orig_end_io(rbio, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a sector pointer specified by its @stripe_nr and @sector_nr
|
||||||
|
*
|
||||||
|
* @rbio: The raid bio
|
||||||
|
* @stripe_nr: Stripe number, valid range [0, real_stripe)
|
||||||
|
* @sector_nr: Sector number inside the stripe,
|
||||||
|
* valid range [0, stripe_nsectors)
|
||||||
|
* @bio_list_only: Whether to use sectors inside the bio list only.
|
||||||
|
*
|
||||||
|
* The read/modify/write code wants to reuse the original bio page as much
|
||||||
|
* as possible, and only use stripe_sectors as fallback.
|
||||||
|
*/
|
||||||
|
static struct sector_ptr *sector_in_rbio(struct btrfs_raid_bio *rbio,
|
||||||
|
int stripe_nr, int sector_nr,
|
||||||
|
bool bio_list_only)
|
||||||
|
{
|
||||||
|
struct sector_ptr *sector;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
ASSERT(stripe_nr >= 0 && stripe_nr < rbio->real_stripes);
|
||||||
|
ASSERT(sector_nr >= 0 && sector_nr < rbio->stripe_nsectors);
|
||||||
|
|
||||||
|
index = stripe_nr * rbio->stripe_nsectors + sector_nr;
|
||||||
|
ASSERT(index >= 0 && index < rbio->nr_sectors);
|
||||||
|
|
||||||
|
spin_lock_irq(&rbio->bio_list_lock);
|
||||||
|
sector = &rbio->bio_sectors[index];
|
||||||
|
if (sector->page || bio_list_only) {
|
||||||
|
/* Don't return sector without a valid page pointer */
|
||||||
|
if (!sector->page)
|
||||||
|
sector = NULL;
|
||||||
|
spin_unlock_irq(&rbio->bio_list_lock);
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
spin_unlock_irq(&rbio->bio_list_lock);
|
||||||
|
|
||||||
|
return &rbio->stripe_sectors[index];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the read/modify/write code wants to use the original bio for
|
* the read/modify/write code wants to use the original bio for
|
||||||
* any pages it included, and then use the rbio for everything
|
* any pages it included, and then use the rbio for everything
|
||||||
@@ -1119,26 +1177,40 @@ static int alloc_rbio_parity_pages(struct btrfs_raid_bio *rbio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add a single page from a specific stripe into our list of bios for IO
|
* Add a single sector @sector into our list of bios for IO.
|
||||||
* this will try to merge into existing bios if possible, and returns
|
*
|
||||||
* zero if all went well.
|
* Return 0 if everything went well.
|
||||||
|
* Return <0 for error.
|
||||||
*/
|
*/
|
||||||
static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
|
static int rbio_add_io_sector(struct btrfs_raid_bio *rbio,
|
||||||
struct bio_list *bio_list,
|
struct bio_list *bio_list,
|
||||||
struct page *page,
|
struct sector_ptr *sector,
|
||||||
int stripe_nr,
|
unsigned int stripe_nr,
|
||||||
unsigned long page_index,
|
unsigned int sector_nr,
|
||||||
unsigned long bio_max_len,
|
unsigned long bio_max_len,
|
||||||
unsigned int opf)
|
unsigned int opf)
|
||||||
{
|
{
|
||||||
|
const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
|
||||||
struct bio *last = bio_list->tail;
|
struct bio *last = bio_list->tail;
|
||||||
int ret;
|
int ret;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct btrfs_io_stripe *stripe;
|
struct btrfs_io_stripe *stripe;
|
||||||
u64 disk_start;
|
u64 disk_start;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: here stripe_nr has taken device replace into consideration,
|
||||||
|
* thus it can be larger than rbio->real_stripe.
|
||||||
|
* So here we check against bioc->num_stripes, not rbio->real_stripes.
|
||||||
|
*/
|
||||||
|
ASSERT(stripe_nr >= 0 && stripe_nr < rbio->bioc->num_stripes);
|
||||||
|
ASSERT(sector_nr >= 0 && sector_nr < rbio->stripe_nsectors);
|
||||||
|
ASSERT(sector->page);
|
||||||
|
|
||||||
|
/* We don't yet support subpage, thus pgoff should always be 0 */
|
||||||
|
ASSERT(sector->pgoff == 0);
|
||||||
|
|
||||||
stripe = &rbio->bioc->stripes[stripe_nr];
|
stripe = &rbio->bioc->stripes[stripe_nr];
|
||||||
disk_start = stripe->physical + (page_index << PAGE_SHIFT);
|
disk_start = stripe->physical + sector_nr * sectorsize;
|
||||||
|
|
||||||
/* if the device is missing, just fail this stripe */
|
/* if the device is missing, just fail this stripe */
|
||||||
if (!stripe->dev->bdev)
|
if (!stripe->dev->bdev)
|
||||||
@@ -1155,8 +1227,9 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
|
|||||||
*/
|
*/
|
||||||
if (last_end == disk_start && !last->bi_status &&
|
if (last_end == disk_start && !last->bi_status &&
|
||||||
last->bi_bdev == stripe->dev->bdev) {
|
last->bi_bdev == stripe->dev->bdev) {
|
||||||
ret = bio_add_page(last, page, PAGE_SIZE, 0);
|
ret = bio_add_page(last, sector->page, sectorsize,
|
||||||
if (ret == PAGE_SIZE)
|
sector->pgoff);
|
||||||
|
if (ret == sectorsize)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1167,7 +1240,7 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
|
|||||||
bio->bi_iter.bi_sector = disk_start >> 9;
|
bio->bi_iter.bi_sector = disk_start >> 9;
|
||||||
bio->bi_private = rbio;
|
bio->bi_private = rbio;
|
||||||
|
|
||||||
bio_add_page(bio, page, PAGE_SIZE, 0);
|
bio_add_page(bio, sector->page, sectorsize, sector->pgoff);
|
||||||
bio_list_add(bio_list, bio);
|
bio_list_add(bio_list, bio);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1266,7 +1339,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
|
|||||||
void **pointers = rbio->finish_pointers;
|
void **pointers = rbio->finish_pointers;
|
||||||
int nr_data = rbio->nr_data;
|
int nr_data = rbio->nr_data;
|
||||||
int stripe;
|
int stripe;
|
||||||
int pagenr;
|
int sectornr;
|
||||||
bool has_qstripe;
|
bool has_qstripe;
|
||||||
struct bio_list bio_list;
|
struct bio_list bio_list;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
@@ -1310,16 +1383,16 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
|
|||||||
else
|
else
|
||||||
clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
|
clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
|
||||||
|
|
||||||
for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
|
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
|
||||||
struct page *p;
|
struct page *p;
|
||||||
/* first collect one page from each data stripe */
|
/* first collect one page from each data stripe */
|
||||||
for (stripe = 0; stripe < nr_data; stripe++) {
|
for (stripe = 0; stripe < nr_data; stripe++) {
|
||||||
p = page_in_rbio(rbio, stripe, pagenr, 0);
|
p = page_in_rbio(rbio, stripe, sectornr, 0);
|
||||||
pointers[stripe] = kmap_local_page(p);
|
pointers[stripe] = kmap_local_page(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* then add the parity stripe */
|
/* then add the parity stripe */
|
||||||
p = rbio_pstripe_page(rbio, pagenr);
|
p = rbio_pstripe_page(rbio, sectornr);
|
||||||
SetPageUptodate(p);
|
SetPageUptodate(p);
|
||||||
pointers[stripe++] = kmap_local_page(p);
|
pointers[stripe++] = kmap_local_page(p);
|
||||||
|
|
||||||
@@ -1329,7 +1402,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
|
|||||||
* raid6, add the qstripe and call the
|
* raid6, add the qstripe and call the
|
||||||
* library function to fill in our p/q
|
* library function to fill in our p/q
|
||||||
*/
|
*/
|
||||||
p = rbio_qstripe_page(rbio, pagenr);
|
p = rbio_qstripe_page(rbio, sectornr);
|
||||||
SetPageUptodate(p);
|
SetPageUptodate(p);
|
||||||
pointers[stripe++] = kmap_local_page(p);
|
pointers[stripe++] = kmap_local_page(p);
|
||||||
|
|
||||||
@@ -1350,18 +1423,19 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
|
|||||||
* everything else.
|
* everything else.
|
||||||
*/
|
*/
|
||||||
for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
|
for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
|
||||||
for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
|
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
|
||||||
struct page *page;
|
struct sector_ptr *sector;
|
||||||
|
|
||||||
if (stripe < rbio->nr_data) {
|
if (stripe < rbio->nr_data) {
|
||||||
page = page_in_rbio(rbio, stripe, pagenr, 1);
|
sector = sector_in_rbio(rbio, stripe, sectornr, 1);
|
||||||
if (!page)
|
if (!sector)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
page = rbio_stripe_page(rbio, stripe, pagenr);
|
sector = rbio_stripe_sector(rbio, stripe, sectornr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rbio_add_io_page(rbio, &bio_list,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
|
||||||
page, stripe, pagenr, rbio->stripe_len,
|
sectornr, rbio->stripe_len,
|
||||||
REQ_OP_WRITE);
|
REQ_OP_WRITE);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -1375,19 +1449,20 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
|
|||||||
if (!bioc->tgtdev_map[stripe])
|
if (!bioc->tgtdev_map[stripe])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
|
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
|
||||||
struct page *page;
|
struct sector_ptr *sector;
|
||||||
|
|
||||||
if (stripe < rbio->nr_data) {
|
if (stripe < rbio->nr_data) {
|
||||||
page = page_in_rbio(rbio, stripe, pagenr, 1);
|
sector = sector_in_rbio(rbio, stripe, sectornr, 1);
|
||||||
if (!page)
|
if (!sector)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
page = rbio_stripe_page(rbio, stripe, pagenr);
|
sector = rbio_stripe_sector(rbio, stripe, sectornr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rbio_add_io_page(rbio, &bio_list, page,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector,
|
||||||
rbio->bioc->tgtdev_map[stripe],
|
rbio->bioc->tgtdev_map[stripe],
|
||||||
pagenr, rbio->stripe_len,
|
sectornr, rbio->stripe_len,
|
||||||
REQ_OP_WRITE);
|
REQ_OP_WRITE);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -1564,7 +1639,7 @@ static int raid56_rmw_stripe(struct btrfs_raid_bio *rbio)
|
|||||||
int bios_to_read = 0;
|
int bios_to_read = 0;
|
||||||
struct bio_list bio_list;
|
struct bio_list bio_list;
|
||||||
int ret;
|
int ret;
|
||||||
int pagenr;
|
int sectornr;
|
||||||
int stripe;
|
int stripe;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
|
|
||||||
@@ -1582,28 +1657,29 @@ static int raid56_rmw_stripe(struct btrfs_raid_bio *rbio)
|
|||||||
* stripe
|
* stripe
|
||||||
*/
|
*/
|
||||||
for (stripe = 0; stripe < rbio->nr_data; stripe++) {
|
for (stripe = 0; stripe < rbio->nr_data; stripe++) {
|
||||||
for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
|
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
|
||||||
struct page *page;
|
struct sector_ptr *sector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we want to find all the pages missing from
|
* We want to find all the sectors missing from the
|
||||||
* the rbio and read them from the disk. If
|
* rbio and read them from the disk. If * sector_in_rbio()
|
||||||
* page_in_rbio finds a page in the bio list
|
* finds a page in the bio list we don't need to read
|
||||||
* we don't need to read it off the stripe.
|
* it off the stripe.
|
||||||
*/
|
*/
|
||||||
page = page_in_rbio(rbio, stripe, pagenr, 1);
|
sector = sector_in_rbio(rbio, stripe, sectornr, 1);
|
||||||
if (page)
|
if (sector)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
page = rbio_stripe_page(rbio, stripe, pagenr);
|
sector = rbio_stripe_sector(rbio, stripe, sectornr);
|
||||||
/*
|
/*
|
||||||
* the bio cache may have handed us an uptodate
|
* The bio cache may have handed us an uptodate page.
|
||||||
* page. If so, be happy and use it
|
* If so, be happy and use it.
|
||||||
*/
|
*/
|
||||||
if (PageUptodate(page))
|
if (sector->uptodate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = rbio_add_io_page(rbio, &bio_list, page,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector,
|
||||||
stripe, pagenr, rbio->stripe_len,
|
stripe, sectornr, rbio->stripe_len,
|
||||||
REQ_OP_READ);
|
REQ_OP_READ);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -2107,7 +2183,7 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
|
|||||||
int bios_to_read = 0;
|
int bios_to_read = 0;
|
||||||
struct bio_list bio_list;
|
struct bio_list bio_list;
|
||||||
int ret;
|
int ret;
|
||||||
int pagenr;
|
int sectornr;
|
||||||
int stripe;
|
int stripe;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
|
|
||||||
@@ -2130,20 +2206,19 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
|
for (sectornr = 0; sectornr < rbio->stripe_nsectors; sectornr++) {
|
||||||
struct page *p;
|
struct sector_ptr *sector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the rmw code may have already read this
|
* the rmw code may have already read this
|
||||||
* page in
|
* page in
|
||||||
*/
|
*/
|
||||||
p = rbio_stripe_page(rbio, stripe, pagenr);
|
sector = rbio_stripe_sector(rbio, stripe, sectornr);
|
||||||
if (PageUptodate(p))
|
if (sector->uptodate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = rbio_add_io_page(rbio, &bio_list,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector,
|
||||||
rbio_stripe_page(rbio, stripe, pagenr),
|
stripe, sectornr, rbio->stripe_len,
|
||||||
stripe, pagenr, rbio->stripe_len,
|
|
||||||
REQ_OP_READ);
|
REQ_OP_READ);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -2399,7 +2474,7 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
|
|||||||
unsigned long *pbitmap = rbio->finish_pbitmap;
|
unsigned long *pbitmap = rbio->finish_pbitmap;
|
||||||
int nr_data = rbio->nr_data;
|
int nr_data = rbio->nr_data;
|
||||||
int stripe;
|
int stripe;
|
||||||
int pagenr;
|
int sectornr;
|
||||||
bool has_qstripe;
|
bool has_qstripe;
|
||||||
struct page *p_page = NULL;
|
struct page *p_page = NULL;
|
||||||
struct page *q_page = NULL;
|
struct page *q_page = NULL;
|
||||||
@@ -2419,7 +2494,7 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
|
|||||||
|
|
||||||
if (bioc->num_tgtdevs && bioc->tgtdev_map[rbio->scrubp]) {
|
if (bioc->num_tgtdevs && bioc->tgtdev_map[rbio->scrubp]) {
|
||||||
is_replace = 1;
|
is_replace = 1;
|
||||||
bitmap_copy(pbitmap, rbio->dbitmap, rbio->stripe_npages);
|
bitmap_copy(pbitmap, rbio->dbitmap, rbio->stripe_nsectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2453,12 +2528,12 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
|
|||||||
/* Map the parity stripe just once */
|
/* Map the parity stripe just once */
|
||||||
pointers[nr_data] = kmap_local_page(p_page);
|
pointers[nr_data] = kmap_local_page(p_page);
|
||||||
|
|
||||||
for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
|
for_each_set_bit(sectornr, rbio->dbitmap, rbio->stripe_nsectors) {
|
||||||
struct page *p;
|
struct page *p;
|
||||||
void *parity;
|
void *parity;
|
||||||
/* first collect one page from each data stripe */
|
/* first collect one page from each data stripe */
|
||||||
for (stripe = 0; stripe < nr_data; stripe++) {
|
for (stripe = 0; stripe < nr_data; stripe++) {
|
||||||
p = page_in_rbio(rbio, stripe, pagenr, 0);
|
p = page_in_rbio(rbio, stripe, sectornr, 0);
|
||||||
pointers[stripe] = kmap_local_page(p);
|
pointers[stripe] = kmap_local_page(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2473,13 +2548,13 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check scrubbing parity and repair it */
|
/* Check scrubbing parity and repair it */
|
||||||
p = rbio_stripe_page(rbio, rbio->scrubp, pagenr);
|
p = rbio_stripe_page(rbio, rbio->scrubp, sectornr);
|
||||||
parity = kmap_local_page(p);
|
parity = kmap_local_page(p);
|
||||||
if (memcmp(parity, pointers[rbio->scrubp], PAGE_SIZE))
|
if (memcmp(parity, pointers[rbio->scrubp], PAGE_SIZE))
|
||||||
copy_page(parity, pointers[rbio->scrubp]);
|
copy_page(parity, pointers[rbio->scrubp]);
|
||||||
else
|
else
|
||||||
/* Parity is right, needn't writeback */
|
/* Parity is right, needn't writeback */
|
||||||
bitmap_clear(rbio->dbitmap, pagenr, 1);
|
bitmap_clear(rbio->dbitmap, sectornr, 1);
|
||||||
kunmap_local(parity);
|
kunmap_local(parity);
|
||||||
|
|
||||||
for (stripe = nr_data - 1; stripe >= 0; stripe--)
|
for (stripe = nr_data - 1; stripe >= 0; stripe--)
|
||||||
@@ -2499,12 +2574,12 @@ writeback:
|
|||||||
* higher layers (the bio_list in our rbio) and our p/q. Ignore
|
* higher layers (the bio_list in our rbio) and our p/q. Ignore
|
||||||
* everything else.
|
* everything else.
|
||||||
*/
|
*/
|
||||||
for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
|
for_each_set_bit(sectornr, rbio->dbitmap, rbio->stripe_nsectors) {
|
||||||
struct page *page;
|
struct sector_ptr *sector;
|
||||||
|
|
||||||
page = rbio_stripe_page(rbio, rbio->scrubp, pagenr);
|
sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
|
||||||
ret = rbio_add_io_page(rbio, &bio_list, page, rbio->scrubp,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector, rbio->scrubp,
|
||||||
pagenr, rbio->stripe_len, REQ_OP_WRITE);
|
sectornr, rbio->stripe_len, REQ_OP_WRITE);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@@ -2512,13 +2587,13 @@ writeback:
|
|||||||
if (!is_replace)
|
if (!is_replace)
|
||||||
goto submit_write;
|
goto submit_write;
|
||||||
|
|
||||||
for_each_set_bit(pagenr, pbitmap, rbio->stripe_npages) {
|
for_each_set_bit(sectornr, pbitmap, rbio->stripe_nsectors) {
|
||||||
struct page *page;
|
struct sector_ptr *sector;
|
||||||
|
|
||||||
page = rbio_stripe_page(rbio, rbio->scrubp, pagenr);
|
sector = rbio_stripe_sector(rbio, rbio->scrubp, sectornr);
|
||||||
ret = rbio_add_io_page(rbio, &bio_list, page,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector,
|
||||||
bioc->tgtdev_map[rbio->scrubp],
|
bioc->tgtdev_map[rbio->scrubp],
|
||||||
pagenr, rbio->stripe_len, REQ_OP_WRITE);
|
sectornr, rbio->stripe_len, REQ_OP_WRITE);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@@ -2650,7 +2725,7 @@ static void raid56_parity_scrub_stripe(struct btrfs_raid_bio *rbio)
|
|||||||
int bios_to_read = 0;
|
int bios_to_read = 0;
|
||||||
struct bio_list bio_list;
|
struct bio_list bio_list;
|
||||||
int ret;
|
int ret;
|
||||||
int pagenr;
|
int sectornr;
|
||||||
int stripe;
|
int stripe;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
|
|
||||||
@@ -2666,28 +2741,29 @@ static void raid56_parity_scrub_stripe(struct btrfs_raid_bio *rbio)
|
|||||||
* stripe
|
* stripe
|
||||||
*/
|
*/
|
||||||
for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
|
for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
|
||||||
for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
|
for_each_set_bit(sectornr , rbio->dbitmap, rbio->stripe_nsectors) {
|
||||||
struct page *page;
|
struct sector_ptr *sector;
|
||||||
/*
|
/*
|
||||||
* we want to find all the pages missing from
|
* We want to find all the sectors missing from the
|
||||||
* the rbio and read them from the disk. If
|
* rbio and read them from the disk. If * sector_in_rbio()
|
||||||
* page_in_rbio finds a page in the bio list
|
* finds a sector in the bio list we don't need to read
|
||||||
* we don't need to read it off the stripe.
|
* it off the stripe.
|
||||||
*/
|
*/
|
||||||
page = page_in_rbio(rbio, stripe, pagenr, 1);
|
sector = sector_in_rbio(rbio, stripe, sectornr, 1);
|
||||||
if (page)
|
if (sector)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
page = rbio_stripe_page(rbio, stripe, pagenr);
|
sector = rbio_stripe_sector(rbio, stripe, sectornr);
|
||||||
/*
|
/*
|
||||||
* the bio cache may have handed us an uptodate
|
* The bio cache may have handed us an uptodate sector.
|
||||||
* page. If so, be happy and use it
|
* If so, be happy and use it.
|
||||||
*/
|
*/
|
||||||
if (PageUptodate(page))
|
if (sector->uptodate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = rbio_add_io_page(rbio, &bio_list, page, stripe,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector,
|
||||||
pagenr, rbio->stripe_len, REQ_OP_READ);
|
stripe, sectornr, rbio->stripe_len,
|
||||||
|
REQ_OP_READ);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user