diff options
author | mav <mav@FreeBSD.org> | 2015-03-12 10:20:53 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-03-12 10:20:53 +0000 |
commit | 19bf0d882b83adc63cf9aeada8ca86c9a2bf8adb (patch) | |
tree | b349253a49159be48870736e4230c6177a8cf88b /sys/geom | |
parent | cc29b99b5c7678b30f105f23bd5e92ea81115b9e (diff) | |
download | FreeBSD-src-19bf0d882b83adc63cf9aeada8ca86c9a2bf8adb.zip FreeBSD-src-19bf0d882b83adc63cf9aeada8ca86c9a2bf8adb.tar.gz |
Fix couple BIO_DELETE bugs in geom_mirror.
Do not report GEOM::candelete if none of providers support BIO_DELETE.
If consumer still requests BIO_DELETE, report error instead of hanging.
MFC after: 2 weeks
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/mirror/g_mirror.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 2fae439..89fb9c0 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -1021,6 +1021,23 @@ g_mirror_sync_done(struct bio *bp) } static void +g_mirror_candelete(struct bio *bp) +{ + struct g_mirror_softc *sc; + struct g_mirror_disk *disk; + int *val; + + sc = bp->bio_to->geom->softc; + LIST_FOREACH(disk, &sc->sc_disks, d_next) { + if (disk->d_flags & G_MIRROR_DISK_FLAG_CANDELETE) + break; + } + val = (int *)bp->bio_data; + *val = (disk != NULL); + g_io_deliver(bp, 0); +} + +static void g_mirror_kernel_dump(struct bio *bp) { struct g_mirror_softc *sc; @@ -1114,9 +1131,10 @@ g_mirror_start(struct bio *bp) g_mirror_flush(sc, bp); return; case BIO_GETATTR: - if (g_handleattr_int(bp, "GEOM::candelete", 1)) + if (!strcmp(bp->bio_attribute, "GEOM::candelete")) { + g_mirror_candelete(bp); return; - else if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) { + } else if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) { g_mirror_kernel_dump(bp); return; } @@ -1680,6 +1698,10 @@ g_mirror_register_request(struct bio *bp) ("Consumer %s not opened (r%dw%de%d).", cp->provider->name, cp->acr, cp->acw, cp->ace)); } + if (bioq_first(&queue) == NULL) { + g_io_deliver(bp, EOPNOTSUPP); + return; + } while ((cbp = bioq_takefirst(&queue)) != NULL) { G_MIRROR_LOGREQ(3, cbp, "Sending request."); cp = cbp->bio_caller1; |