|
@@ -81,6 +81,24 @@ static void lower_barrier(struct r1conf *conf, sector_t sector_nr);
|
|
|
#define raid1_log(md, fmt, args...) \
|
|
|
do { if ((md)->queue) blk_add_trace_msg((md)->queue, "raid1 " fmt, ##args); } while (0)
|
|
|
|
|
|
+/*
|
|
|
+ * 'strct resync_pages' stores actual pages used for doing the resync
|
|
|
+ * IO, and it is per-bio, so make .bi_private points to it.
|
|
|
+ */
|
|
|
+static inline struct resync_pages *get_resync_pages(struct bio *bio)
|
|
|
+{
|
|
|
+ return bio->bi_private;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * for resync bio, r1bio pointer can be retrieved from the per-bio
|
|
|
+ * 'struct resync_pages'.
|
|
|
+ */
|
|
|
+static inline struct r1bio *get_resync_r1bio(struct bio *bio)
|
|
|
+{
|
|
|
+ return get_resync_pages(bio)->raid_bio;
|
|
|
+}
|
|
|
+
|
|
|
static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
|
|
|
{
|
|
|
struct pool_info *pi = data;
|
|
@@ -108,12 +126,18 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
|
|
|
struct r1bio *r1_bio;
|
|
|
struct bio *bio;
|
|
|
int need_pages;
|
|
|
- int i, j;
|
|
|
+ int j;
|
|
|
+ struct resync_pages *rps;
|
|
|
|
|
|
r1_bio = r1bio_pool_alloc(gfp_flags, pi);
|
|
|
if (!r1_bio)
|
|
|
return NULL;
|
|
|
|
|
|
+ rps = kmalloc(sizeof(struct resync_pages) * pi->raid_disks,
|
|
|
+ gfp_flags);
|
|
|
+ if (!rps)
|
|
|
+ goto out_free_r1bio;
|
|
|
+
|
|
|
/*
|
|
|
* Allocate bios : 1 for reading, n-1 for writing
|
|
|
*/
|
|
@@ -133,22 +157,22 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
|
|
|
need_pages = pi->raid_disks;
|
|
|
else
|
|
|
need_pages = 1;
|
|
|
- for (j = 0; j < need_pages; j++) {
|
|
|
+ for (j = 0; j < pi->raid_disks; j++) {
|
|
|
+ struct resync_pages *rp = &rps[j];
|
|
|
+
|
|
|
bio = r1_bio->bios[j];
|
|
|
- bio->bi_vcnt = RESYNC_PAGES;
|
|
|
-
|
|
|
- if (bio_alloc_pages(bio, gfp_flags))
|
|
|
- goto out_free_pages;
|
|
|
- }
|
|
|
- /* If not user-requests, copy the page pointers to all bios */
|
|
|
- if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) {
|
|
|
- for (i = 0; i< RESYNC_PAGES; i++)
|
|
|
- for (j = 1; j < pi->raid_disks; j++) {
|
|
|
- struct page *page =
|
|
|
- r1_bio->bios[0]->bi_io_vec[i].bv_page;
|
|
|
- get_page(page);
|
|
|
- r1_bio->bios[j]->bi_io_vec[i].bv_page = page;
|
|
|
- }
|
|
|
+
|
|
|
+ if (j < need_pages) {
|
|
|
+ if (resync_alloc_pages(rp, gfp_flags))
|
|
|
+ goto out_free_pages;
|
|
|
+ } else {
|
|
|
+ memcpy(rp, &rps[0], sizeof(*rp));
|
|
|
+ resync_get_all_pages(rp);
|
|
|
+ }
|
|
|
+
|
|
|
+ rp->idx = 0;
|
|
|
+ rp->raid_bio = r1_bio;
|
|
|
+ bio->bi_private = rp;
|
|
|
}
|
|
|
|
|
|
r1_bio->master_bio = NULL;
|
|
@@ -157,11 +181,14 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
|
|
|
|
|
|
out_free_pages:
|
|
|
while (--j >= 0)
|
|
|
- bio_free_pages(r1_bio->bios[j]);
|
|
|
+ resync_free_pages(&rps[j]);
|
|
|
|
|
|
out_free_bio:
|
|
|
while (++j < pi->raid_disks)
|
|
|
bio_put(r1_bio->bios[j]);
|
|
|
+ kfree(rps);
|
|
|
+
|
|
|
+out_free_r1bio:
|
|
|
r1bio_pool_free(r1_bio, data);
|
|
|
return NULL;
|
|
|
}
|
|
@@ -169,14 +196,18 @@ out_free_bio:
|
|
|
static void r1buf_pool_free(void *__r1_bio, void *data)
|
|
|
{
|
|
|
struct pool_info *pi = data;
|
|
|
- int i,j;
|
|
|
+ int i;
|
|
|
struct r1bio *r1bio = __r1_bio;
|
|
|
+ struct resync_pages *rp = NULL;
|
|
|
|
|
|
- for (i = 0; i < RESYNC_PAGES; i++)
|
|
|
- for (j = pi->raid_disks; j-- ;)
|
|
|
- safe_put_page(r1bio->bios[j]->bi_io_vec[i].bv_page);
|
|
|
- for (i=0 ; i < pi->raid_disks; i++)
|
|
|
+ for (i = pi->raid_disks; i--; ) {
|
|
|
+ rp = get_resync_pages(r1bio->bios[i]);
|
|
|
+ resync_free_pages(rp);
|
|
|
bio_put(r1bio->bios[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* resync pages array stored in the 1st bio's .bi_private */
|
|
|
+ kfree(rp);
|
|
|
|
|
|
r1bio_pool_free(r1bio, data);
|
|
|
}
|
|
@@ -1844,7 +1875,7 @@ abort:
|
|
|
|
|
|
static void end_sync_read(struct bio *bio)
|
|
|
{
|
|
|
- struct r1bio *r1_bio = bio->bi_private;
|
|
|
+ struct r1bio *r1_bio = get_resync_r1bio(bio);
|
|
|
|
|
|
update_head_pos(r1_bio->read_disk, r1_bio);
|
|
|
|
|
@@ -1863,7 +1894,7 @@ static void end_sync_read(struct bio *bio)
|
|
|
static void end_sync_write(struct bio *bio)
|
|
|
{
|
|
|
int uptodate = !bio->bi_error;
|
|
|
- struct r1bio *r1_bio = bio->bi_private;
|
|
|
+ struct r1bio *r1_bio = get_resync_r1bio(bio);
|
|
|
struct mddev *mddev = r1_bio->mddev;
|
|
|
struct r1conf *conf = mddev->private;
|
|
|
sector_t first_bad;
|
|
@@ -2080,6 +2111,7 @@ static void process_checks(struct r1bio *r1_bio)
|
|
|
int size;
|
|
|
int error;
|
|
|
struct bio *b = r1_bio->bios[i];
|
|
|
+ struct resync_pages *rp = get_resync_pages(b);
|
|
|
if (b->bi_end_io != end_sync_read)
|
|
|
continue;
|
|
|
/* fixup the bio for reuse, but preserve errno */
|
|
@@ -2092,7 +2124,8 @@ static void process_checks(struct r1bio *r1_bio)
|
|
|
conf->mirrors[i].rdev->data_offset;
|
|
|
b->bi_bdev = conf->mirrors[i].rdev->bdev;
|
|
|
b->bi_end_io = end_sync_read;
|
|
|
- b->bi_private = r1_bio;
|
|
|
+ rp->raid_bio = r1_bio;
|
|
|
+ b->bi_private = rp;
|
|
|
|
|
|
size = b->bi_iter.bi_size;
|
|
|
for (j = 0; j < vcnt ; j++) {
|
|
@@ -2746,7 +2779,6 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|
|
for (i = 0; i < conf->raid_disks * 2; i++) {
|
|
|
struct md_rdev *rdev;
|
|
|
bio = r1_bio->bios[i];
|
|
|
- bio_reset(bio);
|
|
|
|
|
|
rdev = rcu_dereference(conf->mirrors[i].rdev);
|
|
|
if (rdev == NULL ||
|
|
@@ -2802,7 +2834,6 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|
|
atomic_inc(&rdev->nr_pending);
|
|
|
bio->bi_iter.bi_sector = sector_nr + rdev->data_offset;
|
|
|
bio->bi_bdev = rdev->bdev;
|
|
|
- bio->bi_private = r1_bio;
|
|
|
if (test_bit(FailFast, &rdev->flags))
|
|
|
bio->bi_opf |= MD_FAILFAST;
|
|
|
}
|
|
@@ -2888,9 +2919,12 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|
|
}
|
|
|
|
|
|
for (i = 0 ; i < conf->raid_disks * 2; i++) {
|
|
|
+ struct resync_pages *rp;
|
|
|
+
|
|
|
bio = r1_bio->bios[i];
|
|
|
+ rp = get_resync_pages(bio);
|
|
|
if (bio->bi_end_io) {
|
|
|
- page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
|
|
|
+ page = resync_fetch_page(rp, rp->idx++);
|
|
|
|
|
|
/*
|
|
|
* won't fail because the vec table is big
|
|
@@ -2902,7 +2936,8 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|
|
nr_sectors += len>>9;
|
|
|
sector_nr += len>>9;
|
|
|
sync_blocks -= (len>>9);
|
|
|
- } while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
|
|
|
+ } while (get_resync_pages(r1_bio->bios[disk]->bi_private)->idx < RESYNC_PAGES);
|
|
|
+
|
|
|
r1_bio->sectors = nr_sectors;
|
|
|
|
|
|
if (mddev_is_clustered(mddev) &&
|