diff options
author | NeilBrown <neilb@suse.de> | 2011-07-27 21:32:10 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-07-27 21:32:10 -0400 |
commit | 2ca68f5ed7383733102ee53cd8fa4021ecc3b275 (patch) | |
tree | 29543cff802770d90380b889cf8b0cc01e7d1814 /drivers/md/raid1.c | |
parent | 4367af556133723d0f443e14ca8170d9447317cb (diff) |
md/raid1: store behind-write pages in bi_vecs.
When performing write-behind we allocate pages to store the data
during write.
Previously we just keep a list of pages. Now we keep a list of
bi_vec which includes offset and size.
This means that the r1bio has complete information to create a new
bio which will be needed for retrying after write errors.
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Namhyung Kim <namhyung@gmail.com>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 141de75a6c7c..b16d2ee5e9dd 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -327,9 +327,9 @@ static void r1_bio_write_done(r1bio_t *r1_bio) | |||
327 | /* free extra copy of the data pages */ | 327 | /* free extra copy of the data pages */ |
328 | int i = r1_bio->behind_page_count; | 328 | int i = r1_bio->behind_page_count; |
329 | while (i--) | 329 | while (i--) |
330 | safe_put_page(r1_bio->behind_pages[i]); | 330 | safe_put_page(r1_bio->behind_bvecs[i].bv_page); |
331 | kfree(r1_bio->behind_pages); | 331 | kfree(r1_bio->behind_bvecs); |
332 | r1_bio->behind_pages = NULL; | 332 | r1_bio->behind_bvecs = NULL; |
333 | } | 333 | } |
334 | /* clear the bitmap if all writes complete successfully */ | 334 | /* clear the bitmap if all writes complete successfully */ |
335 | bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector, | 335 | bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector, |
@@ -748,30 +748,31 @@ static void alloc_behind_pages(struct bio *bio, r1bio_t *r1_bio) | |||
748 | { | 748 | { |
749 | int i; | 749 | int i; |
750 | struct bio_vec *bvec; | 750 | struct bio_vec *bvec; |
751 | struct page **pages = kzalloc(bio->bi_vcnt * sizeof(struct page*), | 751 | struct bio_vec *bvecs = kzalloc(bio->bi_vcnt * sizeof(struct bio_vec), |
752 | GFP_NOIO); | 752 | GFP_NOIO); |
753 | if (unlikely(!pages)) | 753 | if (unlikely(!bvecs)) |
754 | return; | 754 | return; |
755 | 755 | ||
756 | bio_for_each_segment(bvec, bio, i) { | 756 | bio_for_each_segment(bvec, bio, i) { |
757 | pages[i] = alloc_page(GFP_NOIO); | 757 | bvecs[i] = *bvec; |
758 | if (unlikely(!pages[i])) | 758 | bvecs[i].bv_page = alloc_page(GFP_NOIO); |
759 | if (unlikely(!bvecs[i].bv_page)) | ||
759 | goto do_sync_io; | 760 | goto do_sync_io; |
760 | memcpy(kmap(pages[i]) + bvec->bv_offset, | 761 | memcpy(kmap(bvecs[i].bv_page) + bvec->bv_offset, |
761 | kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len); | 762 | kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len); |
762 | kunmap(pages[i]); | 763 | kunmap(bvecs[i].bv_page); |
763 | kunmap(bvec->bv_page); | 764 | kunmap(bvec->bv_page); |
764 | } | 765 | } |
765 | r1_bio->behind_pages = pages; | 766 | r1_bio->behind_bvecs = bvecs; |
766 | r1_bio->behind_page_count = bio->bi_vcnt; | 767 | r1_bio->behind_page_count = bio->bi_vcnt; |
767 | set_bit(R1BIO_BehindIO, &r1_bio->state); | 768 | set_bit(R1BIO_BehindIO, &r1_bio->state); |
768 | return; | 769 | return; |
769 | 770 | ||
770 | do_sync_io: | 771 | do_sync_io: |
771 | for (i = 0; i < bio->bi_vcnt; i++) | 772 | for (i = 0; i < bio->bi_vcnt; i++) |
772 | if (pages[i]) | 773 | if (bvecs[i].bv_page) |
773 | put_page(pages[i]); | 774 | put_page(bvecs[i].bv_page); |
774 | kfree(pages); | 775 | kfree(bvecs); |
775 | PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size); | 776 | PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size); |
776 | } | 777 | } |
777 | 778 | ||
@@ -1058,7 +1059,7 @@ read_again: | |||
1058 | &r1_bio->state)); | 1059 | &r1_bio->state)); |
1059 | first_clone = 0; | 1060 | first_clone = 0; |
1060 | } | 1061 | } |
1061 | if (r1_bio->behind_pages) { | 1062 | if (r1_bio->behind_bvecs) { |
1062 | struct bio_vec *bvec; | 1063 | struct bio_vec *bvec; |
1063 | int j; | 1064 | int j; |
1064 | 1065 | ||
@@ -1070,7 +1071,7 @@ read_again: | |||
1070 | * them all | 1071 | * them all |
1071 | */ | 1072 | */ |
1072 | __bio_for_each_segment(bvec, mbio, j, 0) | 1073 | __bio_for_each_segment(bvec, mbio, j, 0) |
1073 | bvec->bv_page = r1_bio->behind_pages[j]; | 1074 | bvec->bv_page = r1_bio->behind_bvecs[j].bv_page; |
1074 | if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags)) | 1075 | if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags)) |
1075 | atomic_inc(&r1_bio->behind_remaining); | 1076 | atomic_inc(&r1_bio->behind_remaining); |
1076 | } | 1077 | } |