MFprojects/camlock r256445:

Add unmapped I/O support to GEOM RAID.
This commit is contained in:
Alexander Motin 2013-10-16 09:33:23 +00:00
parent 21d0712c33
commit b43560ab19
7 changed files with 90 additions and 61 deletions

View File

@ -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;

View File

@ -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;
};

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 @@ g_raid_tr_iostart_raid1e_write(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);
@ -1030,6 +1042,9 @@ g_raid_tr_iodone_raid1e(struct g_raid_tr_object *tr,
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",

View File

@ -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);