1 /* 2 * Copyright (c) 2006, Cisco Systems, Inc. 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 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Cisco Systems, Inc. nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/mbuf.h> 37 #include <sys/malloc.h> 38 #include <sys/kernel.h> 39 #include <sys/socket.h> 40 #include <sys/queue.h> 41 #include <sys/taskqueue.h> 42 #include <sys/namei.h> 43 #include <sys/proc.h> 44 #include <sys/filedesc.h> 45 #include <sys/vnode.h> 46 #include <sys/fcntl.h> 47 #include <sys/disk.h> 48 #include <sys/bio.h> 49 50 #include <sys/module.h> 51 #include <sys/bus.h> 52 #include <sys/sysctl.h> 53 54 #include <geom/geom.h> 55 56 #include <vm/vm_extern.h> 57 #include <vm/vm_kern.h> 58 59 #include <machine/xen-os.h> 60 #include <machine/hypervisor.h> 61 #include <machine/hypervisor-ifs.h> 62 #include <machine/xen_intr.h> 63 #include <machine/evtchn.h> 64 #include <machine/xenbus.h> 65 #include <machine/gnttab.h> 66 #include <machine/xen-public/memory.h> 67 #include <dev/xen/xenbus/xenbus_comms.h> 68 69 70 #if XEN_BLKBACK_DEBUG 71 #define DPRINTF(fmt, args...) \ 72 printf("blkback (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args) 73 #else 74 #define DPRINTF(fmt, args...) ((void)0) 75 #endif 76 77 #define WPRINTF(fmt, args...) \ 78 printf("blkback (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args) 79 80 #define BLKBACK_INVALID_HANDLE (~0) 81 82 struct ring_ref { 83 vm_offset_t va; 84 grant_handle_t handle; 85 uint64_t bus_addr; 86 }; 87 88 typedef struct blkback_info { 89 90 /* Schedule lists */ 91 STAILQ_ENTRY(blkback_info) next_req; 92 int on_req_sched_list; 93 94 struct xenbus_device *xdev; 95 XenbusState frontend_state; 96 97 domid_t domid; 98 99 int state; 100 int ring_connected; 101 struct ring_ref rr; 102 blkif_back_ring_t ring; 103 evtchn_port_t evtchn; 104 int irq; 105 void *irq_cookie; 106 107 int ref_cnt; 108 109 int handle; 110 char *mode; 111 char *type; 112 char *dev_name; 113 114 struct vnode *vn; 115 struct cdev *cdev; 116 struct cdevsw *csw; 117 u_int sector_size; 118 int sector_size_shift; 119 off_t media_size; 120 u_int media_num_sectors; 121 int major; 122 int minor; 123 int read_only; 124 125 struct mtx blk_ring_lock; 126 127 device_t ndev; 128 129 /* Stats */ 130 int st_rd_req; 131 int st_wr_req; 132 int st_oo_req; 133 int st_err_req; 134 } blkif_t; 135 136 /* 137 * These are rather arbitrary. They are fairly large because adjacent requests 138 * pulled from a communication ring are quite likely to end up being part of 139 * the same scatter/gather request at the disc. 140 * 141 * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW ** 142 * 143 * This will increase the chances of being able to write whole tracks. 144 * 64 should be enough to keep us competitive with Linux. 145 */ 146 static int blkif_reqs = 64; 147 TUNABLE_INT("xen.vbd.blkif_reqs", &blkif_reqs); 148 149 static int mmap_pages; 150 151 /* 152 * Each outstanding request that we've passed to the lower device layers has a 153 * 'pending_req' allocated to it. Each buffer_head that completes decrements 154 * the pendcnt towards zero. When it hits zero, the specified domain has a 155 * response queued for it, with the saved 'id' passed back. 156 */ 157 typedef struct pending_req { 158 blkif_t *blkif; 159 uint64_t id; 160 int nr_pages; 161 int pendcnt; 162 unsigned short operation; 163 int status; 164 STAILQ_ENTRY(pending_req) free_list; 165 } pending_req_t; 166 167 static pending_req_t *pending_reqs; 168 static STAILQ_HEAD(pending_reqs_list, pending_req) pending_free = 169 STAILQ_HEAD_INITIALIZER(pending_free); 170 static struct mtx pending_free_lock; 171 172 static STAILQ_HEAD(blkback_req_sched_list, blkback_info) req_sched_list = 173 STAILQ_HEAD_INITIALIZER(req_sched_list); 174 static struct mtx req_sched_list_lock; 175 176 static unsigned long mmap_vstart; 177 static unsigned long *pending_vaddrs; 178 static grant_handle_t *pending_grant_handles; 179 180 static struct task blk_req_task; 181 182 /* Protos */ 183 static void disconnect_ring(blkif_t *blkif); 184 static int vbd_add_dev(struct xenbus_device *xdev); 185 186 static inline int vaddr_pagenr(pending_req_t *req, int seg) 187 { 188 return (req - pending_reqs) * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg; 189 } 190 191 static inline unsigned long vaddr(pending_req_t *req, int seg) 192 { 193 return pending_vaddrs[vaddr_pagenr(req, seg)]; 194 } 195 196 #define pending_handle(_req, _seg) \ 197 (pending_grant_handles[vaddr_pagenr(_req, _seg)]) 198 199 static unsigned long 200 alloc_empty_page_range(unsigned long nr_pages) 201 { 202 void *pages; 203 int i = 0, j = 0; 204 multicall_entry_t mcl[17]; 205 unsigned long mfn_list[16]; 206 struct xen_memory_reservation reservation = { 207 .extent_start = mfn_list, 208 .nr_extents = 0, 209 .address_bits = 0, 210 .extent_order = 0, 211 .domid = DOMID_SELF 212 }; 213 214 pages = malloc(nr_pages*PAGE_SIZE, M_DEVBUF, M_NOWAIT); 215 if (pages == NULL) 216 return 0; 217 218 memset(mcl, 0, sizeof(mcl)); 219 220 while (i < nr_pages) { 221 unsigned long va = (unsigned long)pages + (i++ * PAGE_SIZE); 222 223 mcl[j].op = __HYPERVISOR_update_va_mapping; 224 mcl[j].args[0] = va; 225 226 mfn_list[j++] = vtomach(va) >> PAGE_SHIFT; 227 228 xen_phys_machine[(vtophys(va) >> PAGE_SHIFT)] = INVALID_P2M_ENTRY; 229 230 if (j == 16 || i == nr_pages) { 231 mcl[j-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_LOCAL; 232 233 reservation.nr_extents = j; 234 235 mcl[j].op = __HYPERVISOR_memory_op; 236 mcl[j].args[0] = XENMEM_decrease_reservation; 237 mcl[j].args[1] = (unsigned long)&reservation; 238 239 (void)HYPERVISOR_multicall(mcl, j+1); 240 241 mcl[j-1].args[MULTI_UVMFLAGS_INDEX] = 0; 242 j = 0; 243 } 244 } 245 246 return (unsigned long)pages; 247 } 248 249 static pending_req_t * 250 alloc_req(void) 251 { 252 pending_req_t *req; 253 mtx_lock(&pending_free_lock); 254 if ((req = STAILQ_FIRST(&pending_free))) { 255 STAILQ_REMOVE(&pending_free, req, pending_req, free_list); 256 STAILQ_NEXT(req, free_list) = NULL; 257 } 258 mtx_unlock(&pending_free_lock); 259 return req; 260 } 261 262 static void 263 free_req(pending_req_t *req) 264 { 265 int was_empty; 266 267 mtx_lock(&pending_free_lock); 268 was_empty = STAILQ_EMPTY(&pending_free); 269 STAILQ_INSERT_TAIL(&pending_free, req, free_list); 270 mtx_unlock(&pending_free_lock); 271 if (was_empty) 272 taskqueue_enqueue(taskqueue_swi, &blk_req_task); 273 } 274 275 static void 276 fast_flush_area(pending_req_t *req) 277 { 278 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 279 unsigned int i, invcount = 0; 280 grant_handle_t handle; 281 int ret; 282 283 for (i = 0; i < req->nr_pages; i++) { 284 handle = pending_handle(req, i); 285 if (handle == BLKBACK_INVALID_HANDLE) 286 continue; 287 unmap[invcount].host_addr = vaddr(req, i); 288 unmap[invcount].dev_bus_addr = 0; 289 unmap[invcount].handle = handle; 290 pending_handle(req, i) = BLKBACK_INVALID_HANDLE; 291 invcount++; 292 } 293 294 ret = HYPERVISOR_grant_table_op( 295 GNTTABOP_unmap_grant_ref, unmap, invcount); 296 PANIC_IF(ret); 297 } 298 299 static void 300 blkif_get(blkif_t *blkif) 301 { 302 atomic_add_int(&blkif->ref_cnt, 1); 303 } 304 305 static void 306 blkif_put(blkif_t *blkif) 307 { 308 if (atomic_fetchadd_int(&blkif->ref_cnt, -1) == 1) { 309 DPRINTF("Removing %x\n", (unsigned int)blkif); 310 disconnect_ring(blkif); 311 if (blkif->mode) 312 free(blkif->mode, M_DEVBUF); 313 if (blkif->type) 314 free(blkif->type, M_DEVBUF); 315 if (blkif->dev_name) 316 free(blkif->dev_name, M_DEVBUF); 317 free(blkif, M_DEVBUF); 318 } 319 } 320 321 static int 322 blkif_create(struct xenbus_device *xdev, long handle, char *mode, char *type, char *params) 323 { 324 blkif_t *blkif; 325 326 blkif = (blkif_t *)malloc(sizeof(*blkif), M_DEVBUF, M_NOWAIT | M_ZERO); 327 if (!blkif) 328 return ENOMEM; 329 330 DPRINTF("Created %x\n", (unsigned int)blkif); 331 332 blkif->ref_cnt = 1; 333 blkif->domid = xdev->otherend_id; 334 blkif->handle = handle; 335 blkif->mode = mode; 336 blkif->type = type; 337 blkif->dev_name = params; 338 blkif->xdev = xdev; 339 xdev->data = blkif; 340 341 mtx_init(&blkif->blk_ring_lock, "blk_ring_ock", "blkback ring lock", MTX_DEF); 342 343 if (strcmp(mode, "w")) 344 blkif->read_only = 1; 345 346 return 0; 347 } 348 349 static void 350 add_to_req_schedule_list_tail(blkif_t *blkif) 351 { 352 if (!blkif->on_req_sched_list) { 353 mtx_lock(&req_sched_list_lock); 354 if (!blkif->on_req_sched_list && (blkif->state == XenbusStateConnected)) { 355 blkif_get(blkif); 356 STAILQ_INSERT_TAIL(&req_sched_list, blkif, next_req); 357 blkif->on_req_sched_list = 1; 358 taskqueue_enqueue(taskqueue_swi, &blk_req_task); 359 } 360 mtx_unlock(&req_sched_list_lock); 361 } 362 } 363 364 /* This routine does not call blkif_get(), does not schedule the blk_req_task to run, 365 and assumes that the state is connected */ 366 static void 367 add_to_req_schedule_list_tail2(blkif_t *blkif) 368 { 369 mtx_lock(&req_sched_list_lock); 370 if (!blkif->on_req_sched_list) { 371 STAILQ_INSERT_TAIL(&req_sched_list, blkif, next_req); 372 blkif->on_req_sched_list = 1; 373 } 374 mtx_unlock(&req_sched_list_lock); 375 } 376 377 /* Removes blkif from front of list and does not call blkif_put() (caller must) */ 378 static blkif_t * 379 remove_from_req_schedule_list(void) 380 { 381 blkif_t *blkif; 382 383 mtx_lock(&req_sched_list_lock); 384 385 if ((blkif = STAILQ_FIRST(&req_sched_list))) { 386 STAILQ_REMOVE(&req_sched_list, blkif, blkback_info, next_req); 387 STAILQ_NEXT(blkif, next_req) = NULL; 388 blkif->on_req_sched_list = 0; 389 } 390 391 mtx_unlock(&req_sched_list_lock); 392 393 return blkif; 394 } 395 396 static void 397 make_response(blkif_t *blkif, uint64_t id, 398 unsigned short op, int st) 399 { 400 blkif_response_t *resp; 401 blkif_back_ring_t *blk_ring = &blkif->ring; 402 int more_to_do = 0; 403 int notify; 404 405 mtx_lock(&blkif->blk_ring_lock); 406 407 408 /* Place on the response ring for the relevant domain. */ 409 resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); 410 resp->id = id; 411 resp->operation = op; 412 resp->status = st; 413 blk_ring->rsp_prod_pvt++; 414 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify); 415 416 if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) { 417 /* 418 * Tail check for pending requests. Allows frontend to avoid 419 * notifications if requests are already in flight (lower 420 * overheads and promotes batching). 421 */ 422 RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do); 423 424 } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) 425 more_to_do = 1; 426 427 mtx_unlock(&blkif->blk_ring_lock); 428 429 if (more_to_do) 430 add_to_req_schedule_list_tail(blkif); 431 432 if (notify) 433 notify_remote_via_irq(blkif->irq); 434 } 435 436 static void 437 end_block_io_op(struct bio *bio) 438 { 439 pending_req_t *pending_req = bio->bio_caller2; 440 441 if (bio->bio_error) { 442 DPRINTF("BIO returned error %d for operation on device %s\n", 443 bio->bio_error, pending_req->blkif->dev_name); 444 pending_req->status = BLKIF_RSP_ERROR; 445 pending_req->blkif->st_err_req++; 446 } 447 448 #if 0 449 printf("done: bio=%x error=%x completed=%llu resid=%lu flags=%x\n", 450 (unsigned int)bio, bio->bio_error, bio->bio_completed, bio->bio_resid, bio->bio_flags); 451 #endif 452 453 if (atomic_fetchadd_int(&pending_req->pendcnt, -1) == 1) { 454 fast_flush_area(pending_req); 455 make_response(pending_req->blkif, pending_req->id, 456 pending_req->operation, pending_req->status); 457 blkif_put(pending_req->blkif); 458 free_req(pending_req); 459 } 460 461 g_destroy_bio(bio); 462 } 463 464 static void 465 dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req, pending_req_t *pending_req) 466 { 467 struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 468 struct { 469 unsigned long buf; unsigned int nsec; 470 } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 471 unsigned int nseg = req->nr_segments, nr_sects = 0; 472 struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 473 int operation, ret, i, nbio = 0; 474 475 /* Check that number of segments is sane. */ 476 if (unlikely(nseg == 0) || 477 unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { 478 DPRINTF("Bad number of segments in request (%d)\n", nseg); 479 goto fail_response; 480 } 481 482 if (req->operation == BLKIF_OP_WRITE) { 483 if (blkif->read_only) { 484 DPRINTF("Attempt to write to read only device %s\n", blkif->dev_name); 485 goto fail_response; 486 } 487 operation = BIO_WRITE; 488 } else 489 operation = BIO_READ; 490 491 pending_req->blkif = blkif; 492 pending_req->id = req->id; 493 pending_req->operation = req->operation; 494 pending_req->status = BLKIF_RSP_OKAY; 495 pending_req->nr_pages = nseg; 496 497 for (i = 0; i < nseg; i++) { 498 seg[i].nsec = req->seg[i].last_sect - 499 req->seg[i].first_sect + 1; 500 501 if ((req->seg[i].last_sect >= (PAGE_SIZE >> 9)) || 502 (seg[i].nsec <= 0)) 503 goto fail_response; 504 nr_sects += seg[i].nsec; 505 506 map[i].host_addr = vaddr(pending_req, i); 507 map[i].dom = blkif->domid; 508 map[i].ref = req->seg[i].gref; 509 map[i].flags = GNTMAP_host_map; 510 if (operation == BIO_WRITE) 511 map[i].flags |= GNTMAP_readonly; 512 } 513 514 /* Convert to the disk's sector size */ 515 nr_sects = (nr_sects << 9) >> blkif->sector_size_shift; 516 517 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); 518 PANIC_IF(ret); 519 520 for (i = 0; i < nseg; i++) { 521 if (unlikely(map[i].status != 0)) { 522 DPRINTF("invalid buffer -- could not remap it\n"); 523 goto fail_flush; 524 } 525 526 pending_handle(pending_req, i) = map[i].handle; 527 #if 0 528 /* Can't do this in FreeBSD since vtophys() returns the pfn */ 529 /* of the remote domain who loaned us the machine page - DPT */ 530 xen_phys_machine[(vtophys(vaddr(pending_req, i)) >> PAGE_SHIFT)] = 531 map[i]dev_bus_addr >> PAGE_SHIFT; 532 #endif 533 seg[i].buf = map[i].dev_bus_addr | 534 (req->seg[i].first_sect << 9); 535 } 536 537 if (req->sector_number + nr_sects > blkif->media_num_sectors) { 538 DPRINTF("%s of [%llu,%llu] extends past end of device %s\n", 539 operation == BIO_READ ? "read" : "write", 540 req->sector_number, 541 req->sector_number + nr_sects, blkif->dev_name); 542 goto fail_flush; 543 } 544 545 for (i = 0; i < nseg; i++) { 546 struct bio *bio; 547 548 if ((int)seg[i].nsec & ((blkif->sector_size >> 9) - 1)) { 549 DPRINTF("Misaligned I/O request from domain %d", blkif->domid); 550 goto fail_put_bio; 551 } 552 553 bio = biolist[nbio++] = g_new_bio(); 554 if (unlikely(bio == NULL)) 555 goto fail_put_bio; 556 557 bio->bio_cmd = operation; 558 bio->bio_offset = req->sector_number << blkif->sector_size_shift; 559 bio->bio_length = seg[i].nsec << 9; 560 bio->bio_bcount = bio->bio_length; 561 bio->bio_data = (caddr_t)(vaddr(pending_req, i) | (seg[i].buf & PAGE_MASK)); 562 bio->bio_done = end_block_io_op; 563 bio->bio_caller2 = pending_req; 564 bio->bio_dev = blkif->cdev; 565 566 req->sector_number += (seg[i].nsec << 9) >> blkif->sector_size_shift; 567 #if 0 568 printf("new: bio=%x cmd=%d sect=%llu nsect=%u iosize_max=%u @ %08lx\n", 569 (unsigned int)bio, req->operation, req->sector_number, seg[i].nsec, 570 blkif->cdev->si_iosize_max, seg[i].buf); 571 #endif 572 } 573 574 pending_req->pendcnt = nbio; 575 blkif_get(blkif); 576 577 for (i = 0; i < nbio; i++) 578 (*blkif->csw->d_strategy)(biolist[i]); 579 580 return; 581 582 fail_put_bio: 583 for (i = 0; i < (nbio-1); i++) 584 g_destroy_bio(biolist[i]); 585 fail_flush: 586 fast_flush_area(pending_req); 587 fail_response: 588 make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); 589 free_req(pending_req); 590 } 591 592 static void 593 blk_req_action(void *context, int pending) 594 { 595 blkif_t *blkif; 596 597 DPRINTF("\n"); 598 599 while (!STAILQ_EMPTY(&req_sched_list)) { 600 blkif_back_ring_t *blk_ring; 601 RING_IDX rc, rp; 602 603 blkif = remove_from_req_schedule_list(); 604 605 blk_ring = &blkif->ring; 606 rc = blk_ring->req_cons; 607 rp = blk_ring->sring->req_prod; 608 rmb(); /* Ensure we see queued requests up to 'rp'. */ 609 610 while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) { 611 blkif_request_t *req; 612 pending_req_t *pending_req; 613 614 pending_req = alloc_req(); 615 if (pending_req == NULL) 616 goto out_of_preqs; 617 618 req = RING_GET_REQUEST(blk_ring, rc); 619 blk_ring->req_cons = ++rc; /* before make_response() */ 620 621 switch (req->operation) { 622 case BLKIF_OP_READ: 623 blkif->st_rd_req++; 624 dispatch_rw_block_io(blkif, req, pending_req); 625 break; 626 case BLKIF_OP_WRITE: 627 blkif->st_wr_req++; 628 dispatch_rw_block_io(blkif, req, pending_req); 629 break; 630 default: 631 blkif->st_err_req++; 632 DPRINTF("error: unknown block io operation [%d]\n", 633 req->operation); 634 make_response(blkif, req->id, req->operation, 635 BLKIF_RSP_ERROR); 636 free_req(pending_req); 637 break; 638 } 639 } 640 641 blkif_put(blkif); 642 } 643 644 return; 645 646 out_of_preqs: 647 /* We ran out of pending req structs */ 648 /* Just requeue interface and wait to be rescheduled to run when one is freed */ 649 add_to_req_schedule_list_tail2(blkif); 650 blkif->st_oo_req++; 651 } 652 653 /* Handle interrupt from a frontend */ 654 static void 655 blkback_intr(void *arg) 656 { 657 blkif_t *blkif = arg; 658 DPRINTF("%x\n", (unsigned int)blkif); 659 add_to_req_schedule_list_tail(blkif); 660 } 661 662 /* Map grant ref for ring */ 663 static int 664 map_ring(grant_ref_t ref, domid_t dom, struct ring_ref *ring) 665 { 666 struct gnttab_map_grant_ref op; 667 668 ring->va = kmem_alloc_nofault(kernel_map, PAGE_SIZE); 669 if (ring->va == 0) 670 return ENOMEM; 671 672 op.host_addr = ring->va; 673 op.flags = GNTMAP_host_map; 674 op.ref = ref; 675 op.dom = dom; 676 HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); 677 if (op.status) { 678 WPRINTF("grant table op err=%d\n", op.status); 679 kmem_free(kernel_map, ring->va, PAGE_SIZE); 680 ring->va = 0; 681 return EACCES; 682 } 683 684 ring->handle = op.handle; 685 ring->bus_addr = op.dev_bus_addr; 686 687 return 0; 688 } 689 690 /* Unmap grant ref for ring */ 691 static void 692 unmap_ring(struct ring_ref *ring) 693 { 694 struct gnttab_unmap_grant_ref op; 695 696 op.host_addr = ring->va; 697 op.dev_bus_addr = ring->bus_addr; 698 op.handle = ring->handle; 699 HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); 700 if (op.status) 701 WPRINTF("grant table op err=%d\n", op.status); 702 703 kmem_free(kernel_map, ring->va, PAGE_SIZE); 704 ring->va = 0; 705 } 706 707 static int 708 connect_ring(blkif_t *blkif) 709 { 710 struct xenbus_device *xdev = blkif->xdev; 711 blkif_sring_t *ring; 712 unsigned long ring_ref; 713 evtchn_port_t evtchn; 714 evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; 715 int err; 716 717 if (blkif->ring_connected) 718 return 0; 719 720 // Grab FE data and map his memory 721 err = xenbus_gather(NULL, xdev->otherend, 722 "ring-ref", "%lu", &ring_ref, 723 "event-channel", "%u", &evtchn, NULL); 724 if (err) { 725 xenbus_dev_fatal(xdev, err, 726 "reading %s/ring-ref and event-channel", 727 xdev->otherend); 728 return err; 729 } 730 731 err = map_ring(ring_ref, blkif->domid, &blkif->rr); 732 if (err) { 733 xenbus_dev_fatal(xdev, err, "mapping ring"); 734 return err; 735 } 736 ring = (blkif_sring_t *)blkif->rr.va; 737 BACK_RING_INIT(&blkif->ring, ring, PAGE_SIZE); 738 739 op.u.bind_interdomain.remote_dom = blkif->domid; 740 op.u.bind_interdomain.remote_port = evtchn; 741 err = HYPERVISOR_event_channel_op(&op); 742 if (err) { 743 unmap_ring(&blkif->rr); 744 xenbus_dev_fatal(xdev, err, "binding event channel"); 745 return err; 746 } 747 blkif->evtchn = op.u.bind_interdomain.local_port; 748 749 /* bind evtchn to irq handler */ 750 blkif->irq = 751 bind_evtchn_to_irqhandler(blkif->evtchn, "blkback", 752 blkback_intr, blkif, INTR_TYPE_NET|INTR_MPSAFE, &blkif->irq_cookie); 753 754 blkif->ring_connected = 1; 755 756 DPRINTF("%x rings connected! evtchn=%d irq=%d\n", 757 (unsigned int)blkif, blkif->evtchn, blkif->irq); 758 759 return 0; 760 } 761 762 static void 763 disconnect_ring(blkif_t *blkif) 764 { 765 DPRINTF("\n"); 766 767 if (blkif->ring_connected) { 768 unbind_from_irqhandler(blkif->irq, blkif->irq_cookie); 769 blkif->irq = 0; 770 unmap_ring(&blkif->rr); 771 blkif->ring_connected = 0; 772 } 773 } 774 775 static void 776 connect(blkif_t *blkif) 777 { 778 struct xenbus_transaction *xbt; 779 struct xenbus_device *xdev = blkif->xdev; 780 int err; 781 782 if (!blkif->ring_connected || 783 blkif->vn == NULL || 784 blkif->state == XenbusStateConnected) 785 return; 786 787 DPRINTF("%s\n", xdev->otherend); 788 789 /* Supply the information about the device the frontend needs */ 790 again: 791 xbt = xenbus_transaction_start(); 792 if (IS_ERR(xbt)) { 793 xenbus_dev_fatal(xdev, PTR_ERR(xbt), 794 "Error writing configuration for backend " 795 "(start transaction)"); 796 return; 797 } 798 799 err = xenbus_printf(xbt, xdev->nodename, "sectors", "%u", 800 blkif->media_num_sectors); 801 if (err) { 802 xenbus_dev_fatal(xdev, err, "writing %s/sectors", 803 xdev->nodename); 804 goto abort; 805 } 806 807 err = xenbus_printf(xbt, xdev->nodename, "info", "%u", 808 blkif->read_only ? VDISK_READONLY : 0); 809 if (err) { 810 xenbus_dev_fatal(xdev, err, "writing %s/info", 811 xdev->nodename); 812 goto abort; 813 } 814 err = xenbus_printf(xbt, xdev->nodename, "sector-size", "%u", 815 blkif->sector_size); 816 if (err) { 817 xenbus_dev_fatal(xdev, err, "writing %s/sector-size", 818 xdev->nodename); 819 goto abort; 820 } 821 822 err = xenbus_transaction_end(xbt, 0); 823 if (err == -EAGAIN) 824 goto again; 825 if (err) 826 xenbus_dev_fatal(xdev, err, "ending transaction"); 827 828 err = xenbus_switch_state(xdev, NULL, XenbusStateConnected); 829 if (err) 830 xenbus_dev_fatal(xdev, err, "switching to Connected state", 831 xdev->nodename); 832 833 blkif->state = XenbusStateConnected; 834 835 return; 836 837 abort: 838 xenbus_transaction_end(xbt, 1); 839 } 840 841 static int 842 blkback_probe(struct xenbus_device *xdev, const struct xenbus_device_id *id) 843 { 844 int err; 845 char *p, *mode = NULL, *type = NULL, *params = NULL; 846 long handle; 847 848 DPRINTF("node=%s\n", xdev->nodename); 849 850 p = strrchr(xdev->otherend, '/') + 1; 851 handle = strtoul(p, NULL, 0); 852 853 mode = xenbus_read(NULL, xdev->nodename, "mode", NULL); 854 if (IS_ERR(mode)) { 855 xenbus_dev_fatal(xdev, PTR_ERR(mode), "reading mode"); 856 err = PTR_ERR(mode); 857 goto error; 858 } 859 860 type = xenbus_read(NULL, xdev->nodename, "type", NULL); 861 if (IS_ERR(type)) { 862 xenbus_dev_fatal(xdev, PTR_ERR(type), "reading type"); 863 err = PTR_ERR(type); 864 goto error; 865 } 866 867 params = xenbus_read(NULL, xdev->nodename, "params", NULL); 868 if (IS_ERR(type)) { 869 xenbus_dev_fatal(xdev, PTR_ERR(params), "reading params"); 870 err = PTR_ERR(params); 871 goto error; 872 } 873 874 err = blkif_create(xdev, handle, mode, type, params); 875 if (err) { 876 xenbus_dev_fatal(xdev, err, "creating blkif"); 877 goto error; 878 } 879 880 err = vbd_add_dev(xdev); 881 if (err) { 882 blkif_put((blkif_t *)xdev->data); 883 xenbus_dev_fatal(xdev, err, "adding vbd device"); 884 } 885 886 return err; 887 888 error: 889 if (mode) 890 free(mode, M_DEVBUF); 891 if (type) 892 free(type, M_DEVBUF); 893 if (params) 894 free(params, M_DEVBUF); 895 return err; 896 } 897 898 static int 899 blkback_remove(struct xenbus_device *xdev) 900 { 901 blkif_t *blkif = xdev->data; 902 device_t ndev; 903 904 DPRINTF("node=%s\n", xdev->nodename); 905 906 blkif->state = XenbusStateClosing; 907 908 if ((ndev = blkif->ndev)) { 909 blkif->ndev = NULL; 910 mtx_lock(&Giant); 911 device_detach(ndev); 912 mtx_unlock(&Giant); 913 } 914 915 xdev->data = NULL; 916 blkif->xdev = NULL; 917 blkif_put(blkif); 918 919 return 0; 920 } 921 922 static int 923 blkback_resume(struct xenbus_device *xdev) 924 { 925 DPRINTF("node=%s\n", xdev->nodename); 926 return 0; 927 } 928 929 static void 930 frontend_changed(struct xenbus_device *xdev, 931 XenbusState frontend_state) 932 { 933 blkif_t *blkif = xdev->data; 934 935 DPRINTF("state=%d\n", frontend_state); 936 937 blkif->frontend_state = frontend_state; 938 939 switch (frontend_state) { 940 case XenbusStateInitialising: 941 break; 942 case XenbusStateInitialised: 943 case XenbusStateConnected: 944 connect_ring(blkif); 945 connect(blkif); 946 break; 947 case XenbusStateClosing: 948 xenbus_switch_state(xdev, NULL, XenbusStateClosing); 949 break; 950 case XenbusStateClosed: 951 xenbus_remove_device(xdev); 952 break; 953 case XenbusStateUnknown: 954 case XenbusStateInitWait: 955 xenbus_dev_fatal(xdev, EINVAL, "saw state %d at frontend", 956 frontend_state); 957 break; 958 } 959 } 960 961 /* ** Driver registration ** */ 962 963 static struct xenbus_device_id blkback_ids[] = { 964 { "vbd" }, 965 { "" } 966 }; 967 968 static struct xenbus_driver blkback = { 969 .name = "blkback", 970 .ids = blkback_ids, 971 .probe = blkback_probe, 972 .remove = blkback_remove, 973 .resume = blkback_resume, 974 .otherend_changed = frontend_changed, 975 }; 976 977 static void 978 blkback_init(void *unused) 979 { 980 int i; 981 982 TASK_INIT(&blk_req_task, 0, blk_req_action, NULL); 983 mtx_init(&req_sched_list_lock, "blk_req_sched_lock", "blkback req sched lock", MTX_DEF); 984 985 mtx_init(&pending_free_lock, "blk_pending_req_ock", "blkback pending request lock", MTX_DEF); 986 987 mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; 988 pending_reqs = malloc(sizeof(pending_reqs[0]) * 989 blkif_reqs, M_DEVBUF, M_ZERO|M_NOWAIT); 990 pending_grant_handles = malloc(sizeof(pending_grant_handles[0]) * 991 mmap_pages, M_DEVBUF, M_NOWAIT); 992 pending_vaddrs = malloc(sizeof(pending_vaddrs[0]) * 993 mmap_pages, M_DEVBUF, M_NOWAIT); 994 mmap_vstart = alloc_empty_page_range(mmap_pages); 995 if (!pending_reqs || !pending_grant_handles || !pending_vaddrs || !mmap_vstart) { 996 if (pending_reqs) 997 free(pending_reqs, M_DEVBUF); 998 if (pending_grant_handles) 999 free(pending_grant_handles, M_DEVBUF); 1000 if (pending_vaddrs) 1001 free(pending_vaddrs, M_DEVBUF); 1002 WPRINTF("out of memory\n"); 1003 return; 1004 } 1005 1006 for (i = 0; i < mmap_pages; i++) { 1007 pending_vaddrs[i] = mmap_vstart + (i << PAGE_SHIFT); 1008 pending_grant_handles[i] = BLKBACK_INVALID_HANDLE; 1009 } 1010 1011 for (i = 0; i < blkif_reqs; i++) { 1012 STAILQ_INSERT_TAIL(&pending_free, &pending_reqs[i], free_list); 1013 } 1014 1015 DPRINTF("registering %s\n", blkback.name); 1016 xenbus_register_backend(&blkback); 1017 } 1018 1019 SYSINIT(xbbedev, SI_SUB_PSEUDO, SI_ORDER_ANY, blkback_init, NULL) 1020 1021 static void 1022 close_device(blkif_t *blkif) 1023 { 1024 DPRINTF("closing dev=%s\n", blkif->dev_name); 1025 if (blkif->vn) { 1026 int flags = FREAD; 1027 1028 if (!blkif->read_only) 1029 flags |= FWRITE; 1030 1031 if (blkif->csw) { 1032 dev_relthread(blkif->cdev); 1033 blkif->csw = NULL; 1034 } 1035 1036 (void)vn_close(blkif->vn, flags, NOCRED, curthread); 1037 blkif->vn = NULL; 1038 } 1039 } 1040 1041 static int 1042 open_device(blkif_t *blkif) 1043 { 1044 struct nameidata nd; 1045 struct vattr vattr; 1046 struct cdev *dev; 1047 struct cdevsw *devsw; 1048 int flags = FREAD, err = 0; 1049 1050 DPRINTF("opening dev=%s\n", blkif->dev_name); 1051 1052 if (!blkif->read_only) 1053 flags |= FWRITE; 1054 1055 if (!curthread->td_proc->p_fd->fd_cdir) { 1056 curthread->td_proc->p_fd->fd_cdir = rootvnode; 1057 VREF(rootvnode); 1058 } 1059 if (!curthread->td_proc->p_fd->fd_rdir) { 1060 curthread->td_proc->p_fd->fd_rdir = rootvnode; 1061 VREF(rootvnode); 1062 } 1063 if (!curthread->td_proc->p_fd->fd_jdir) { 1064 curthread->td_proc->p_fd->fd_jdir = rootvnode; 1065 VREF(rootvnode); 1066 } 1067 1068 again: 1069 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, blkif->dev_name, curthread); 1070 err = vn_open(&nd, &flags, 0, -1); 1071 if (err) { 1072 if (blkif->dev_name[0] != '/') { 1073 char *dev_path = "/dev/"; 1074 char *dev_name; 1075 1076 /* Try adding device path at beginning of name */ 1077 dev_name = malloc(strlen(blkif->dev_name) + strlen(dev_path) + 1, M_DEVBUF, M_NOWAIT); 1078 if (dev_name) { 1079 sprintf(dev_name, "%s%s", dev_path, blkif->dev_name); 1080 free(blkif->dev_name, M_DEVBUF); 1081 blkif->dev_name = dev_name; 1082 goto again; 1083 } 1084 } 1085 xenbus_dev_fatal(blkif->xdev, err, "error opening device %s", blkif->dev_name); 1086 return err; 1087 } 1088 NDFREE(&nd, NDF_ONLY_PNBUF); 1089 1090 blkif->vn = nd.ni_vp; 1091 1092 /* We only support disks for now */ 1093 if (!vn_isdisk(blkif->vn, &err)) { 1094 xenbus_dev_fatal(blkif->xdev, err, "device %s is not a disk", blkif->dev_name); 1095 VOP_UNLOCK(blkif->vn, 0, curthread); 1096 goto error; 1097 } 1098 1099 blkif->cdev = blkif->vn->v_rdev; 1100 blkif->csw = dev_refthread(blkif->cdev); 1101 PANIC_IF(blkif->csw == NULL); 1102 1103 err = VOP_GETATTR(blkif->vn, &vattr, NOCRED); 1104 if (err) { 1105 xenbus_dev_fatal(blkif->xdev, err, 1106 "error getting vnode attributes for device %s", blkif->dev_name); 1107 VOP_UNLOCK(blkif->vn, 0, curthread); 1108 goto error; 1109 } 1110 1111 VOP_UNLOCK(blkif->vn, 0, curthread); 1112 1113 dev = blkif->vn->v_rdev; 1114 devsw = dev->si_devsw; 1115 if (!devsw->d_ioctl) { 1116 err = ENODEV; 1117 xenbus_dev_fatal(blkif->xdev, err, 1118 "no d_ioctl for device %s!", blkif->dev_name); 1119 goto error; 1120 } 1121 1122 err = (*devsw->d_ioctl)(dev, DIOCGSECTORSIZE, (caddr_t)&blkif->sector_size, FREAD, curthread); 1123 if (err) { 1124 xenbus_dev_fatal(blkif->xdev, err, 1125 "error calling ioctl DIOCGSECTORSIZE for device %s", blkif->dev_name); 1126 goto error; 1127 } 1128 blkif->sector_size_shift = fls(blkif->sector_size) - 1; 1129 1130 err = (*devsw->d_ioctl)(dev, DIOCGMEDIASIZE, (caddr_t)&blkif->media_size, FREAD, curthread); 1131 if (err) { 1132 xenbus_dev_fatal(blkif->xdev, err, 1133 "error calling ioctl DIOCGMEDIASIZE for device %s", blkif->dev_name); 1134 goto error; 1135 } 1136 blkif->media_num_sectors = blkif->media_size >> blkif->sector_size_shift; 1137 1138 blkif->major = major(vattr.va_rdev); 1139 blkif->minor = minor(vattr.va_rdev); 1140 1141 DPRINTF("opened dev=%s major=%d minor=%d sector_size=%u media_size=%lld\n", 1142 blkif->dev_name, blkif->major, blkif->minor, blkif->sector_size, blkif->media_size); 1143 1144 return 0; 1145 1146 error: 1147 close_device(blkif); 1148 return err; 1149 } 1150 1151 static int 1152 vbd_add_dev(struct xenbus_device *xdev) 1153 { 1154 blkif_t *blkif = xdev->data; 1155 device_t nexus, ndev; 1156 devclass_t dc; 1157 int err = 0; 1158 1159 mtx_lock(&Giant); 1160 1161 /* We will add a vbd device as a child of nexus0 (for now) */ 1162 if (!(dc = devclass_find("nexus")) || 1163 !(nexus = devclass_get_device(dc, 0))) { 1164 WPRINTF("could not find nexus0!\n"); 1165 err = ENOENT; 1166 goto done; 1167 } 1168 1169 1170 /* Create a newbus device representing the vbd */ 1171 ndev = BUS_ADD_CHILD(nexus, 0, "vbd", blkif->handle); 1172 if (!ndev) { 1173 WPRINTF("could not create newbus device vbd%d!\n", blkif->handle); 1174 err = EFAULT; 1175 goto done; 1176 } 1177 1178 blkif_get(blkif); 1179 device_set_ivars(ndev, blkif); 1180 blkif->ndev = ndev; 1181 1182 device_probe_and_attach(ndev); 1183 1184 done: 1185 1186 mtx_unlock(&Giant); 1187 1188 return err; 1189 } 1190 1191 enum { 1192 VBD_SYSCTL_DOMID, 1193 VBD_SYSCTL_ST_RD_REQ, 1194 VBD_SYSCTL_ST_WR_REQ, 1195 VBD_SYSCTL_ST_OO_REQ, 1196 VBD_SYSCTL_ST_ERR_REQ, 1197 VBD_SYSCTL_RING, 1198 }; 1199 1200 static char * 1201 vbd_sysctl_ring_info(blkif_t *blkif, int cmd) 1202 { 1203 char *buf = malloc(256, M_DEVBUF, M_WAITOK); 1204 if (buf) { 1205 if (!blkif->ring_connected) 1206 sprintf(buf, "ring not connected\n"); 1207 else { 1208 blkif_back_ring_t *ring = &blkif->ring; 1209 sprintf(buf, "nr_ents=%x req_cons=%x" 1210 " req_prod=%x req_event=%x" 1211 " rsp_prod=%x rsp_event=%x", 1212 ring->nr_ents, ring->req_cons, 1213 ring->sring->req_prod, ring->sring->req_event, 1214 ring->sring->rsp_prod, ring->sring->rsp_event); 1215 } 1216 } 1217 return buf; 1218 } 1219 1220 static int 1221 vbd_sysctl_handler(SYSCTL_HANDLER_ARGS) 1222 { 1223 device_t dev = (device_t)arg1; 1224 blkif_t *blkif = (blkif_t *)device_get_ivars(dev); 1225 const char *value; 1226 char *buf = NULL; 1227 int err; 1228 1229 switch (arg2) { 1230 case VBD_SYSCTL_DOMID: 1231 return sysctl_handle_int(oidp, NULL, blkif->domid, req); 1232 case VBD_SYSCTL_ST_RD_REQ: 1233 return sysctl_handle_int(oidp, NULL, blkif->st_rd_req, req); 1234 case VBD_SYSCTL_ST_WR_REQ: 1235 return sysctl_handle_int(oidp, NULL, blkif->st_wr_req, req); 1236 case VBD_SYSCTL_ST_OO_REQ: 1237 return sysctl_handle_int(oidp, NULL, blkif->st_oo_req, req); 1238 case VBD_SYSCTL_ST_ERR_REQ: 1239 return sysctl_handle_int(oidp, NULL, blkif->st_err_req, req); 1240 case VBD_SYSCTL_RING: 1241 value = buf = vbd_sysctl_ring_info(blkif, arg2); 1242 break; 1243 default: 1244 return (EINVAL); 1245 } 1246 1247 err = SYSCTL_OUT(req, value, strlen(value)); 1248 if (buf != NULL) 1249 free(buf, M_DEVBUF); 1250 1251 return err; 1252 } 1253 1254 /* Newbus vbd device driver probe */ 1255 static int 1256 vbd_probe(device_t dev) 1257 { 1258 DPRINTF("vbd%d\n", device_get_unit(dev)); 1259 return 0; 1260 } 1261 1262 /* Newbus vbd device driver attach */ 1263 static int 1264 vbd_attach(device_t dev) 1265 { 1266 blkif_t *blkif = (blkif_t *)device_get_ivars(dev); 1267 1268 DPRINTF("%s\n", blkif->dev_name); 1269 1270 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1271 OID_AUTO, "domid", CTLTYPE_INT|CTLFLAG_RD, 1272 dev, VBD_SYSCTL_DOMID, vbd_sysctl_handler, "I", 1273 "domid of frontend"); 1274 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1275 OID_AUTO, "rd_reqs", CTLTYPE_INT|CTLFLAG_RD, 1276 dev, VBD_SYSCTL_ST_RD_REQ, vbd_sysctl_handler, "I", 1277 "number of read reqs"); 1278 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1279 OID_AUTO, "wr_reqs", CTLTYPE_INT|CTLFLAG_RD, 1280 dev, VBD_SYSCTL_ST_WR_REQ, vbd_sysctl_handler, "I", 1281 "number of write reqs"); 1282 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1283 OID_AUTO, "oo_reqs", CTLTYPE_INT|CTLFLAG_RD, 1284 dev, VBD_SYSCTL_ST_OO_REQ, vbd_sysctl_handler, "I", 1285 "number of deferred reqs"); 1286 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1287 OID_AUTO, "err_reqs", CTLTYPE_INT|CTLFLAG_RD, 1288 dev, VBD_SYSCTL_ST_ERR_REQ, vbd_sysctl_handler, "I", 1289 "number of reqs that returned error"); 1290 #if XEN_BLKBACK_DEBUG 1291 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1292 OID_AUTO, "ring", CTLFLAG_RD, 1293 dev, VBD_SYSCTL_RING, vbd_sysctl_handler, "A", 1294 "req ring info"); 1295 #endif 1296 1297 if (!open_device(blkif)) 1298 connect(blkif); 1299 1300 return bus_generic_attach(dev); 1301 } 1302 1303 /* Newbus vbd device driver detach */ 1304 static int 1305 vbd_detach(device_t dev) 1306 { 1307 blkif_t *blkif = (blkif_t *)device_get_ivars(dev); 1308 1309 DPRINTF("%s\n", blkif->dev_name); 1310 1311 close_device(blkif); 1312 1313 bus_generic_detach(dev); 1314 1315 blkif_put(blkif); 1316 1317 return 0; 1318 } 1319 1320 static device_method_t vbd_methods[] = { 1321 /* Device interface */ 1322 DEVMETHOD(device_probe, vbd_probe), 1323 DEVMETHOD(device_attach, vbd_attach), 1324 DEVMETHOD(device_detach, vbd_detach), 1325 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1326 DEVMETHOD(device_suspend, bus_generic_suspend), 1327 DEVMETHOD(device_resume, bus_generic_resume), 1328 {0, 0} 1329 }; 1330 1331 static devclass_t vbd_devclass; 1332 1333 static driver_t vbd_driver = { 1334 "vbd", 1335 vbd_methods, 1336 0, 1337 }; 1338 1339 DRIVER_MODULE(vbd, nexus, vbd_driver, vbd_devclass, 0, 0); 1340 1341 /* 1342 * Local variables: 1343 * mode: C 1344 * c-set-style: "BSD" 1345 * c-basic-offset: 4 1346 * tab-width: 4 1347 * indent-tabs-mode: t 1348 * End: 1349 */ 1350