Deleted Added
full compact
virtio_blk.c (234349) virtio_blk.c (238360)
1/*-
2 * Copyright (c) 2011, Bryan Venteicher <bryanv@daemoninthecloset.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27/* Driver for VirtIO block devices. */
28
29#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2011, Bryan Venteicher <bryanv@daemoninthecloset.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27/* Driver for VirtIO block devices. */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/virtio/block/virtio_blk.c 234349 2012-04-16 18:29:12Z grehan $");
30__FBSDID("$FreeBSD: head/sys/dev/virtio/block/virtio_blk.c 238360 2012-07-11 02:57:19Z grehan $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/bio.h>
36#include <sys/malloc.h>
37#include <sys/module.h>
38#include <sys/sglist.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/queue.h>
42#include <sys/taskqueue.h>
43
44#include <geom/geom_disk.h>
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/bio.h>
36#include <sys/malloc.h>
37#include <sys/module.h>
38#include <sys/sglist.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/queue.h>
42#include <sys/taskqueue.h>
43
44#include <geom/geom_disk.h>
45#include <vm/uma.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49#include <sys/bus.h>
50#include <sys/rman.h>
51
52#include <dev/virtio/virtio.h>
53#include <dev/virtio/virtqueue.h>

--- 60 unchanged lines hidden (view full) ---

114static int vtblk_detach(device_t);
115static int vtblk_suspend(device_t);
116static int vtblk_resume(device_t);
117static int vtblk_shutdown(device_t);
118
119static int vtblk_open(struct disk *);
120static int vtblk_close(struct disk *);
121static int vtblk_ioctl(struct disk *, u_long, void *, int,
45
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50
51#include <dev/virtio/virtio.h>
52#include <dev/virtio/virtqueue.h>

--- 60 unchanged lines hidden (view full) ---

113static int vtblk_detach(device_t);
114static int vtblk_suspend(device_t);
115static int vtblk_resume(device_t);
116static int vtblk_shutdown(device_t);
117
118static int vtblk_open(struct disk *);
119static int vtblk_close(struct disk *);
120static int vtblk_ioctl(struct disk *, u_long, void *, int,
122 struct thread *);
121 struct thread *);
123static int vtblk_dump(void *, void *, vm_offset_t, off_t, size_t);
124static void vtblk_strategy(struct bio *);
125
126static void vtblk_negotiate_features(struct vtblk_softc *);
127static int vtblk_maximum_segments(struct vtblk_softc *,
128 struct virtio_blk_config *);
129static int vtblk_alloc_virtqueue(struct vtblk_softc *);
130static void vtblk_alloc_disk(struct vtblk_softc *,

--- 57 unchanged lines hidden (view full) ---

188#define VTBLK_LOCK(_sc) mtx_lock(VTBLK_MTX((_sc)))
189#define VTBLK_UNLOCK(_sc) mtx_unlock(VTBLK_MTX((_sc)))
190#define VTBLK_LOCK_DESTROY(_sc) mtx_destroy(VTBLK_MTX((_sc)))
191#define VTBLK_LOCK_ASSERT(_sc) mtx_assert(VTBLK_MTX((_sc)), MA_OWNED)
192#define VTBLK_LOCK_ASSERT_NOTOWNED(_sc) \
193 mtx_assert(VTBLK_MTX((_sc)), MA_NOTOWNED)
194
195#define VTBLK_DISK_NAME "vtbd"
122static int vtblk_dump(void *, void *, vm_offset_t, off_t, size_t);
123static void vtblk_strategy(struct bio *);
124
125static void vtblk_negotiate_features(struct vtblk_softc *);
126static int vtblk_maximum_segments(struct vtblk_softc *,
127 struct virtio_blk_config *);
128static int vtblk_alloc_virtqueue(struct vtblk_softc *);
129static void vtblk_alloc_disk(struct vtblk_softc *,

--- 57 unchanged lines hidden (view full) ---

187#define VTBLK_LOCK(_sc) mtx_lock(VTBLK_MTX((_sc)))
188#define VTBLK_UNLOCK(_sc) mtx_unlock(VTBLK_MTX((_sc)))
189#define VTBLK_LOCK_DESTROY(_sc) mtx_destroy(VTBLK_MTX((_sc)))
190#define VTBLK_LOCK_ASSERT(_sc) mtx_assert(VTBLK_MTX((_sc)), MA_OWNED)
191#define VTBLK_LOCK_ASSERT_NOTOWNED(_sc) \
192 mtx_assert(VTBLK_MTX((_sc)), MA_NOTOWNED)
193
194#define VTBLK_DISK_NAME "vtbd"
196#define VTBLK_QUIESCE_TIMEOUT (30 * hz)
195#define VTBLK_QUIESCE_TIMEOUT (30 * hz)
197
198/*
199 * Each block request uses at least two segments - one for the header
200 * and one for the status.
201 */
202#define VTBLK_MIN_SEGMENTS 2
203
196
197/*
198 * Each block request uses at least two segments - one for the header
199 * and one for the status.
200 */
201#define VTBLK_MIN_SEGMENTS 2
202
204static uma_zone_t vtblk_req_zone;
205
206static device_method_t vtblk_methods[] = {
207 /* Device methods. */
208 DEVMETHOD(device_probe, vtblk_probe),
209 DEVMETHOD(device_attach, vtblk_attach),
210 DEVMETHOD(device_detach, vtblk_detach),
211 DEVMETHOD(device_suspend, vtblk_suspend),
212 DEVMETHOD(device_resume, vtblk_resume),
213 DEVMETHOD(device_shutdown, vtblk_shutdown),

--- 17 unchanged lines hidden (view full) ---

231vtblk_modevent(module_t mod, int type, void *unused)
232{
233 int error;
234
235 error = 0;
236
237 switch (type) {
238 case MOD_LOAD:
203static device_method_t vtblk_methods[] = {
204 /* Device methods. */
205 DEVMETHOD(device_probe, vtblk_probe),
206 DEVMETHOD(device_attach, vtblk_attach),
207 DEVMETHOD(device_detach, vtblk_detach),
208 DEVMETHOD(device_suspend, vtblk_suspend),
209 DEVMETHOD(device_resume, vtblk_resume),
210 DEVMETHOD(device_shutdown, vtblk_shutdown),

--- 17 unchanged lines hidden (view full) ---

228vtblk_modevent(module_t mod, int type, void *unused)
229{
230 int error;
231
232 error = 0;
233
234 switch (type) {
235 case MOD_LOAD:
239 vtblk_req_zone = uma_zcreate("vtblk_request",
240 sizeof(struct vtblk_request),
241 NULL, NULL, NULL, NULL, 0, 0);
242 break;
243 case MOD_QUIESCE:
244 case MOD_UNLOAD:
236 case MOD_QUIESCE:
237 case MOD_UNLOAD:
245 if (uma_zone_get_cur(vtblk_req_zone) > 0)
246 error = EBUSY;
247 else if (type == MOD_UNLOAD) {
248 uma_zdestroy(vtblk_req_zone);
249 vtblk_req_zone = NULL;
250 }
251 break;
252 case MOD_SHUTDOWN:
253 break;
254 default:
255 error = EOPNOTSUPP;
256 break;
257 }
258
259 return (error);

--- 51 unchanged lines hidden (view full) ---

311 error = ENOTSUP;
312 device_printf(dev, "host requires unsupported "
313 "maximum segment size feature\n");
314 goto fail;
315 }
316 }
317
318 sc->vtblk_max_nsegs = vtblk_maximum_segments(sc, &blkcfg);
238 case MOD_SHUTDOWN:
239 break;
240 default:
241 error = EOPNOTSUPP;
242 break;
243 }
244
245 return (error);

--- 51 unchanged lines hidden (view full) ---

297 error = ENOTSUP;
298 device_printf(dev, "host requires unsupported "
299 "maximum segment size feature\n");
300 goto fail;
301 }
302 }
303
304 sc->vtblk_max_nsegs = vtblk_maximum_segments(sc, &blkcfg);
319 if (sc->vtblk_max_nsegs <= VTBLK_MIN_SEGMENTS) {
305 if (sc->vtblk_max_nsegs <= VTBLK_MIN_SEGMENTS) {
320 error = EINVAL;
321 device_printf(dev, "fewer than minimum number of segments "
322 "allowed: %d\n", sc->vtblk_max_nsegs);
323 goto fail;
324 }
325
326 sc->vtblk_sglist = sglist_alloc(sc->vtblk_max_nsegs, M_NOWAIT);
327 if (sc->vtblk_sglist == NULL) {

--- 160 unchanged lines hidden (view full) ---

488vtblk_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
489 size_t length)
490{
491 struct disk *dp;
492 struct vtblk_softc *sc;
493 int error;
494
495 dp = arg;
306 error = EINVAL;
307 device_printf(dev, "fewer than minimum number of segments "
308 "allowed: %d\n", sc->vtblk_max_nsegs);
309 goto fail;
310 }
311
312 sc->vtblk_sglist = sglist_alloc(sc->vtblk_max_nsegs, M_NOWAIT);
313 if (sc->vtblk_sglist == NULL) {

--- 160 unchanged lines hidden (view full) ---

474vtblk_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
475 size_t length)
476{
477 struct disk *dp;
478 struct vtblk_softc *sc;
479 int error;
480
481 dp = arg;
496 error = 0;
497
498 if ((sc = dp->d_drv1) == NULL)
499 return (ENXIO);
500
501 VTBLK_LOCK(sc);
502
503 if ((sc->vtblk_flags & VTBLK_FLAG_DUMPING) == 0) {
504 vtblk_prepare_dump(sc);

--- 29 unchanged lines hidden (view full) ---

534 * be a better way to report our readonly'ness to GEOM above.
535 */
536 if (sc->vtblk_flags & VTBLK_FLAG_READONLY &&
537 (bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_FLUSH)) {
538 vtblk_finish_bio(bp, EROFS);
539 return;
540 }
541
482
483 if ((sc = dp->d_drv1) == NULL)
484 return (ENXIO);
485
486 VTBLK_LOCK(sc);
487
488 if ((sc->vtblk_flags & VTBLK_FLAG_DUMPING) == 0) {
489 vtblk_prepare_dump(sc);

--- 29 unchanged lines hidden (view full) ---

519 * be a better way to report our readonly'ness to GEOM above.
520 */
521 if (sc->vtblk_flags & VTBLK_FLAG_READONLY &&
522 (bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_FLUSH)) {
523 vtblk_finish_bio(bp, EROFS);
524 return;
525 }
526
542#ifdef INVARIANTS
527#ifdef INVARIANTS
543 /*
544 * Prevent read/write buffers spanning too many segments from
545 * getting into the queue. This should only trip if d_maxsize
546 * was incorrectly set.
547 */
548 if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
549 int nsegs, max_nsegs;
528 /*
529 * Prevent read/write buffers spanning too many segments from
530 * getting into the queue. This should only trip if d_maxsize
531 * was incorrectly set.
532 */
533 if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
534 int nsegs, max_nsegs;
550
535
551 nsegs = sglist_count(bp->bio_data, bp->bio_bcount);
552 max_nsegs = sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS;
553
554 KASSERT(nsegs <= max_nsegs,
536 nsegs = sglist_count(bp->bio_data, bp->bio_bcount);
537 max_nsegs = sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS;
538
539 KASSERT(nsegs <= max_nsegs,
555 ("bio spanned too many segments: %d, max: %d",
556 nsegs, max_nsegs));
540 ("bio %p spanned too many segments: %d, max: %d",
541 bp, nsegs, max_nsegs));
557 }
558#endif
559
560 VTBLK_LOCK(sc);
561 if (sc->vtblk_flags & VTBLK_FLAG_DETACH)
562 vtblk_finish_bio(bp, ENXIO);
563 else {
564 bioq_disksort(&sc->vtblk_bioq, bp);

--- 230 unchanged lines hidden (view full) ---

795
796 sg = sc->vtblk_sglist;
797 bp = req->vbr_bp;
798 writable = 0;
799
800 VTBLK_LOCK_ASSERT(sc);
801
802 sglist_reset(sg);
542 }
543#endif
544
545 VTBLK_LOCK(sc);
546 if (sc->vtblk_flags & VTBLK_FLAG_DETACH)
547 vtblk_finish_bio(bp, ENXIO);
548 else {
549 bioq_disksort(&sc->vtblk_bioq, bp);

--- 230 unchanged lines hidden (view full) ---

780
781 sg = sc->vtblk_sglist;
782 bp = req->vbr_bp;
783 writable = 0;
784
785 VTBLK_LOCK_ASSERT(sc);
786
787 sglist_reset(sg);
803 error = sglist_append(sg, &req->vbr_hdr,
804 sizeof(struct virtio_blk_outhdr));
805 KASSERT(error == 0, ("error adding header to sglist"));
806 KASSERT(sg->sg_nseg == 1,
807 ("header spanned multiple segments: %d", sg->sg_nseg));
808
788
789 sglist_append(sg, &req->vbr_hdr, sizeof(struct virtio_blk_outhdr));
790
809 if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
810 error = sglist_append(sg, bp->bio_data, bp->bio_bcount);
791 if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
792 error = sglist_append(sg, bp->bio_data, bp->bio_bcount);
811 KASSERT(error == 0, ("error adding buffer to sglist"));
793 if (error || sg->sg_nseg == sg->sg_maxseg)
794 panic("%s: data buffer too big bio:%p error:%d",
795 __FUNCTION__, bp, error);
812
813 /* BIO_READ means the host writes into our buffer. */
814 if (bp->bio_cmd == BIO_READ)
796
797 /* BIO_READ means the host writes into our buffer. */
798 if (bp->bio_cmd == BIO_READ)
815 writable += sg->sg_nseg - 1;
799 writable = sg->sg_nseg - 1;
816 }
817
800 }
801
818 error = sglist_append(sg, &req->vbr_ack, sizeof(uint8_t));
819 KASSERT(error == 0, ("error adding ack to sglist"));
820 writable++;
802 writable++;
803 sglist_append(sg, &req->vbr_ack, sizeof(uint8_t));
821
804
822 KASSERT(sg->sg_nseg >= VTBLK_MIN_SEGMENTS,
823 ("fewer than min segments: %d", sg->sg_nseg));
824
825 readable = sg->sg_nseg - writable;
826
827 return (virtqueue_enqueue(sc->vtblk_vq, req, sg, readable, writable));
828}
829
830static int
831vtblk_vq_intr(void *xsc)
832{

--- 157 unchanged lines hidden (view full) ---

990 buf.bio_cmd = BIO_FLUSH;
991
992 return (vtblk_poll_request(sc, req));
993}
994
995static int
996vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req)
997{
805 readable = sg->sg_nseg - writable;
806
807 return (virtqueue_enqueue(sc->vtblk_vq, req, sg, readable, writable));
808}
809
810static int
811vtblk_vq_intr(void *xsc)
812{

--- 157 unchanged lines hidden (view full) ---

970 buf.bio_cmd = BIO_FLUSH;
971
972 return (vtblk_poll_request(sc, req));
973}
974
975static int
976vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req)
977{
998 device_t dev;
999 struct virtqueue *vq;
1000 struct vtblk_request *r;
1001 int error;
1002
978 struct virtqueue *vq;
979 struct vtblk_request *r;
980 int error;
981
1003 dev = sc->vtblk_dev;
1004 vq = sc->vtblk_vq;
1005
1006 if (!virtqueue_empty(vq))
1007 return (EBUSY);
1008
1009 error = vtblk_execute_request(sc, req);
1010 if (error)
1011 return (error);
1012
1013 virtqueue_notify(vq);
1014
1015 r = virtqueue_poll(vq, NULL);
982 vq = sc->vtblk_vq;
983
984 if (!virtqueue_empty(vq))
985 return (EBUSY);
986
987 error = vtblk_execute_request(sc, req);
988 if (error)
989 return (error);
990
991 virtqueue_notify(vq);
992
993 r = virtqueue_poll(vq, NULL);
1016 KASSERT(r == req, ("unexpected request response"));
994 KASSERT(r == req, ("unexpected request response: %p/%p", r, req));
1017
1018 error = vtblk_request_error(req);
1019 if (error && bootverbose) {
995
996 error = vtblk_request_error(req);
997 if (error && bootverbose) {
1020 device_printf(dev, "vtblk_poll_request: IO error: %d\n",
1021 error);
998 device_printf(sc->vtblk_dev,
999 "%s: IO error: %d\n", __FUNCTION__, error);
1022 }
1023
1024 return (error);
1025}
1026
1027static void
1028vtblk_finish_completed(struct vtblk_softc *sc)
1029{

--- 55 unchanged lines hidden (view full) ---

1085 while (bioq_first(bioq) != NULL) {
1086 bp = bioq_takefirst(bioq);
1087 vtblk_finish_bio(bp, ENXIO);
1088 }
1089
1090 vtblk_free_requests(sc);
1091}
1092
1000 }
1001
1002 return (error);
1003}
1004
1005static void
1006vtblk_finish_completed(struct vtblk_softc *sc)
1007{

--- 55 unchanged lines hidden (view full) ---

1063 while (bioq_first(bioq) != NULL) {
1064 bp = bioq_takefirst(bioq);
1065 vtblk_finish_bio(bp, ENXIO);
1066 }
1067
1068 vtblk_free_requests(sc);
1069}
1070
1071#ifdef INVARIANTS
1072static void
1073vtblk_request_invariants(struct vtblk_request *req)
1074{
1075 int hdr_nsegs, ack_nsegs;
1076
1077 hdr_nsegs = sglist_count(&req->vbr_hdr, sizeof(req->vbr_hdr));
1078 ack_nsegs = sglist_count(&req->vbr_ack, sizeof(req->vbr_ack));
1079
1080 KASSERT(hdr_nsegs == 1, ("request header crossed page boundary"));
1081 KASSERT(ack_nsegs == 1, ("request ack crossed page boundary"));
1082}
1083#endif
1084
1093static int
1094vtblk_alloc_requests(struct vtblk_softc *sc)
1095{
1096 struct vtblk_request *req;
1097 int i, nreqs;
1098
1099 nreqs = virtqueue_size(sc->vtblk_vq);
1100
1101 /*
1102 * Preallocate sufficient requests to keep the virtqueue full. Each
1103 * request consumes VTBLK_MIN_SEGMENTS or more descriptors so reduce
1104 * the number allocated when indirect descriptors are not available.
1105 */
1106 if ((sc->vtblk_flags & VTBLK_FLAG_INDIRECT) == 0)
1107 nreqs /= VTBLK_MIN_SEGMENTS;
1108
1109 for (i = 0; i < nreqs; i++) {
1085static int
1086vtblk_alloc_requests(struct vtblk_softc *sc)
1087{
1088 struct vtblk_request *req;
1089 int i, nreqs;
1090
1091 nreqs = virtqueue_size(sc->vtblk_vq);
1092
1093 /*
1094 * Preallocate sufficient requests to keep the virtqueue full. Each
1095 * request consumes VTBLK_MIN_SEGMENTS or more descriptors so reduce
1096 * the number allocated when indirect descriptors are not available.
1097 */
1098 if ((sc->vtblk_flags & VTBLK_FLAG_INDIRECT) == 0)
1099 nreqs /= VTBLK_MIN_SEGMENTS;
1100
1101 for (i = 0; i < nreqs; i++) {
1110 req = uma_zalloc(vtblk_req_zone, M_NOWAIT);
1102 req = malloc(sizeof(struct vtblk_request), M_DEVBUF, M_NOWAIT);
1111 if (req == NULL)
1112 return (ENOMEM);
1113
1103 if (req == NULL)
1104 return (ENOMEM);
1105
1106#ifdef INVARIANTS
1107 vtblk_request_invariants(req);
1108#endif
1109
1114 sc->vtblk_request_count++;
1115 vtblk_enqueue_request(sc, req);
1116 }
1117
1118 return (0);
1119}
1120
1121static void
1122vtblk_free_requests(struct vtblk_softc *sc)
1123{
1124 struct vtblk_request *req;
1125
1126 KASSERT(TAILQ_EMPTY(&sc->vtblk_req_ready),
1127 ("ready requests left on queue"));
1128
1129 while ((req = vtblk_dequeue_request(sc)) != NULL) {
1130 sc->vtblk_request_count--;
1110 sc->vtblk_request_count++;
1111 vtblk_enqueue_request(sc, req);
1112 }
1113
1114 return (0);
1115}
1116
1117static void
1118vtblk_free_requests(struct vtblk_softc *sc)
1119{
1120 struct vtblk_request *req;
1121
1122 KASSERT(TAILQ_EMPTY(&sc->vtblk_req_ready),
1123 ("ready requests left on queue"));
1124
1125 while ((req = vtblk_dequeue_request(sc)) != NULL) {
1126 sc->vtblk_request_count--;
1131 uma_zfree(vtblk_req_zone, req);
1127 free(req, M_DEVBUF);
1132 }
1133
1128 }
1129
1134 KASSERT(sc->vtblk_request_count == 0, ("leaked requests"));
1130 KASSERT(sc->vtblk_request_count == 0,
1131 ("leaked requests: %d", sc->vtblk_request_count));
1135}
1136
1137static struct vtblk_request *
1138vtblk_dequeue_request(struct vtblk_softc *sc)
1139{
1140 struct vtblk_request *req;
1141
1142 req = TAILQ_FIRST(&sc->vtblk_req_free);

--- 65 unchanged lines hidden ---
1132}
1133
1134static struct vtblk_request *
1135vtblk_dequeue_request(struct vtblk_softc *sc)
1136{
1137 struct vtblk_request *req;
1138
1139 req = TAILQ_FIRST(&sc->vtblk_req_free);

--- 65 unchanged lines hidden ---