1 /* $NetBSD: vnd.c,v 1.242 2015/04/06 12:02:08 mlelstv Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1988 University of Utah. 34 * Copyright (c) 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * from: Utah $Hdr: vn.c 1.13 94/04/02$ 66 * 67 * @(#)vn.c 8.9 (Berkeley) 5/14/95 68 */ 69 70 /* 71 * Vnode disk driver. 72 * 73 * Block/character interface to a vnode. Allows one to treat a file 74 * as a disk (e.g. build a filesystem in it, mount it, etc.). 75 * 76 * NOTE 1: If the vnode supports the VOP_BMAP and VOP_STRATEGY operations, 77 * this uses them to avoid distorting the local buffer cache. If those 78 * block-level operations are not available, this falls back to the regular 79 * read and write calls. Using these may distort the cache in some cases 80 * but better have the driver working than preventing it to work on file 81 * systems where the block-level operations are not implemented for 82 * whatever reason. 83 * 84 * NOTE 2: There is a security issue involved with this driver. 85 * Once mounted all access to the contents of the "mapped" file via 86 * the special file is controlled by the permissions on the special 87 * file, the protection of the mapped file is ignored (effectively, 88 * by using root credentials in all transactions). 89 * 90 * NOTE 3: Doesn't interact with leases, should it? 91 */ 92 93 #include <sys/cdefs.h> 94 __KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.242 2015/04/06 12:02:08 mlelstv Exp $"); 95 96 #if defined(_KERNEL_OPT) 97 #include "opt_vnd.h" 98 #include "opt_compat_netbsd.h" 99 #endif 100 101 #include <sys/param.h> 102 #include <sys/systm.h> 103 #include <sys/namei.h> 104 #include <sys/proc.h> 105 #include <sys/kthread.h> 106 #include <sys/errno.h> 107 #include <sys/buf.h> 108 #include <sys/bufq.h> 109 #include <sys/malloc.h> 110 #include <sys/ioctl.h> 111 #include <sys/disklabel.h> 112 #include <sys/device.h> 113 #include <sys/disk.h> 114 #include <sys/stat.h> 115 #include <sys/mount.h> 116 #include <sys/vnode.h> 117 #include <sys/file.h> 118 #include <sys/uio.h> 119 #include <sys/conf.h> 120 #include <sys/kauth.h> 121 122 #include <net/zlib.h> 123 124 #include <miscfs/genfs/genfs.h> 125 #include <miscfs/specfs/specdev.h> 126 127 #include <dev/dkvar.h> 128 #include <dev/vndvar.h> 129 130 #if defined(VNDDEBUG) && !defined(DEBUG) 131 #define DEBUG 132 #endif 133 134 #ifdef DEBUG 135 int dovndcluster = 1; 136 #define VDB_FOLLOW 0x01 137 #define VDB_INIT 0x02 138 #define VDB_IO 0x04 139 #define VDB_LABEL 0x08 140 int vnddebug = 0x00; 141 #endif 142 143 #define vndunit(x) DISKUNIT(x) 144 145 struct vndxfer { 146 struct buf vx_buf; 147 struct vnd_softc *vx_vnd; 148 }; 149 #define VND_BUFTOXFER(bp) ((struct vndxfer *)(void *)bp) 150 151 #define VND_GETXFER(vnd) pool_get(&(vnd)->sc_vxpool, PR_WAITOK) 152 #define VND_PUTXFER(vnd, vx) pool_put(&(vnd)->sc_vxpool, (vx)) 153 154 #define VNDLABELDEV(dev) \ 155 (MAKEDISKDEV(major((dev)), vndunit((dev)), RAW_PART)) 156 157 #define VND_MAXPENDING(vnd) ((vnd)->sc_maxactive * 4) 158 159 /* called by main() at boot time */ 160 void vndattach(int); 161 162 static void vndclear(struct vnd_softc *, int); 163 static int vnddoclear(struct vnd_softc *, int, int, bool); 164 static int vndsetcred(struct vnd_softc *, kauth_cred_t); 165 static void vndthrottle(struct vnd_softc *, struct vnode *); 166 static void vndiodone(struct buf *); 167 #if 0 168 static void vndshutdown(void); 169 #endif 170 171 static void vndgetdefaultlabel(struct vnd_softc *, struct disklabel *); 172 static void vndgetdisklabel(dev_t, struct vnd_softc *); 173 174 static int vndlock(struct vnd_softc *); 175 static void vndunlock(struct vnd_softc *); 176 #ifdef VND_COMPRESSION 177 static void compstrategy(struct buf *, off_t); 178 static void *vnd_alloc(void *, u_int, u_int); 179 static void vnd_free(void *, void *); 180 #endif /* VND_COMPRESSION */ 181 182 static void vndthread(void *); 183 static bool vnode_has_op(const struct vnode *, int); 184 static void handle_with_rdwr(struct vnd_softc *, const struct buf *, 185 struct buf *); 186 static void handle_with_strategy(struct vnd_softc *, const struct buf *, 187 struct buf *); 188 static void vnd_set_geometry(struct vnd_softc *); 189 190 static dev_type_open(vndopen); 191 static dev_type_close(vndclose); 192 static dev_type_read(vndread); 193 static dev_type_write(vndwrite); 194 static dev_type_ioctl(vndioctl); 195 static dev_type_strategy(vndstrategy); 196 static dev_type_dump(vnddump); 197 static dev_type_size(vndsize); 198 199 const struct bdevsw vnd_bdevsw = { 200 .d_open = vndopen, 201 .d_close = vndclose, 202 .d_strategy = vndstrategy, 203 .d_ioctl = vndioctl, 204 .d_dump = vnddump, 205 .d_psize = vndsize, 206 .d_discard = nodiscard, 207 .d_flag = D_DISK 208 }; 209 210 const struct cdevsw vnd_cdevsw = { 211 .d_open = vndopen, 212 .d_close = vndclose, 213 .d_read = vndread, 214 .d_write = vndwrite, 215 .d_ioctl = vndioctl, 216 .d_stop = nostop, 217 .d_tty = notty, 218 .d_poll = nopoll, 219 .d_mmap = nommap, 220 .d_kqfilter = nokqfilter, 221 .d_discard = nodiscard, 222 .d_flag = D_DISK 223 }; 224 225 static int vnd_match(device_t, cfdata_t, void *); 226 static void vnd_attach(device_t, device_t, void *); 227 static int vnd_detach(device_t, int); 228 229 CFATTACH_DECL3_NEW(vnd, sizeof(struct vnd_softc), 230 vnd_match, vnd_attach, vnd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 231 extern struct cfdriver vnd_cd; 232 233 static struct vnd_softc *vnd_spawn(int); 234 int vnd_destroy(device_t); 235 236 static struct dkdriver vnddkdriver = { vndstrategy, minphys }; 237 238 void 239 vndattach(int num) 240 { 241 int error; 242 243 error = config_cfattach_attach(vnd_cd.cd_name, &vnd_ca); 244 if (error) 245 aprint_error("%s: unable to register cfattach\n", 246 vnd_cd.cd_name); 247 } 248 249 static int 250 vnd_match(device_t self, cfdata_t cfdata, void *aux) 251 { 252 253 return 1; 254 } 255 256 static void 257 vnd_attach(device_t parent, device_t self, void *aux) 258 { 259 struct vnd_softc *sc = device_private(self); 260 261 sc->sc_dev = self; 262 sc->sc_comp_offsets = NULL; 263 sc->sc_comp_buff = NULL; 264 sc->sc_comp_decombuf = NULL; 265 bufq_alloc(&sc->sc_tab, "disksort", BUFQ_SORT_RAWBLOCK); 266 disk_init(&sc->sc_dkdev, device_xname(self), &vnddkdriver); 267 if (!pmf_device_register(self, NULL, NULL)) 268 aprint_error_dev(self, "couldn't establish power handler\n"); 269 } 270 271 static int 272 vnd_detach(device_t self, int flags) 273 { 274 int error; 275 struct vnd_softc *sc = device_private(self); 276 277 if (sc->sc_flags & VNF_INITED) { 278 error = vnddoclear(sc, 0, -1, (flags & DETACH_FORCE) != 0); 279 if (error != 0) 280 return error; 281 } 282 283 pmf_device_deregister(self); 284 bufq_free(sc->sc_tab); 285 disk_destroy(&sc->sc_dkdev); 286 287 return 0; 288 } 289 290 static struct vnd_softc * 291 vnd_spawn(int unit) 292 { 293 cfdata_t cf; 294 295 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK); 296 cf->cf_name = vnd_cd.cd_name; 297 cf->cf_atname = vnd_cd.cd_name; 298 cf->cf_unit = unit; 299 cf->cf_fstate = FSTATE_STAR; 300 301 return device_private(config_attach_pseudo(cf)); 302 } 303 304 int 305 vnd_destroy(device_t dev) 306 { 307 int error; 308 cfdata_t cf; 309 310 cf = device_cfdata(dev); 311 error = config_detach(dev, DETACH_QUIET); 312 if (error) 313 return error; 314 free(cf, M_DEVBUF); 315 return 0; 316 } 317 318 static int 319 vndopen(dev_t dev, int flags, int mode, struct lwp *l) 320 { 321 int unit = vndunit(dev); 322 struct vnd_softc *sc; 323 int error = 0, part, pmask; 324 struct disklabel *lp; 325 326 #ifdef DEBUG 327 if (vnddebug & VDB_FOLLOW) 328 printf("vndopen(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l); 329 #endif 330 sc = device_lookup_private(&vnd_cd, unit); 331 if (sc == NULL) { 332 sc = vnd_spawn(unit); 333 if (sc == NULL) 334 return ENOMEM; 335 336 /* compatibility, keep disklabel after close */ 337 sc->sc_flags = VNF_KLABEL; 338 } 339 340 if ((error = vndlock(sc)) != 0) 341 return error; 342 343 if ((sc->sc_flags & VNF_CLEARING) != 0) { 344 error = ENXIO; 345 goto done; 346 } 347 348 lp = sc->sc_dkdev.dk_label; 349 350 part = DISKPART(dev); 351 pmask = (1 << part); 352 353 if (sc->sc_dkdev.dk_nwedges != 0 && part != RAW_PART) { 354 error = EBUSY; 355 goto done; 356 } 357 358 if (sc->sc_flags & VNF_INITED) { 359 if ((sc->sc_dkdev.dk_openmask & ~(1<<RAW_PART)) != 0) { 360 /* 361 * If any non-raw partition is open, but the disk 362 * has been invalidated, disallow further opens. 363 */ 364 if ((sc->sc_flags & VNF_VLABEL) == 0) { 365 error = EIO; 366 goto done; 367 } 368 } else { 369 /* 370 * Load the partition info if not already loaded. 371 */ 372 if ((sc->sc_flags & VNF_VLABEL) == 0) { 373 sc->sc_flags |= VNF_VLABEL; 374 vndgetdisklabel(dev, sc); 375 } 376 } 377 } 378 379 /* Check that the partitions exists. */ 380 if (part != RAW_PART) { 381 if (((sc->sc_flags & VNF_INITED) == 0) || 382 ((part >= lp->d_npartitions) || 383 (lp->d_partitions[part].p_fstype == FS_UNUSED))) { 384 error = ENXIO; 385 goto done; 386 } 387 } 388 389 /* Prevent our unit from being unconfigured while open. */ 390 switch (mode) { 391 case S_IFCHR: 392 sc->sc_dkdev.dk_copenmask |= pmask; 393 break; 394 395 case S_IFBLK: 396 sc->sc_dkdev.dk_bopenmask |= pmask; 397 break; 398 } 399 sc->sc_dkdev.dk_openmask = 400 sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask; 401 402 done: 403 vndunlock(sc); 404 return error; 405 } 406 407 static int 408 vndclose(dev_t dev, int flags, int mode, struct lwp *l) 409 { 410 int unit = vndunit(dev); 411 struct vnd_softc *sc; 412 int error = 0, part; 413 414 #ifdef DEBUG 415 if (vnddebug & VDB_FOLLOW) 416 printf("vndclose(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l); 417 #endif 418 sc = device_lookup_private(&vnd_cd, unit); 419 if (sc == NULL) 420 return ENXIO; 421 422 if ((error = vndlock(sc)) != 0) 423 return error; 424 425 part = DISKPART(dev); 426 427 /* ...that much closer to allowing unconfiguration... */ 428 switch (mode) { 429 case S_IFCHR: 430 sc->sc_dkdev.dk_copenmask &= ~(1 << part); 431 break; 432 433 case S_IFBLK: 434 sc->sc_dkdev.dk_bopenmask &= ~(1 << part); 435 break; 436 } 437 sc->sc_dkdev.dk_openmask = 438 sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask; 439 440 /* are we last opener ? */ 441 if (sc->sc_dkdev.dk_openmask == 0) { 442 if ((sc->sc_flags & VNF_KLABEL) == 0) 443 sc->sc_flags &= ~VNF_VLABEL; 444 } 445 446 vndunlock(sc); 447 448 if ((sc->sc_flags & VNF_INITED) == 0) { 449 if ((error = vnd_destroy(sc->sc_dev)) != 0) { 450 aprint_error_dev(sc->sc_dev, 451 "unable to detach instance\n"); 452 return error; 453 } 454 } 455 456 return 0; 457 } 458 459 /* 460 * Queue the request, and wakeup the kernel thread to handle it. 461 */ 462 static void 463 vndstrategy(struct buf *bp) 464 { 465 int unit = vndunit(bp->b_dev); 466 struct vnd_softc *vnd = 467 device_lookup_private(&vnd_cd, unit); 468 struct disklabel *lp; 469 daddr_t blkno; 470 int s = splbio(); 471 472 if (vnd == NULL) { 473 bp->b_error = ENXIO; 474 goto done; 475 } 476 lp = vnd->sc_dkdev.dk_label; 477 478 if ((vnd->sc_flags & VNF_INITED) == 0) { 479 bp->b_error = ENXIO; 480 goto done; 481 } 482 483 /* 484 * The transfer must be a whole number of blocks. 485 */ 486 if ((bp->b_bcount % lp->d_secsize) != 0) { 487 bp->b_error = EINVAL; 488 goto done; 489 } 490 491 /* 492 * check if we're read-only. 493 */ 494 if ((vnd->sc_flags & VNF_READONLY) && !(bp->b_flags & B_READ)) { 495 bp->b_error = EACCES; 496 goto done; 497 } 498 499 /* If it's a nil transfer, wake up the top half now. */ 500 if (bp->b_bcount == 0) { 501 goto done; 502 } 503 504 /* 505 * Do bounds checking and adjust transfer. If there's an error, 506 * the bounds check will flag that for us. 507 */ 508 if (DISKPART(bp->b_dev) == RAW_PART) { 509 if (bounds_check_with_mediasize(bp, DEV_BSIZE, 510 vnd->sc_size) <= 0) 511 goto done; 512 } else { 513 if (bounds_check_with_label(&vnd->sc_dkdev, 514 bp, vnd->sc_flags & (VNF_WLABEL|VNF_LABELLING)) <= 0) 515 goto done; 516 } 517 518 /* 519 * Put the block number in terms of the logical blocksize 520 * of the "device". 521 */ 522 523 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 524 525 /* 526 * Translate the partition-relative block number to an absolute. 527 */ 528 if (DISKPART(bp->b_dev) != RAW_PART) { 529 struct partition *pp; 530 531 pp = &vnd->sc_dkdev.dk_label->d_partitions[ 532 DISKPART(bp->b_dev)]; 533 blkno += pp->p_offset; 534 } 535 bp->b_rawblkno = blkno; 536 537 #ifdef DEBUG 538 if (vnddebug & VDB_FOLLOW) 539 printf("vndstrategy(%p): unit %d\n", bp, unit); 540 #endif 541 if ((vnd->sc_flags & VNF_USE_VN_RDWR)) { 542 KASSERT(vnd->sc_pending >= 0 && 543 vnd->sc_pending <= VND_MAXPENDING(vnd)); 544 while (vnd->sc_pending == VND_MAXPENDING(vnd)) 545 tsleep(&vnd->sc_pending, PRIBIO, "vndpc", 0); 546 vnd->sc_pending++; 547 } 548 bufq_put(vnd->sc_tab, bp); 549 wakeup(&vnd->sc_tab); 550 splx(s); 551 return; 552 553 done: 554 bp->b_resid = bp->b_bcount; 555 biodone(bp); 556 splx(s); 557 } 558 559 static bool 560 vnode_has_strategy(struct vnd_softc *vnd) 561 { 562 return vnode_has_op(vnd->sc_vp, VOFFSET(vop_bmap)) && 563 vnode_has_op(vnd->sc_vp, VOFFSET(vop_strategy)); 564 } 565 566 /* XXX this function needs a reliable check to detect 567 * sparse files. Otherwise, bmap/strategy may be used 568 * and fail on non-allocated blocks. VOP_READ/VOP_WRITE 569 * works on sparse files. 570 */ 571 #if notyet 572 static bool 573 vnode_strategy_probe(struct vnd_softc *vnd) 574 { 575 int error; 576 daddr_t nbn; 577 578 if (!vnode_has_strategy(vnd)) 579 return false; 580 581 /* Convert the first logical block number to its 582 * physical block number. 583 */ 584 error = 0; 585 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 586 error = VOP_BMAP(vnd->sc_vp, 0, NULL, &nbn, NULL); 587 VOP_UNLOCK(vnd->sc_vp); 588 589 /* Test if that worked. */ 590 if (error == 0 && (long)nbn == -1) 591 return false; 592 593 return true; 594 } 595 #endif 596 597 static void 598 vndthread(void *arg) 599 { 600 struct vnd_softc *vnd = arg; 601 int s; 602 603 /* Determine whether we can *use* VOP_BMAP and VOP_STRATEGY to 604 * directly access the backing vnode. If we can, use these two 605 * operations to avoid messing with the local buffer cache. 606 * Otherwise fall back to regular VOP_READ/VOP_WRITE operations 607 * which are guaranteed to work with any file system. */ 608 if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0 && 609 ! vnode_has_strategy(vnd)) 610 vnd->sc_flags |= VNF_USE_VN_RDWR; 611 612 #ifdef DEBUG 613 if (vnddebug & VDB_INIT) 614 printf("vndthread: vp %p, %s\n", vnd->sc_vp, 615 (vnd->sc_flags & VNF_USE_VN_RDWR) == 0 ? 616 "using bmap/strategy operations" : 617 "using read/write operations"); 618 #endif 619 620 s = splbio(); 621 vnd->sc_flags |= VNF_KTHREAD; 622 wakeup(&vnd->sc_kthread); 623 624 /* 625 * Dequeue requests and serve them depending on the available 626 * vnode operations. 627 */ 628 while ((vnd->sc_flags & VNF_VUNCONF) == 0) { 629 struct vndxfer *vnx; 630 struct buf *obp; 631 struct buf *bp; 632 633 obp = bufq_get(vnd->sc_tab); 634 if (obp == NULL) { 635 tsleep(&vnd->sc_tab, PRIBIO, "vndbp", 0); 636 continue; 637 }; 638 if ((vnd->sc_flags & VNF_USE_VN_RDWR)) { 639 KASSERT(vnd->sc_pending > 0 && 640 vnd->sc_pending <= VND_MAXPENDING(vnd)); 641 if (vnd->sc_pending-- == VND_MAXPENDING(vnd)) 642 wakeup(&vnd->sc_pending); 643 } 644 splx(s); 645 #ifdef DEBUG 646 if (vnddebug & VDB_FOLLOW) 647 printf("vndthread(%p)\n", obp); 648 #endif 649 650 if (vnd->sc_vp->v_mount == NULL) { 651 obp->b_error = ENXIO; 652 goto done; 653 } 654 #ifdef VND_COMPRESSION 655 /* handle a compressed read */ 656 if ((obp->b_flags & B_READ) != 0 && (vnd->sc_flags & VNF_COMP)) { 657 off_t bn; 658 659 /* Convert to a byte offset within the file. */ 660 bn = obp->b_rawblkno * 661 vnd->sc_dkdev.dk_label->d_secsize; 662 663 compstrategy(obp, bn); 664 goto done; 665 } 666 #endif /* VND_COMPRESSION */ 667 668 /* 669 * Allocate a header for this transfer and link it to the 670 * buffer 671 */ 672 s = splbio(); 673 vnx = VND_GETXFER(vnd); 674 splx(s); 675 vnx->vx_vnd = vnd; 676 677 s = splbio(); 678 while (vnd->sc_active >= vnd->sc_maxactive) { 679 tsleep(&vnd->sc_tab, PRIBIO, "vndac", 0); 680 } 681 vnd->sc_active++; 682 splx(s); 683 684 /* Instrumentation. */ 685 disk_busy(&vnd->sc_dkdev); 686 687 bp = &vnx->vx_buf; 688 buf_init(bp); 689 bp->b_flags = (obp->b_flags & B_READ); 690 bp->b_oflags = obp->b_oflags; 691 bp->b_cflags = obp->b_cflags; 692 bp->b_iodone = vndiodone; 693 bp->b_private = obp; 694 bp->b_vp = vnd->sc_vp; 695 bp->b_objlock = bp->b_vp->v_interlock; 696 bp->b_data = obp->b_data; 697 bp->b_bcount = obp->b_bcount; 698 BIO_COPYPRIO(bp, obp); 699 700 /* Handle the request using the appropriate operations. */ 701 if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0) 702 handle_with_strategy(vnd, obp, bp); 703 else 704 handle_with_rdwr(vnd, obp, bp); 705 706 s = splbio(); 707 continue; 708 709 done: 710 biodone(obp); 711 s = splbio(); 712 } 713 714 vnd->sc_flags &= (~VNF_KTHREAD | VNF_VUNCONF); 715 wakeup(&vnd->sc_kthread); 716 splx(s); 717 kthread_exit(0); 718 } 719 720 /* 721 * Checks if the given vnode supports the requested operation. 722 * The operation is specified the offset returned by VOFFSET. 723 * 724 * XXX The test below used to determine this is quite fragile 725 * because it relies on the file system to use genfs to specify 726 * unimplemented operations. There might be another way to do 727 * it more cleanly. 728 */ 729 static bool 730 vnode_has_op(const struct vnode *vp, int opoffset) 731 { 732 int (*defaultp)(void *); 733 int (*opp)(void *); 734 735 defaultp = vp->v_op[VOFFSET(vop_default)]; 736 opp = vp->v_op[opoffset]; 737 738 return opp != defaultp && opp != genfs_eopnotsupp && 739 opp != genfs_badop && opp != genfs_nullop; 740 } 741 742 /* 743 * Handes the read/write request given in 'bp' using the vnode's VOP_READ 744 * and VOP_WRITE operations. 745 * 746 * 'obp' is a pointer to the original request fed to the vnd device. 747 */ 748 static void 749 handle_with_rdwr(struct vnd_softc *vnd, const struct buf *obp, struct buf *bp) 750 { 751 bool doread; 752 off_t offset; 753 size_t len, resid; 754 struct vnode *vp; 755 756 doread = bp->b_flags & B_READ; 757 offset = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize; 758 len = bp->b_bcount; 759 vp = vnd->sc_vp; 760 761 #if defined(DEBUG) 762 if (vnddebug & VDB_IO) 763 printf("vnd (rdwr): vp %p, %s, rawblkno 0x%" PRIx64 764 ", secsize %d, offset %" PRIu64 765 ", bcount %d\n", 766 vp, doread ? "read" : "write", obp->b_rawblkno, 767 vnd->sc_dkdev.dk_label->d_secsize, offset, 768 bp->b_bcount); 769 #endif 770 771 /* Issue the read or write operation. */ 772 bp->b_error = 773 vn_rdwr(doread ? UIO_READ : UIO_WRITE, 774 vp, bp->b_data, len, offset, UIO_SYSSPACE, 775 IO_ADV_ENCODE(POSIX_FADV_NOREUSE), vnd->sc_cred, &resid, NULL); 776 bp->b_resid = resid; 777 778 mutex_enter(vp->v_interlock); 779 (void) VOP_PUTPAGES(vp, 0, 0, 780 PGO_ALLPAGES | PGO_CLEANIT | PGO_FREE | PGO_SYNCIO); 781 782 /* We need to increase the number of outputs on the vnode if 783 * there was any write to it. */ 784 if (!doread) { 785 mutex_enter(vp->v_interlock); 786 vp->v_numoutput++; 787 mutex_exit(vp->v_interlock); 788 } 789 790 biodone(bp); 791 } 792 793 /* 794 * Handes the read/write request given in 'bp' using the vnode's VOP_BMAP 795 * and VOP_STRATEGY operations. 796 * 797 * 'obp' is a pointer to the original request fed to the vnd device. 798 */ 799 static void 800 handle_with_strategy(struct vnd_softc *vnd, const struct buf *obp, 801 struct buf *bp) 802 { 803 int bsize, error, flags, skipped; 804 size_t resid, sz; 805 off_t bn, offset; 806 struct vnode *vp; 807 struct buf *nbp = NULL; 808 809 flags = obp->b_flags; 810 811 812 /* convert to a byte offset within the file. */ 813 bn = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize; 814 815 bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize; 816 skipped = 0; 817 818 /* 819 * Break the request into bsize pieces and feed them 820 * sequentially using VOP_BMAP/VOP_STRATEGY. 821 * We do it this way to keep from flooding NFS servers if we 822 * are connected to an NFS file. This places the burden on 823 * the client rather than the server. 824 */ 825 error = 0; 826 bp->b_resid = bp->b_bcount; 827 for (offset = 0, resid = bp->b_resid; /* true */; 828 resid -= sz, offset += sz) { 829 daddr_t nbn; 830 int off, nra; 831 832 nra = 0; 833 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 834 error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra); 835 VOP_UNLOCK(vnd->sc_vp); 836 837 if (error == 0 && (long)nbn == -1) 838 error = EIO; 839 840 /* 841 * If there was an error or a hole in the file...punt. 842 * Note that we may have to wait for any operations 843 * that we have already fired off before releasing 844 * the buffer. 845 * 846 * XXX we could deal with holes here but it would be 847 * a hassle (in the write case). 848 */ 849 if (error) { 850 skipped += resid; 851 break; 852 } 853 854 #ifdef DEBUG 855 if (!dovndcluster) 856 nra = 0; 857 #endif 858 859 off = bn % bsize; 860 sz = MIN(((off_t)1 + nra) * bsize - off, resid); 861 #ifdef DEBUG 862 if (vnddebug & VDB_IO) 863 printf("vndstrategy: vp %p/%p bn 0x%qx/0x%" PRIx64 864 " sz 0x%zx\n", vnd->sc_vp, vp, (long long)bn, 865 nbn, sz); 866 #endif 867 868 nbp = getiobuf(vp, true); 869 nestiobuf_setup(bp, nbp, offset, sz); 870 nbp->b_blkno = nbn + btodb(off); 871 872 #if 0 /* XXX #ifdef DEBUG */ 873 if (vnddebug & VDB_IO) 874 printf("vndstart(%ld): bp %p vp %p blkno " 875 "0x%" PRIx64 " flags %x addr %p cnt 0x%x\n", 876 (long) (vnd-vnd_softc), &nbp->vb_buf, 877 nbp->vb_buf.b_vp, nbp->vb_buf.b_blkno, 878 nbp->vb_buf.b_flags, nbp->vb_buf.b_data, 879 nbp->vb_buf.b_bcount); 880 #endif 881 if (resid == sz) { 882 break; 883 } 884 VOP_STRATEGY(vp, nbp); 885 bn += sz; 886 } 887 if (!(flags & B_READ)) { 888 struct vnode *w_vp; 889 /* 890 * this is the last nested buf, account for 891 * the parent buf write too. 892 * This has to be done last, so that 893 * fsync won't wait for this write which 894 * has no chance to complete before all nested bufs 895 * have been queued. But it has to be done 896 * before the last VOP_STRATEGY() 897 * or the call to nestiobuf_done(). 898 */ 899 w_vp = bp->b_vp; 900 mutex_enter(w_vp->v_interlock); 901 w_vp->v_numoutput++; 902 mutex_exit(w_vp->v_interlock); 903 } 904 KASSERT(skipped != 0 || nbp != NULL); 905 if (skipped) 906 nestiobuf_done(bp, skipped, error); 907 else 908 VOP_STRATEGY(vp, nbp); 909 } 910 911 static void 912 vndiodone(struct buf *bp) 913 { 914 struct vndxfer *vnx = VND_BUFTOXFER(bp); 915 struct vnd_softc *vnd = vnx->vx_vnd; 916 struct buf *obp = bp->b_private; 917 int s = splbio(); 918 919 KASSERT(&vnx->vx_buf == bp); 920 KASSERT(vnd->sc_active > 0); 921 #ifdef DEBUG 922 if (vnddebug & VDB_IO) { 923 printf("vndiodone1: bp %p iodone: error %d\n", 924 bp, bp->b_error); 925 } 926 #endif 927 disk_unbusy(&vnd->sc_dkdev, bp->b_bcount - bp->b_resid, 928 (bp->b_flags & B_READ)); 929 vnd->sc_active--; 930 if (vnd->sc_active == 0) { 931 wakeup(&vnd->sc_tab); 932 } 933 splx(s); 934 obp->b_error = bp->b_error; 935 obp->b_resid = bp->b_resid; 936 buf_destroy(bp); 937 VND_PUTXFER(vnd, vnx); 938 biodone(obp); 939 } 940 941 /* ARGSUSED */ 942 static int 943 vndread(dev_t dev, struct uio *uio, int flags) 944 { 945 int unit = vndunit(dev); 946 struct vnd_softc *sc; 947 948 #ifdef DEBUG 949 if (vnddebug & VDB_FOLLOW) 950 printf("vndread(0x%"PRIx64", %p)\n", dev, uio); 951 #endif 952 953 sc = device_lookup_private(&vnd_cd, unit); 954 if (sc == NULL) 955 return ENXIO; 956 957 if ((sc->sc_flags & VNF_INITED) == 0) 958 return ENXIO; 959 960 return physio(vndstrategy, NULL, dev, B_READ, minphys, uio); 961 } 962 963 /* ARGSUSED */ 964 static int 965 vndwrite(dev_t dev, struct uio *uio, int flags) 966 { 967 int unit = vndunit(dev); 968 struct vnd_softc *sc; 969 970 #ifdef DEBUG 971 if (vnddebug & VDB_FOLLOW) 972 printf("vndwrite(0x%"PRIx64", %p)\n", dev, uio); 973 #endif 974 975 sc = device_lookup_private(&vnd_cd, unit); 976 if (sc == NULL) 977 return ENXIO; 978 979 if ((sc->sc_flags & VNF_INITED) == 0) 980 return ENXIO; 981 982 return physio(vndstrategy, NULL, dev, B_WRITE, minphys, uio); 983 } 984 985 static int 986 vnd_cget(struct lwp *l, int unit, int *un, struct vattr *va) 987 { 988 int error; 989 struct vnd_softc *vnd; 990 991 if (*un == -1) 992 *un = unit; 993 if (*un < 0) 994 return EINVAL; 995 996 vnd = device_lookup_private(&vnd_cd, *un); 997 if (vnd == NULL) 998 return -1; 999 1000 if ((vnd->sc_flags & VNF_INITED) == 0) 1001 return -1; 1002 1003 vn_lock(vnd->sc_vp, LK_SHARED | LK_RETRY); 1004 error = VOP_GETATTR(vnd->sc_vp, va, l->l_cred); 1005 VOP_UNLOCK(vnd->sc_vp); 1006 return error; 1007 } 1008 1009 static int 1010 vnddoclear(struct vnd_softc *vnd, int pmask, int minor, bool force) 1011 { 1012 int error; 1013 1014 if ((error = vndlock(vnd)) != 0) 1015 return error; 1016 1017 /* 1018 * Don't unconfigure if any other partitions are open 1019 * or if both the character and block flavors of this 1020 * partition are open. 1021 */ 1022 if (DK_BUSY(vnd, pmask) && !force) { 1023 vndunlock(vnd); 1024 return EBUSY; 1025 } 1026 1027 /* Delete all of our wedges */ 1028 dkwedge_delall(&vnd->sc_dkdev); 1029 1030 /* 1031 * XXX vndclear() might call vndclose() implicitly; 1032 * release lock to avoid recursion 1033 * 1034 * Set VNF_CLEARING to prevent vndopen() from 1035 * sneaking in after we vndunlock(). 1036 */ 1037 vnd->sc_flags |= VNF_CLEARING; 1038 vndunlock(vnd); 1039 vndclear(vnd, minor); 1040 #ifdef DEBUG 1041 if (vnddebug & VDB_INIT) 1042 printf("vndioctl: CLRed\n"); 1043 #endif 1044 1045 /* Destroy the xfer and buffer pools. */ 1046 pool_destroy(&vnd->sc_vxpool); 1047 1048 /* Detach the disk. */ 1049 disk_detach(&vnd->sc_dkdev); 1050 1051 return 0; 1052 } 1053 1054 /* ARGSUSED */ 1055 static int 1056 vndioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1057 { 1058 bool force; 1059 int unit = vndunit(dev); 1060 struct vnd_softc *vnd; 1061 struct vnd_ioctl *vio; 1062 struct vattr vattr; 1063 struct pathbuf *pb; 1064 struct nameidata nd; 1065 int error, part, pmask; 1066 uint64_t geomsize; 1067 int fflags; 1068 #ifdef __HAVE_OLD_DISKLABEL 1069 struct disklabel newlabel; 1070 #endif 1071 1072 #ifdef DEBUG 1073 if (vnddebug & VDB_FOLLOW) 1074 printf("vndioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p): unit %d\n", 1075 dev, cmd, data, flag, l->l_proc, unit); 1076 #endif 1077 vnd = device_lookup_private(&vnd_cd, unit); 1078 if (vnd == NULL && 1079 #ifdef COMPAT_30 1080 cmd != VNDIOCGET30 && 1081 #endif 1082 #ifdef COMPAT_50 1083 cmd != VNDIOCGET50 && 1084 #endif 1085 cmd != VNDIOCGET) 1086 return ENXIO; 1087 vio = (struct vnd_ioctl *)data; 1088 1089 /* Must be open for writes for these commands... */ 1090 switch (cmd) { 1091 case VNDIOCSET: 1092 case VNDIOCCLR: 1093 #ifdef COMPAT_50 1094 case VNDIOCSET50: 1095 case VNDIOCCLR50: 1096 #endif 1097 case DIOCSDINFO: 1098 case DIOCWDINFO: 1099 #ifdef __HAVE_OLD_DISKLABEL 1100 case ODIOCSDINFO: 1101 case ODIOCWDINFO: 1102 #endif 1103 case DIOCKLABEL: 1104 case DIOCWLABEL: 1105 if ((flag & FWRITE) == 0) 1106 return EBADF; 1107 } 1108 1109 /* Must be initialized for these... */ 1110 switch (cmd) { 1111 case VNDIOCCLR: 1112 #ifdef VNDIOCCLR50 1113 case VNDIOCCLR50: 1114 #endif 1115 case DIOCGDINFO: 1116 case DIOCSDINFO: 1117 case DIOCWDINFO: 1118 case DIOCGPART: 1119 case DIOCKLABEL: 1120 case DIOCWLABEL: 1121 case DIOCGDEFLABEL: 1122 case DIOCCACHESYNC: 1123 #ifdef __HAVE_OLD_DISKLABEL 1124 case ODIOCGDINFO: 1125 case ODIOCSDINFO: 1126 case ODIOCWDINFO: 1127 case ODIOCGDEFLABEL: 1128 #endif 1129 if ((vnd->sc_flags & VNF_INITED) == 0) 1130 return ENXIO; 1131 } 1132 1133 error = disk_ioctl(&vnd->sc_dkdev, dev, cmd, data, flag, l); 1134 if (error != EPASSTHROUGH) 1135 return error; 1136 1137 1138 switch (cmd) { 1139 #ifdef VNDIOCSET50 1140 case VNDIOCSET50: 1141 #endif 1142 case VNDIOCSET: 1143 if (vnd->sc_flags & VNF_INITED) 1144 return EBUSY; 1145 1146 if ((error = vndlock(vnd)) != 0) 1147 return error; 1148 1149 fflags = FREAD; 1150 if ((vio->vnd_flags & VNDIOF_READONLY) == 0) 1151 fflags |= FWRITE; 1152 error = pathbuf_copyin(vio->vnd_file, &pb); 1153 if (error) { 1154 goto unlock_and_exit; 1155 } 1156 NDINIT(&nd, LOOKUP, FOLLOW, pb); 1157 if ((error = vn_open(&nd, fflags, 0)) != 0) { 1158 pathbuf_destroy(pb); 1159 goto unlock_and_exit; 1160 } 1161 KASSERT(l); 1162 error = VOP_GETATTR(nd.ni_vp, &vattr, l->l_cred); 1163 if (!error && nd.ni_vp->v_type != VREG) 1164 error = EOPNOTSUPP; 1165 if (!error && vattr.va_bytes < vattr.va_size) 1166 /* File is definitely sparse, use vn_rdwr() */ 1167 vnd->sc_flags |= VNF_USE_VN_RDWR; 1168 if (error) { 1169 VOP_UNLOCK(nd.ni_vp); 1170 goto close_and_exit; 1171 } 1172 1173 /* If using a compressed file, initialize its info */ 1174 /* (or abort with an error if kernel has no compression) */ 1175 if (vio->vnd_flags & VNF_COMP) { 1176 #ifdef VND_COMPRESSION 1177 struct vnd_comp_header *ch; 1178 int i; 1179 u_int32_t comp_size; 1180 u_int32_t comp_maxsize; 1181 1182 /* allocate space for compresed file header */ 1183 ch = malloc(sizeof(struct vnd_comp_header), 1184 M_TEMP, M_WAITOK); 1185 1186 /* read compressed file header */ 1187 error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch, 1188 sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE, 1189 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); 1190 if (error) { 1191 free(ch, M_TEMP); 1192 VOP_UNLOCK(nd.ni_vp); 1193 goto close_and_exit; 1194 } 1195 1196 /* save some header info */ 1197 vnd->sc_comp_blksz = ntohl(ch->block_size); 1198 /* note last offset is the file byte size */ 1199 vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1; 1200 free(ch, M_TEMP); 1201 if (vnd->sc_comp_blksz == 0 || 1202 vnd->sc_comp_blksz % DEV_BSIZE !=0) { 1203 VOP_UNLOCK(nd.ni_vp); 1204 error = EINVAL; 1205 goto close_and_exit; 1206 } 1207 if (sizeof(struct vnd_comp_header) + 1208 sizeof(u_int64_t) * vnd->sc_comp_numoffs > 1209 vattr.va_size) { 1210 VOP_UNLOCK(nd.ni_vp); 1211 error = EINVAL; 1212 goto close_and_exit; 1213 } 1214 1215 /* set decompressed file size */ 1216 vattr.va_size = 1217 ((u_quad_t)vnd->sc_comp_numoffs - 1) * 1218 (u_quad_t)vnd->sc_comp_blksz; 1219 1220 /* allocate space for all the compressed offsets */ 1221 vnd->sc_comp_offsets = 1222 malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs, 1223 M_DEVBUF, M_WAITOK); 1224 1225 /* read in the offsets */ 1226 error = vn_rdwr(UIO_READ, nd.ni_vp, 1227 (void *)vnd->sc_comp_offsets, 1228 sizeof(u_int64_t) * vnd->sc_comp_numoffs, 1229 sizeof(struct vnd_comp_header), UIO_SYSSPACE, 1230 IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL); 1231 if (error) { 1232 VOP_UNLOCK(nd.ni_vp); 1233 goto close_and_exit; 1234 } 1235 /* 1236 * find largest block size (used for allocation limit). 1237 * Also convert offset to native byte order. 1238 */ 1239 comp_maxsize = 0; 1240 for (i = 0; i < vnd->sc_comp_numoffs - 1; i++) { 1241 vnd->sc_comp_offsets[i] = 1242 be64toh(vnd->sc_comp_offsets[i]); 1243 comp_size = be64toh(vnd->sc_comp_offsets[i + 1]) 1244 - vnd->sc_comp_offsets[i]; 1245 if (comp_size > comp_maxsize) 1246 comp_maxsize = comp_size; 1247 } 1248 vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1] = 1249 be64toh(vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1]); 1250 1251 /* create compressed data buffer */ 1252 vnd->sc_comp_buff = malloc(comp_maxsize, 1253 M_DEVBUF, M_WAITOK); 1254 1255 /* create decompressed buffer */ 1256 vnd->sc_comp_decombuf = malloc(vnd->sc_comp_blksz, 1257 M_DEVBUF, M_WAITOK); 1258 vnd->sc_comp_buffblk = -1; 1259 1260 /* Initialize decompress stream */ 1261 memset(&vnd->sc_comp_stream, 0, sizeof(z_stream)); 1262 vnd->sc_comp_stream.zalloc = vnd_alloc; 1263 vnd->sc_comp_stream.zfree = vnd_free; 1264 error = inflateInit2(&vnd->sc_comp_stream, MAX_WBITS); 1265 if (error) { 1266 if (vnd->sc_comp_stream.msg) 1267 printf("vnd%d: compressed file, %s\n", 1268 unit, vnd->sc_comp_stream.msg); 1269 VOP_UNLOCK(nd.ni_vp); 1270 error = EINVAL; 1271 goto close_and_exit; 1272 } 1273 1274 vnd->sc_flags |= VNF_COMP | VNF_READONLY; 1275 #else /* !VND_COMPRESSION */ 1276 VOP_UNLOCK(nd.ni_vp); 1277 error = EOPNOTSUPP; 1278 goto close_and_exit; 1279 #endif /* VND_COMPRESSION */ 1280 } 1281 1282 VOP_UNLOCK(nd.ni_vp); 1283 vnd->sc_vp = nd.ni_vp; 1284 vnd->sc_size = btodb(vattr.va_size); /* note truncation */ 1285 1286 /* 1287 * Use pseudo-geometry specified. If none was provided, 1288 * use "standard" Adaptec fictitious geometry. 1289 */ 1290 if (vio->vnd_flags & VNDIOF_HASGEOM) { 1291 1292 memcpy(&vnd->sc_geom, &vio->vnd_geom, 1293 sizeof(vio->vnd_geom)); 1294 1295 /* 1296 * Sanity-check the sector size. 1297 * XXX Don't allow secsize < DEV_BSIZE. Should 1298 * XXX we? 1299 */ 1300 if (vnd->sc_geom.vng_secsize < DEV_BSIZE || 1301 (vnd->sc_geom.vng_secsize % DEV_BSIZE) != 0 || 1302 vnd->sc_geom.vng_ncylinders == 0 || 1303 (vnd->sc_geom.vng_ntracks * 1304 vnd->sc_geom.vng_nsectors) == 0) { 1305 error = EINVAL; 1306 goto close_and_exit; 1307 } 1308 1309 /* 1310 * Compute the size (in DEV_BSIZE blocks) specified 1311 * by the geometry. 1312 */ 1313 geomsize = (int64_t)vnd->sc_geom.vng_nsectors * 1314 vnd->sc_geom.vng_ntracks * 1315 vnd->sc_geom.vng_ncylinders * 1316 (vnd->sc_geom.vng_secsize / DEV_BSIZE); 1317 1318 /* 1319 * Sanity-check the size against the specified 1320 * geometry. 1321 */ 1322 if (vnd->sc_size < geomsize) { 1323 error = EINVAL; 1324 goto close_and_exit; 1325 } 1326 } else if (vnd->sc_size >= (32 * 64)) { 1327 /* 1328 * Size must be at least 2048 DEV_BSIZE blocks 1329 * (1M) in order to use this geometry. 1330 */ 1331 vnd->sc_geom.vng_secsize = DEV_BSIZE; 1332 vnd->sc_geom.vng_nsectors = 32; 1333 vnd->sc_geom.vng_ntracks = 64; 1334 vnd->sc_geom.vng_ncylinders = vnd->sc_size / (64 * 32); 1335 } else { 1336 vnd->sc_geom.vng_secsize = DEV_BSIZE; 1337 vnd->sc_geom.vng_nsectors = 1; 1338 vnd->sc_geom.vng_ntracks = 1; 1339 vnd->sc_geom.vng_ncylinders = vnd->sc_size; 1340 } 1341 1342 vnd_set_geometry(vnd); 1343 1344 if (vio->vnd_flags & VNDIOF_READONLY) { 1345 vnd->sc_flags |= VNF_READONLY; 1346 } 1347 1348 if ((error = vndsetcred(vnd, l->l_cred)) != 0) 1349 goto close_and_exit; 1350 1351 vndthrottle(vnd, vnd->sc_vp); 1352 vio->vnd_osize = dbtob(vnd->sc_size); 1353 #ifdef VNDIOCSET50 1354 if (cmd != VNDIOCSET50) 1355 #endif 1356 vio->vnd_size = dbtob(vnd->sc_size); 1357 vnd->sc_flags |= VNF_INITED; 1358 1359 /* create the kernel thread, wait for it to be up */ 1360 error = kthread_create(PRI_NONE, 0, NULL, vndthread, vnd, 1361 &vnd->sc_kthread, "%s", device_xname(vnd->sc_dev)); 1362 if (error) 1363 goto close_and_exit; 1364 while ((vnd->sc_flags & VNF_KTHREAD) == 0) { 1365 tsleep(&vnd->sc_kthread, PRIBIO, "vndthr", 0); 1366 } 1367 #ifdef DEBUG 1368 if (vnddebug & VDB_INIT) 1369 printf("vndioctl: SET vp %p size 0x%lx %d/%d/%d/%d\n", 1370 vnd->sc_vp, (unsigned long) vnd->sc_size, 1371 vnd->sc_geom.vng_secsize, 1372 vnd->sc_geom.vng_nsectors, 1373 vnd->sc_geom.vng_ntracks, 1374 vnd->sc_geom.vng_ncylinders); 1375 #endif 1376 1377 /* Attach the disk. */ 1378 disk_attach(&vnd->sc_dkdev); 1379 1380 /* Initialize the xfer and buffer pools. */ 1381 pool_init(&vnd->sc_vxpool, sizeof(struct vndxfer), 0, 1382 0, 0, "vndxpl", NULL, IPL_BIO); 1383 1384 vndunlock(vnd); 1385 1386 pathbuf_destroy(pb); 1387 1388 /* Discover wedges on this disk */ 1389 dkwedge_discover(&vnd->sc_dkdev); 1390 1391 break; 1392 1393 close_and_exit: 1394 (void) vn_close(nd.ni_vp, fflags, l->l_cred); 1395 pathbuf_destroy(pb); 1396 unlock_and_exit: 1397 #ifdef VND_COMPRESSION 1398 /* free any allocated memory (for compressed file) */ 1399 if (vnd->sc_comp_offsets) { 1400 free(vnd->sc_comp_offsets, M_DEVBUF); 1401 vnd->sc_comp_offsets = NULL; 1402 } 1403 if (vnd->sc_comp_buff) { 1404 free(vnd->sc_comp_buff, M_DEVBUF); 1405 vnd->sc_comp_buff = NULL; 1406 } 1407 if (vnd->sc_comp_decombuf) { 1408 free(vnd->sc_comp_decombuf, M_DEVBUF); 1409 vnd->sc_comp_decombuf = NULL; 1410 } 1411 #endif /* VND_COMPRESSION */ 1412 vndunlock(vnd); 1413 return error; 1414 1415 #ifdef VNDIOCCLR50 1416 case VNDIOCCLR50: 1417 #endif 1418 case VNDIOCCLR: 1419 part = DISKPART(dev); 1420 pmask = (1 << part); 1421 force = (vio->vnd_flags & VNDIOF_FORCE) != 0; 1422 1423 if ((error = vnddoclear(vnd, pmask, minor(dev), force)) != 0) 1424 return error; 1425 1426 break; 1427 1428 #ifdef COMPAT_30 1429 case VNDIOCGET30: { 1430 struct vnd_user30 *vnu; 1431 struct vattr va; 1432 vnu = (struct vnd_user30 *)data; 1433 KASSERT(l); 1434 switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) { 1435 case 0: 1436 vnu->vnu_dev = va.va_fsid; 1437 vnu->vnu_ino = va.va_fileid; 1438 break; 1439 case -1: 1440 /* unused is not an error */ 1441 vnu->vnu_dev = 0; 1442 vnu->vnu_ino = 0; 1443 break; 1444 default: 1445 return error; 1446 } 1447 break; 1448 } 1449 #endif 1450 1451 #ifdef COMPAT_50 1452 case VNDIOCGET50: { 1453 struct vnd_user50 *vnu; 1454 struct vattr va; 1455 vnu = (struct vnd_user50 *)data; 1456 KASSERT(l); 1457 switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) { 1458 case 0: 1459 vnu->vnu_dev = va.va_fsid; 1460 vnu->vnu_ino = va.va_fileid; 1461 break; 1462 case -1: 1463 /* unused is not an error */ 1464 vnu->vnu_dev = 0; 1465 vnu->vnu_ino = 0; 1466 break; 1467 default: 1468 return error; 1469 } 1470 break; 1471 } 1472 #endif 1473 1474 case VNDIOCGET: { 1475 struct vnd_user *vnu; 1476 struct vattr va; 1477 vnu = (struct vnd_user *)data; 1478 KASSERT(l); 1479 switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) { 1480 case 0: 1481 vnu->vnu_dev = va.va_fsid; 1482 vnu->vnu_ino = va.va_fileid; 1483 break; 1484 case -1: 1485 /* unused is not an error */ 1486 vnu->vnu_dev = 0; 1487 vnu->vnu_ino = 0; 1488 break; 1489 default: 1490 return error; 1491 } 1492 break; 1493 } 1494 1495 case DIOCWDINFO: 1496 case DIOCSDINFO: 1497 #ifdef __HAVE_OLD_DISKLABEL 1498 case ODIOCWDINFO: 1499 case ODIOCSDINFO: 1500 #endif 1501 { 1502 struct disklabel *lp; 1503 1504 if ((error = vndlock(vnd)) != 0) 1505 return error; 1506 1507 vnd->sc_flags |= VNF_LABELLING; 1508 1509 #ifdef __HAVE_OLD_DISKLABEL 1510 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { 1511 memset(&newlabel, 0, sizeof newlabel); 1512 memcpy(&newlabel, data, sizeof (struct olddisklabel)); 1513 lp = &newlabel; 1514 } else 1515 #endif 1516 lp = (struct disklabel *)data; 1517 1518 error = setdisklabel(vnd->sc_dkdev.dk_label, 1519 lp, 0, vnd->sc_dkdev.dk_cpulabel); 1520 if (error == 0) { 1521 if (cmd == DIOCWDINFO 1522 #ifdef __HAVE_OLD_DISKLABEL 1523 || cmd == ODIOCWDINFO 1524 #endif 1525 ) 1526 error = writedisklabel(VNDLABELDEV(dev), 1527 vndstrategy, vnd->sc_dkdev.dk_label, 1528 vnd->sc_dkdev.dk_cpulabel); 1529 } 1530 1531 vnd->sc_flags &= ~VNF_LABELLING; 1532 1533 vndunlock(vnd); 1534 1535 if (error) 1536 return error; 1537 break; 1538 } 1539 1540 case DIOCKLABEL: 1541 if (*(int *)data != 0) 1542 vnd->sc_flags |= VNF_KLABEL; 1543 else 1544 vnd->sc_flags &= ~VNF_KLABEL; 1545 break; 1546 1547 case DIOCWLABEL: 1548 if (*(int *)data != 0) 1549 vnd->sc_flags |= VNF_WLABEL; 1550 else 1551 vnd->sc_flags &= ~VNF_WLABEL; 1552 break; 1553 1554 case DIOCGDEFLABEL: 1555 vndgetdefaultlabel(vnd, (struct disklabel *)data); 1556 break; 1557 1558 #ifdef __HAVE_OLD_DISKLABEL 1559 case ODIOCGDEFLABEL: 1560 vndgetdefaultlabel(vnd, &newlabel); 1561 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 1562 return ENOTTY; 1563 memcpy(data, &newlabel, sizeof (struct olddisklabel)); 1564 break; 1565 #endif 1566 1567 case DIOCCACHESYNC: 1568 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 1569 error = VOP_FSYNC(vnd->sc_vp, vnd->sc_cred, 1570 FSYNC_WAIT | FSYNC_DATAONLY | FSYNC_CACHE, 0, 0); 1571 VOP_UNLOCK(vnd->sc_vp); 1572 return error; 1573 1574 default: 1575 return ENOTTY; 1576 } 1577 1578 return 0; 1579 } 1580 1581 /* 1582 * Duplicate the current processes' credentials. Since we are called only 1583 * as the result of a SET ioctl and only root can do that, any future access 1584 * to this "disk" is essentially as root. Note that credentials may change 1585 * if some other uid can write directly to the mapped file (NFS). 1586 */ 1587 static int 1588 vndsetcred(struct vnd_softc *vnd, kauth_cred_t cred) 1589 { 1590 struct uio auio; 1591 struct iovec aiov; 1592 char *tmpbuf; 1593 int error; 1594 1595 vnd->sc_cred = kauth_cred_dup(cred); 1596 tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK); 1597 1598 /* XXX: Horrible kludge to establish credentials for NFS */ 1599 aiov.iov_base = tmpbuf; 1600 aiov.iov_len = min(DEV_BSIZE, dbtob(vnd->sc_size)); 1601 auio.uio_iov = &aiov; 1602 auio.uio_iovcnt = 1; 1603 auio.uio_offset = 0; 1604 auio.uio_rw = UIO_READ; 1605 auio.uio_resid = aiov.iov_len; 1606 UIO_SETUP_SYSSPACE(&auio); 1607 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 1608 error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred); 1609 if (error == 0) { 1610 /* 1611 * Because vnd does all IO directly through the vnode 1612 * we need to flush (at least) the buffer from the above 1613 * VOP_READ from the buffer cache to prevent cache 1614 * incoherencies. Also, be careful to write dirty 1615 * buffers back to stable storage. 1616 */ 1617 error = vinvalbuf(vnd->sc_vp, V_SAVE, vnd->sc_cred, 1618 curlwp, 0, 0); 1619 } 1620 VOP_UNLOCK(vnd->sc_vp); 1621 1622 free(tmpbuf, M_TEMP); 1623 return error; 1624 } 1625 1626 /* 1627 * Set maxactive based on FS type 1628 */ 1629 static void 1630 vndthrottle(struct vnd_softc *vnd, struct vnode *vp) 1631 { 1632 1633 if (vp->v_tag == VT_NFS) 1634 vnd->sc_maxactive = 2; 1635 else 1636 vnd->sc_maxactive = 8; 1637 1638 if (vnd->sc_maxactive < 1) 1639 vnd->sc_maxactive = 1; 1640 } 1641 1642 #if 0 1643 static void 1644 vndshutdown(void) 1645 { 1646 struct vnd_softc *vnd; 1647 1648 for (vnd = &vnd_softc[0]; vnd < &vnd_softc[numvnd]; vnd++) 1649 if (vnd->sc_flags & VNF_INITED) 1650 vndclear(vnd); 1651 } 1652 #endif 1653 1654 static void 1655 vndclear(struct vnd_softc *vnd, int myminor) 1656 { 1657 struct vnode *vp = vnd->sc_vp; 1658 int fflags = FREAD; 1659 int bmaj, cmaj, i, mn; 1660 int s; 1661 1662 #ifdef DEBUG 1663 if (vnddebug & VDB_FOLLOW) 1664 printf("vndclear(%p): vp %p\n", vnd, vp); 1665 #endif 1666 /* locate the major number */ 1667 bmaj = bdevsw_lookup_major(&vnd_bdevsw); 1668 cmaj = cdevsw_lookup_major(&vnd_cdevsw); 1669 1670 /* Nuke the vnodes for any open instances */ 1671 for (i = 0; i < MAXPARTITIONS; i++) { 1672 mn = DISKMINOR(device_unit(vnd->sc_dev), i); 1673 vdevgone(bmaj, mn, mn, VBLK); 1674 if (mn != myminor) /* XXX avoid to kill own vnode */ 1675 vdevgone(cmaj, mn, mn, VCHR); 1676 } 1677 1678 if ((vnd->sc_flags & VNF_READONLY) == 0) 1679 fflags |= FWRITE; 1680 1681 s = splbio(); 1682 bufq_drain(vnd->sc_tab); 1683 splx(s); 1684 1685 vnd->sc_flags |= VNF_VUNCONF; 1686 wakeup(&vnd->sc_tab); 1687 while (vnd->sc_flags & VNF_KTHREAD) 1688 tsleep(&vnd->sc_kthread, PRIBIO, "vnthr", 0); 1689 1690 #ifdef VND_COMPRESSION 1691 /* free the compressed file buffers */ 1692 if (vnd->sc_flags & VNF_COMP) { 1693 if (vnd->sc_comp_offsets) { 1694 free(vnd->sc_comp_offsets, M_DEVBUF); 1695 vnd->sc_comp_offsets = NULL; 1696 } 1697 if (vnd->sc_comp_buff) { 1698 free(vnd->sc_comp_buff, M_DEVBUF); 1699 vnd->sc_comp_buff = NULL; 1700 } 1701 if (vnd->sc_comp_decombuf) { 1702 free(vnd->sc_comp_decombuf, M_DEVBUF); 1703 vnd->sc_comp_decombuf = NULL; 1704 } 1705 } 1706 #endif /* VND_COMPRESSION */ 1707 vnd->sc_flags &= 1708 ~(VNF_INITED | VNF_READONLY | VNF_KLABEL | VNF_VLABEL 1709 | VNF_VUNCONF | VNF_COMP | VNF_CLEARING); 1710 if (vp == NULL) 1711 panic("vndclear: null vp"); 1712 (void) vn_close(vp, fflags, vnd->sc_cred); 1713 kauth_cred_free(vnd->sc_cred); 1714 vnd->sc_vp = NULL; 1715 vnd->sc_cred = NULL; 1716 vnd->sc_size = 0; 1717 } 1718 1719 static int 1720 vndsize(dev_t dev) 1721 { 1722 struct vnd_softc *sc; 1723 struct disklabel *lp; 1724 int part, unit, omask; 1725 int size; 1726 1727 unit = vndunit(dev); 1728 sc = device_lookup_private(&vnd_cd, unit); 1729 if (sc == NULL) 1730 return -1; 1731 1732 if ((sc->sc_flags & VNF_INITED) == 0) 1733 return -1; 1734 1735 part = DISKPART(dev); 1736 omask = sc->sc_dkdev.dk_openmask & (1 << part); 1737 lp = sc->sc_dkdev.dk_label; 1738 1739 if (omask == 0 && vndopen(dev, 0, S_IFBLK, curlwp)) /* XXX */ 1740 return -1; 1741 1742 if (lp->d_partitions[part].p_fstype != FS_SWAP) 1743 size = -1; 1744 else 1745 size = lp->d_partitions[part].p_size * 1746 (lp->d_secsize / DEV_BSIZE); 1747 1748 if (omask == 0 && vndclose(dev, 0, S_IFBLK, curlwp)) /* XXX */ 1749 return -1; 1750 1751 return size; 1752 } 1753 1754 static int 1755 vnddump(dev_t dev, daddr_t blkno, void *va, 1756 size_t size) 1757 { 1758 1759 /* Not implemented. */ 1760 return ENXIO; 1761 } 1762 1763 static void 1764 vndgetdefaultlabel(struct vnd_softc *sc, struct disklabel *lp) 1765 { 1766 struct vndgeom *vng = &sc->sc_geom; 1767 struct partition *pp; 1768 unsigned spb; 1769 1770 memset(lp, 0, sizeof(*lp)); 1771 1772 spb = vng->vng_secsize / DEV_BSIZE; 1773 if (sc->sc_size / spb > UINT32_MAX) 1774 lp->d_secperunit = UINT32_MAX; 1775 else 1776 lp->d_secperunit = sc->sc_size / spb; 1777 lp->d_secsize = vng->vng_secsize; 1778 lp->d_nsectors = vng->vng_nsectors; 1779 lp->d_ntracks = vng->vng_ntracks; 1780 lp->d_ncylinders = vng->vng_ncylinders; 1781 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1782 1783 strncpy(lp->d_typename, "vnd", sizeof(lp->d_typename)); 1784 lp->d_type = DKTYPE_VND; 1785 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1786 lp->d_rpm = 3600; 1787 lp->d_interleave = 1; 1788 lp->d_flags = 0; 1789 1790 pp = &lp->d_partitions[RAW_PART]; 1791 pp->p_offset = 0; 1792 pp->p_size = lp->d_secperunit; 1793 pp->p_fstype = FS_UNUSED; 1794 lp->d_npartitions = RAW_PART + 1; 1795 1796 lp->d_magic = DISKMAGIC; 1797 lp->d_magic2 = DISKMAGIC; 1798 lp->d_checksum = dkcksum(lp); 1799 } 1800 1801 /* 1802 * Read the disklabel from a vnd. If one is not present, create a fake one. 1803 */ 1804 static void 1805 vndgetdisklabel(dev_t dev, struct vnd_softc *sc) 1806 { 1807 const char *errstring; 1808 struct disklabel *lp = sc->sc_dkdev.dk_label; 1809 struct cpu_disklabel *clp = sc->sc_dkdev.dk_cpulabel; 1810 int i; 1811 1812 memset(clp, 0, sizeof(*clp)); 1813 1814 vndgetdefaultlabel(sc, lp); 1815 1816 /* 1817 * Call the generic disklabel extraction routine. 1818 */ 1819 errstring = readdisklabel(VNDLABELDEV(dev), vndstrategy, lp, clp); 1820 if (errstring) { 1821 /* 1822 * Lack of disklabel is common, but we print the warning 1823 * anyway, since it might contain other useful information. 1824 */ 1825 aprint_normal_dev(sc->sc_dev, "%s\n", errstring); 1826 1827 /* 1828 * For historical reasons, if there's no disklabel 1829 * present, all partitions must be FS_BSDFFS and 1830 * occupy the entire disk. 1831 */ 1832 for (i = 0; i < MAXPARTITIONS; i++) { 1833 /* 1834 * Don't wipe out port specific hack (such as 1835 * dos partition hack of i386 port). 1836 */ 1837 if (lp->d_partitions[i].p_size != 0) 1838 continue; 1839 1840 lp->d_partitions[i].p_size = lp->d_secperunit; 1841 lp->d_partitions[i].p_offset = 0; 1842 lp->d_partitions[i].p_fstype = FS_BSDFFS; 1843 } 1844 1845 strncpy(lp->d_packname, "default label", 1846 sizeof(lp->d_packname)); 1847 1848 lp->d_npartitions = MAXPARTITIONS; 1849 lp->d_checksum = dkcksum(lp); 1850 } 1851 } 1852 1853 /* 1854 * Wait interruptibly for an exclusive lock. 1855 * 1856 * XXX 1857 * Several drivers do this; it should be abstracted and made MP-safe. 1858 */ 1859 static int 1860 vndlock(struct vnd_softc *sc) 1861 { 1862 int error; 1863 1864 while ((sc->sc_flags & VNF_LOCKED) != 0) { 1865 sc->sc_flags |= VNF_WANTED; 1866 if ((error = tsleep(sc, PRIBIO | PCATCH, "vndlck", 0)) != 0) 1867 return error; 1868 } 1869 sc->sc_flags |= VNF_LOCKED; 1870 return 0; 1871 } 1872 1873 /* 1874 * Unlock and wake up any waiters. 1875 */ 1876 static void 1877 vndunlock(struct vnd_softc *sc) 1878 { 1879 1880 sc->sc_flags &= ~VNF_LOCKED; 1881 if ((sc->sc_flags & VNF_WANTED) != 0) { 1882 sc->sc_flags &= ~VNF_WANTED; 1883 wakeup(sc); 1884 } 1885 } 1886 1887 #ifdef VND_COMPRESSION 1888 /* compressed file read */ 1889 static void 1890 compstrategy(struct buf *bp, off_t bn) 1891 { 1892 int error; 1893 int unit = vndunit(bp->b_dev); 1894 struct vnd_softc *vnd = 1895 device_lookup_private(&vnd_cd, unit); 1896 u_int32_t comp_block; 1897 struct uio auio; 1898 char *addr; 1899 int s; 1900 1901 /* set up constants for data move */ 1902 auio.uio_rw = UIO_READ; 1903 UIO_SETUP_SYSSPACE(&auio); 1904 1905 /* read, and transfer the data */ 1906 addr = bp->b_data; 1907 bp->b_resid = bp->b_bcount; 1908 s = splbio(); 1909 while (bp->b_resid > 0) { 1910 unsigned length; 1911 size_t length_in_buffer; 1912 u_int32_t offset_in_buffer; 1913 struct iovec aiov; 1914 1915 /* calculate the compressed block number */ 1916 comp_block = bn / (off_t)vnd->sc_comp_blksz; 1917 1918 /* check for good block number */ 1919 if (comp_block >= vnd->sc_comp_numoffs) { 1920 bp->b_error = EINVAL; 1921 splx(s); 1922 return; 1923 } 1924 1925 /* read in the compressed block, if not in buffer */ 1926 if (comp_block != vnd->sc_comp_buffblk) { 1927 length = vnd->sc_comp_offsets[comp_block + 1] - 1928 vnd->sc_comp_offsets[comp_block]; 1929 vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY); 1930 error = vn_rdwr(UIO_READ, vnd->sc_vp, vnd->sc_comp_buff, 1931 length, vnd->sc_comp_offsets[comp_block], 1932 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, vnd->sc_cred, 1933 NULL, NULL); 1934 if (error) { 1935 bp->b_error = error; 1936 VOP_UNLOCK(vnd->sc_vp); 1937 splx(s); 1938 return; 1939 } 1940 /* uncompress the buffer */ 1941 vnd->sc_comp_stream.next_in = vnd->sc_comp_buff; 1942 vnd->sc_comp_stream.avail_in = length; 1943 vnd->sc_comp_stream.next_out = vnd->sc_comp_decombuf; 1944 vnd->sc_comp_stream.avail_out = vnd->sc_comp_blksz; 1945 inflateReset(&vnd->sc_comp_stream); 1946 error = inflate(&vnd->sc_comp_stream, Z_FINISH); 1947 if (error != Z_STREAM_END) { 1948 if (vnd->sc_comp_stream.msg) 1949 aprint_normal_dev(vnd->sc_dev, 1950 "compressed file, %s\n", 1951 vnd->sc_comp_stream.msg); 1952 bp->b_error = EBADMSG; 1953 VOP_UNLOCK(vnd->sc_vp); 1954 splx(s); 1955 return; 1956 } 1957 vnd->sc_comp_buffblk = comp_block; 1958 VOP_UNLOCK(vnd->sc_vp); 1959 } 1960 1961 /* transfer the usable uncompressed data */ 1962 offset_in_buffer = bn % (off_t)vnd->sc_comp_blksz; 1963 length_in_buffer = vnd->sc_comp_blksz - offset_in_buffer; 1964 if (length_in_buffer > bp->b_resid) 1965 length_in_buffer = bp->b_resid; 1966 auio.uio_iov = &aiov; 1967 auio.uio_iovcnt = 1; 1968 aiov.iov_base = addr; 1969 aiov.iov_len = length_in_buffer; 1970 auio.uio_resid = aiov.iov_len; 1971 auio.uio_offset = 0; 1972 error = uiomove(vnd->sc_comp_decombuf + offset_in_buffer, 1973 length_in_buffer, &auio); 1974 if (error) { 1975 bp->b_error = error; 1976 splx(s); 1977 return; 1978 } 1979 1980 bn += length_in_buffer; 1981 addr += length_in_buffer; 1982 bp->b_resid -= length_in_buffer; 1983 } 1984 splx(s); 1985 } 1986 1987 /* compression memory allocation routines */ 1988 static void * 1989 vnd_alloc(void *aux, u_int items, u_int siz) 1990 { 1991 return malloc(items * siz, M_TEMP, M_NOWAIT); 1992 } 1993 1994 static void 1995 vnd_free(void *aux, void *ptr) 1996 { 1997 free(ptr, M_TEMP); 1998 } 1999 #endif /* VND_COMPRESSION */ 2000 2001 static void 2002 vnd_set_geometry(struct vnd_softc *vnd) 2003 { 2004 struct disk_geom *dg = &vnd->sc_dkdev.dk_geom; 2005 2006 memset(dg, 0, sizeof(*dg)); 2007 2008 dg->dg_secperunit = (int64_t)vnd->sc_geom.vng_nsectors * 2009 vnd->sc_geom.vng_ntracks * vnd->sc_geom.vng_ncylinders; 2010 dg->dg_secsize = vnd->sc_geom.vng_secsize; 2011 dg->dg_nsectors = vnd->sc_geom.vng_nsectors; 2012 dg->dg_ntracks = vnd->sc_geom.vng_ntracks; 2013 dg->dg_ncylinders = vnd->sc_geom.vng_ncylinders; 2014 2015 #ifdef DEBUG 2016 if (vnddebug & VDB_LABEL) { 2017 printf("dg->dg_secperunit: %" PRId64 "\n", dg->dg_secperunit); 2018 printf("dg->dg_ncylinders: %u\n", dg->dg_ncylinders); 2019 } 2020 #endif 2021 disk_set_info(vnd->sc_dev, &vnd->sc_dkdev, NULL); 2022 } 2023 2024 #ifdef _MODULE 2025 2026 #include <sys/module.h> 2027 2028 #ifdef VND_COMPRESSION 2029 #define VND_DEPENDS "zlib" 2030 #else 2031 #define VND_DEPENDS NULL 2032 #endif 2033 2034 MODULE(MODULE_CLASS_DRIVER, vnd, VND_DEPENDS); 2035 CFDRIVER_DECL(vnd, DV_DISK, NULL); 2036 2037 static int 2038 vnd_modcmd(modcmd_t cmd, void *arg) 2039 { 2040 int bmajor = -1, cmajor = -1, error = 0; 2041 2042 switch (cmd) { 2043 case MODULE_CMD_INIT: 2044 error = config_cfdriver_attach(&vnd_cd); 2045 if (error) 2046 break; 2047 2048 error = config_cfattach_attach(vnd_cd.cd_name, &vnd_ca); 2049 if (error) { 2050 config_cfdriver_detach(&vnd_cd); 2051 aprint_error("%s: unable to register cfattach\n", 2052 vnd_cd.cd_name); 2053 break; 2054 } 2055 2056 error = devsw_attach("vnd", &vnd_bdevsw, &bmajor, 2057 &vnd_cdevsw, &cmajor); 2058 if (error) { 2059 config_cfattach_detach(vnd_cd.cd_name, &vnd_ca); 2060 config_cfdriver_detach(&vnd_cd); 2061 break; 2062 } 2063 2064 break; 2065 2066 case MODULE_CMD_FINI: 2067 error = config_cfattach_detach(vnd_cd.cd_name, &vnd_ca); 2068 if (error) 2069 break; 2070 config_cfdriver_detach(&vnd_cd); 2071 devsw_detach(&vnd_bdevsw, &vnd_cdevsw); 2072 break; 2073 2074 case MODULE_CMD_STAT: 2075 return ENOTTY; 2076 2077 default: 2078 return ENOTTY; 2079 } 2080 2081 return error; 2082 } 2083 2084 #endif 2085