From b43560ab19174cd7e5efd94882e4a65da8028a1d Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 16 Oct 2013 09:33:23 +0000 Subject: [PATCH] MFprojects/camlock r256445: Add unmapped I/O support to GEOM RAID. --- sys/geom/raid/g_raid.c | 22 ++++++++++------ sys/geom/raid/g_raid.h | 1 + sys/geom/raid/tr_concat.c | 27 ++++++++++++-------- sys/geom/raid/tr_raid0.c | 27 ++++++++++++-------- sys/geom/raid/tr_raid1.c | 12 +++------ sys/geom/raid/tr_raid1e.c | 53 +++++++++++++++++++++++++-------------- sys/geom/raid/tr_raid5.c | 9 ++----- 7 files changed, 90 insertions(+), 61 deletions(-) diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c index 41a1f9668cb7..9933cf1f8d7b 100644 --- a/sys/geom/raid/g_raid.c +++ b/sys/geom/raid/g_raid.c @@ -993,20 +993,15 @@ g_raid_tr_flush_common(struct g_raid_tr_object *tr, struct bio *bp) cbp->bio_caller1 = sd; bioq_insert_tail(&queue, cbp); } - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error); @@ -1639,11 +1634,13 @@ static void g_raid_launch_provider(struct g_raid_volume *vol) { struct g_raid_disk *disk; + struct g_raid_subdisk *sd; struct g_raid_softc *sc; struct g_provider *pp; char name[G_RAID_MAX_VOLUMENAME]; char announce_buf[80], buf1[32]; off_t off; + int i; sc = vol->v_softc; sx_assert(&sc->sc_lock, SX_LOCKED); @@ -1673,6 +1670,17 @@ g_raid_launch_provider(struct g_raid_volume *vol) } pp = g_new_providerf(sc->sc_geom, "%s", name); + if (vol->v_tr->tro_class->trc_accept_unmapped) { + pp->flags |= G_PF_ACCEPT_UNMAPPED; + for (i = 0; i < vol->v_disks_count; i++) { + sd = &vol->v_subdisks[i]; + if (sd->sd_state == G_RAID_SUBDISK_S_NONE) + continue; + if ((sd->sd_disk->d_consumer->provider->flags & + G_PF_ACCEPT_UNMAPPED) == 0) + pp->flags &= ~G_PF_ACCEPT_UNMAPPED; + } + } pp->private = vol; pp->mediasize = vol->v_mediasize; pp->sectorsize = vol->v_sectorsize; diff --git a/sys/geom/raid/g_raid.h b/sys/geom/raid/g_raid.h index 993b1000b5fe..8a96fa9f4698 100644 --- a/sys/geom/raid/g_raid.h +++ b/sys/geom/raid/g_raid.h @@ -376,6 +376,7 @@ struct g_raid_tr_class { KOBJ_CLASS_FIELDS; int trc_enable; int trc_priority; + int trc_accept_unmapped; LIST_ENTRY(g_raid_tr_class) trc_list; }; diff --git a/sys/geom/raid/tr_concat.c b/sys/geom/raid/tr_concat.c index 60db472fc5aa..44951d444785 100644 --- a/sys/geom/raid/tr_concat.c +++ b/sys/geom/raid/tr_concat.c @@ -74,7 +74,8 @@ static struct g_raid_tr_class g_raid_tr_concat_class = { g_raid_tr_concat_methods, sizeof(struct g_raid_tr_concat_object), .trc_enable = 1, - .trc_priority = 50 + .trc_priority = 50, + .trc_accept_unmapped = 1 }; static int @@ -227,7 +228,10 @@ g_raid_tr_iostart_concat(struct g_raid_tr_object *tr, struct bio *bp) offset = bp->bio_offset; remain = bp->bio_length; - addr = bp->bio_data; + if ((bp->bio_flags & BIO_UNMAPPED) != 0) + addr = NULL; + else + addr = bp->bio_data; no = 0; while (no < vol->v_disks_count && offset >= vol->v_subdisks[no].sd_size) { @@ -244,8 +248,16 @@ g_raid_tr_iostart_concat(struct g_raid_tr_object *tr, struct bio *bp) if (cbp == NULL) goto failure; cbp->bio_offset = offset; - cbp->bio_data = addr; cbp->bio_length = length; + if ((bp->bio_flags & BIO_UNMAPPED) != 0 && + bp->bio_cmd != BIO_DELETE) { + cbp->bio_ma_offset += (uintptr_t)addr; + cbp->bio_ma += cbp->bio_ma_offset / PAGE_SIZE; + cbp->bio_ma_offset %= PAGE_SIZE; + cbp->bio_ma_n = round_page(cbp->bio_ma_offset + + cbp->bio_length) / PAGE_SIZE; + } else + cbp->bio_data = addr; cbp->bio_caller1 = sd; bioq_insert_tail(&queue, cbp); remain -= length; @@ -257,20 +269,15 @@ g_raid_tr_iostart_concat(struct g_raid_tr_object *tr, struct bio *bp) ("Request ends after volume end (%ju, %ju)", bp->bio_offset, bp->bio_length)); } while (remain > 0); - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error); diff --git a/sys/geom/raid/tr_raid0.c b/sys/geom/raid/tr_raid0.c index 7873be82e618..40d35fdbbad8 100644 --- a/sys/geom/raid/tr_raid0.c +++ b/sys/geom/raid/tr_raid0.c @@ -74,7 +74,8 @@ static struct g_raid_tr_class g_raid_tr_raid0_class = { g_raid_tr_raid0_methods, sizeof(struct g_raid_tr_raid0_object), .trc_enable = 1, - .trc_priority = 100 + .trc_priority = 100, + .trc_accept_unmapped = 1 }; static int @@ -204,7 +205,10 @@ g_raid_tr_iostart_raid0(struct g_raid_tr_object *tr, struct bio *bp) g_raid_tr_flush_common(tr, bp); return; } - addr = bp->bio_data; + if ((bp->bio_flags & BIO_UNMAPPED) != 0) + addr = NULL; + else + addr = bp->bio_data; strip_size = vol->v_strip_size; /* Stripe number. */ @@ -225,8 +229,16 @@ g_raid_tr_iostart_raid0(struct g_raid_tr_object *tr, struct bio *bp) if (cbp == NULL) goto failure; cbp->bio_offset = offset + start; - cbp->bio_data = addr; cbp->bio_length = length; + if ((bp->bio_flags & BIO_UNMAPPED) != 0 && + bp->bio_cmd != BIO_DELETE) { + cbp->bio_ma_offset += (uintptr_t)addr; + cbp->bio_ma += cbp->bio_ma_offset / PAGE_SIZE; + cbp->bio_ma_offset %= PAGE_SIZE; + cbp->bio_ma_n = round_page(cbp->bio_ma_offset + + cbp->bio_length) / PAGE_SIZE; + } else + cbp->bio_data = addr; cbp->bio_caller1 = &vol->v_subdisks[no]; bioq_insert_tail(&queue, cbp); if (++no >= vol->v_disks_count) { @@ -238,20 +250,15 @@ g_raid_tr_iostart_raid0(struct g_raid_tr_object *tr, struct bio *bp) addr += length; start = 0; } while (remain > 0); - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error); diff --git a/sys/geom/raid/tr_raid1.c b/sys/geom/raid/tr_raid1.c index 4465e328789c..833655bb854f 100644 --- a/sys/geom/raid/tr_raid1.c +++ b/sys/geom/raid/tr_raid1.c @@ -130,7 +130,8 @@ static struct g_raid_tr_class g_raid_tr_raid1_class = { g_raid_tr_raid1_methods, sizeof(struct g_raid_tr_raid1_object), .trc_enable = 1, - .trc_priority = 100 + .trc_priority = 100, + .trc_accept_unmapped = 1 }; static void g_raid_tr_raid1_rebuild_abort(struct g_raid_tr_object *tr); @@ -594,20 +595,15 @@ g_raid_tr_iostart_raid1_write(struct g_raid_tr_object *tr, struct bio *bp) cbp->bio_caller1 = sd; bioq_insert_tail(&queue, cbp); } - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error); diff --git a/sys/geom/raid/tr_raid1e.c b/sys/geom/raid/tr_raid1e.c index 679b7669b6ed..d283606b59c5 100644 --- a/sys/geom/raid/tr_raid1e.c +++ b/sys/geom/raid/tr_raid1e.c @@ -134,7 +134,8 @@ static struct g_raid_tr_class g_raid_tr_raid1e_class = { g_raid_tr_raid1e_methods, sizeof(struct g_raid_tr_raid1e_object), .trc_enable = 1, - .trc_priority = 200 + .trc_priority = 200, + .trc_accept_unmapped = 1 }; static void g_raid_tr_raid1e_rebuild_abort(struct g_raid_tr_object *tr); @@ -701,7 +702,10 @@ g_raid_tr_iostart_raid1e_read(struct g_raid_tr_object *tr, struct bio *bp) int best; vol = tr->tro_volume; - addr = bp->bio_data; + if ((bp->bio_flags & BIO_UNMAPPED) != 0) + addr = NULL; + else + addr = bp->bio_data; strip_size = vol->v_strip_size; V2P(vol, bp->bio_offset, &no, &offset, &start); remain = bp->bio_length; @@ -721,8 +725,15 @@ g_raid_tr_iostart_raid1e_read(struct g_raid_tr_object *tr, struct bio *bp) if (cbp == NULL) goto failure; cbp->bio_offset = offset + start; - cbp->bio_data = addr; cbp->bio_length = length; + if ((bp->bio_flags & BIO_UNMAPPED) != 0) { + cbp->bio_ma_offset += (uintptr_t)addr; + cbp->bio_ma += cbp->bio_ma_offset / PAGE_SIZE; + cbp->bio_ma_offset %= PAGE_SIZE; + cbp->bio_ma_n = round_page(cbp->bio_ma_offset + + cbp->bio_length) / PAGE_SIZE; + } else + cbp->bio_data = addr; cbp->bio_caller1 = &vol->v_subdisks[no]; bioq_insert_tail(&queue, cbp); no += N - best; @@ -734,20 +745,15 @@ g_raid_tr_iostart_raid1e_read(struct g_raid_tr_object *tr, struct bio *bp) addr += length; start = 0; } - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error); @@ -766,7 +772,10 @@ g_raid_tr_iostart_raid1e_write(struct g_raid_tr_object *tr, struct bio *bp) int i; vol = tr->tro_volume; - addr = bp->bio_data; + if ((bp->bio_flags & BIO_UNMAPPED) != 0) + addr = NULL; + else + addr = bp->bio_data; strip_size = vol->v_strip_size; V2P(vol, bp->bio_offset, &no, &offset, &start); remain = bp->bio_length; @@ -791,8 +800,16 @@ g_raid_tr_iostart_raid1e_write(struct g_raid_tr_object *tr, struct bio *bp) if (cbp == NULL) goto failure; cbp->bio_offset = offset + start; - cbp->bio_data = addr; cbp->bio_length = length; + if ((bp->bio_flags & BIO_UNMAPPED) != 0 && + bp->bio_cmd != BIO_DELETE) { + cbp->bio_ma_offset += (uintptr_t)addr; + cbp->bio_ma += cbp->bio_ma_offset / PAGE_SIZE; + cbp->bio_ma_offset %= PAGE_SIZE; + cbp->bio_ma_n = round_page(cbp->bio_ma_offset + + cbp->bio_length) / PAGE_SIZE; + } else + cbp->bio_data = addr; cbp->bio_caller1 = sd; bioq_insert_tail(&queue, cbp); nextdisk: @@ -806,20 +823,15 @@ nextdisk: addr += length; start = 0; } - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error); @@ -1030,6 +1042,9 @@ rebuild_round_done: cbp->bio_offset = offset + start; cbp->bio_length = bp->bio_length; cbp->bio_data = bp->bio_data; + cbp->bio_ma = bp->bio_ma; + cbp->bio_ma_offset = bp->bio_ma_offset; + cbp->bio_ma_n = bp->bio_ma_n; g_destroy_bio(bp); nsd = &vol->v_subdisks[disk]; G_RAID_LOGREQ(2, cbp, "Retrying read from %d", diff --git a/sys/geom/raid/tr_raid5.c b/sys/geom/raid/tr_raid5.c index 6e54d168ceaf..c90845e51376 100644 --- a/sys/geom/raid/tr_raid5.c +++ b/sys/geom/raid/tr_raid5.c @@ -324,20 +324,15 @@ g_raid_tr_iostart_raid5_read(struct g_raid_tr_object *tr, struct bio *bp) addr += length; start = 0; } while (remain > 0); - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) { sd = cbp->bio_caller1; cbp->bio_caller1 = NULL; g_raid_subdisk_iostart(sd, cbp); } return; failure: - for (cbp = bioq_first(&queue); cbp != NULL; - cbp = bioq_first(&queue)) { - bioq_remove(&queue, cbp); + while ((cbp = bioq_takefirst(&queue)) != NULL) g_destroy_bio(cbp); - } if (bp->bio_error == 0) bp->bio_error = ENOMEM; g_raid_iodone(bp, bp->bio_error);