1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * from: Utah Hdr: vn.c 1.13 94/04/02 39 * 40 * from: @(#)vn.c 8.6 (Berkeley) 4/1/94 41 * $FreeBSD: src/sys/dev/vn/vn.c,v 1.105.2.4 2001/11/18 07:11:00 dillon Exp $ 42 */ 43 44 /* 45 * Vnode disk driver. 46 * 47 * Block/character interface to a vnode. Allows one to treat a file 48 * as a disk (e.g. build a filesystem in it, mount it, etc.). 49 * 50 * NOTE 1: There is a security issue involved with this driver. 51 * Once mounted all access to the contents of the "mapped" file via 52 * the special file is controlled by the permissions on the special 53 * file, the protection of the mapped file is ignored (effectively, 54 * by using root credentials in all transactions). 55 * 56 * NOTE 2: Doesn't interact with leases, should it? 57 */ 58 59 #include "use_vn.h" 60 #include <sys/param.h> 61 #include <sys/systm.h> 62 #include <sys/kernel.h> 63 #include <sys/proc.h> 64 #include <sys/priv.h> 65 #include <sys/nlookup.h> 66 #include <sys/buf.h> 67 #include <sys/malloc.h> 68 #include <sys/mount.h> 69 #include <sys/vnode.h> 70 #include <sys/fcntl.h> 71 #include <sys/conf.h> 72 #include <sys/diskslice.h> 73 #include <sys/disk.h> 74 #include <sys/stat.h> 75 #include <sys/module.h> 76 #include <sys/vnioctl.h> 77 78 #include <vm/vm.h> 79 #include <vm/vm_object.h> 80 #include <vm/vm_page.h> 81 #include <vm/vm_pager.h> 82 #include <vm/vm_pageout.h> 83 #include <vm/swap_pager.h> 84 #include <vm/vm_extern.h> 85 #include <vm/vm_zone.h> 86 #include <sys/devfs.h> 87 88 static d_ioctl_t vnioctl; 89 static d_open_t vnopen; 90 static d_close_t vnclose; 91 static d_psize_t vnsize; 92 static d_strategy_t vnstrategy; 93 static d_clone_t vnclone; 94 95 MALLOC_DEFINE(M_VN, "vn_softc", "vn driver structures"); 96 DEVFS_DECLARE_CLONE_BITMAP(vn); 97 98 #if NVN <= 1 99 #define VN_PREALLOCATED_UNITS 4 100 #else 101 #define VN_PREALLOCATED_UNITS NVN 102 #endif 103 104 #define VN_BSIZE_BEST 8192 105 106 /* 107 * dev_ops 108 * D_DISK we want to look like a disk 109 * D_CANFREE We support BUF_CMD_FREEBLKS 110 */ 111 112 static struct dev_ops vn_ops = { 113 { "vn", 0, D_DISK | D_CANFREE }, 114 .d_open = vnopen, 115 .d_close = vnclose, 116 .d_read = physread, 117 .d_write = physwrite, 118 .d_ioctl = vnioctl, 119 .d_strategy = vnstrategy, 120 .d_psize = vnsize 121 }; 122 123 struct vn_softc { 124 int sc_unit; 125 int sc_flags; /* flags */ 126 u_int64_t sc_size; /* size of vn, sc_secsize scale */ 127 int sc_secsize; /* sector size */ 128 struct disk sc_disk; 129 struct vnode *sc_vp; /* vnode if not NULL */ 130 vm_object_t sc_object; /* backing object if not NULL */ 131 struct ucred *sc_cred; /* credentials */ 132 int sc_maxactive; /* max # of active requests */ 133 struct buf sc_tab; /* transfer queue */ 134 u_long sc_options; /* options */ 135 cdev_t sc_dev; /* devices that refer to this unit */ 136 SLIST_ENTRY(vn_softc) sc_list; 137 }; 138 139 static SLIST_HEAD(, vn_softc) vn_list; 140 141 /* sc_flags */ 142 #define VNF_INITED 0x01 143 #define VNF_READONLY 0x02 144 #define VNF_OPENED 0x10 145 #define VNF_DESTROY 0x20 146 147 static u_long vn_options; 148 149 #define IFOPT(vn,opt) if (((vn)->sc_options|vn_options) & (opt)) 150 #define TESTOPT(vn,opt) (((vn)->sc_options|vn_options) & (opt)) 151 152 static int vnsetcred (struct vn_softc *vn, struct ucred *cred); 153 static void vnclear (struct vn_softc *vn); 154 static int vnget (cdev_t dev, struct vn_softc *vn , struct vn_user *vnu); 155 static int vn_modevent (module_t, int, void *); 156 static int vniocattach_file (struct vn_softc *, struct vn_ioctl *, cdev_t dev, int flag, struct ucred *cred); 157 static int vniocattach_swap (struct vn_softc *, struct vn_ioctl *, cdev_t dev, int flag, struct ucred *cred); 158 static cdev_t vn_create(int unit, struct devfs_bitmap *bitmap, int clone); 159 160 static int 161 vnclone(struct dev_clone_args *ap) 162 { 163 int unit; 164 165 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(vn), 0); 166 ap->a_dev = vn_create(unit, &DEVFS_CLONE_BITMAP(vn), 1); 167 168 return 0; 169 } 170 171 static int 172 vnclose(struct dev_close_args *ap) 173 { 174 cdev_t dev = ap->a_head.a_dev; 175 struct vn_softc *vn; 176 177 vn = dev->si_drv1; 178 KKASSERT(vn != NULL); 179 180 vn->sc_flags &= ~VNF_OPENED; 181 182 /* The disk has been detached and can now be safely destroyed */ 183 if (vn->sc_flags & VNF_DESTROY) { 184 KKASSERT(disk_getopencount(&vn->sc_disk) == 0); 185 disk_destroy(&vn->sc_disk); 186 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(vn), dkunit(dev)); 187 SLIST_REMOVE(&vn_list, vn, vn_softc, sc_list); 188 kfree(vn, M_VN); 189 } 190 return (0); 191 } 192 193 static struct vn_softc * 194 vncreatevn(void) 195 { 196 struct vn_softc *vn; 197 198 vn = kmalloc(sizeof *vn, M_VN, M_WAITOK | M_ZERO); 199 return vn; 200 } 201 202 static void 203 vninitvn(struct vn_softc *vn, cdev_t dev) 204 { 205 int unit; 206 207 KKASSERT(vn != NULL); 208 KKASSERT(dev != NULL); 209 unit = dkunit(dev); 210 211 vn->sc_unit = unit; 212 dev->si_drv1 = vn; 213 vn->sc_dev = dev; 214 215 SLIST_INSERT_HEAD(&vn_list, vn, sc_list); 216 } 217 218 static int 219 vnopen(struct dev_open_args *ap) 220 { 221 cdev_t dev = ap->a_head.a_dev; 222 struct vn_softc *vn; 223 224 /* 225 * Locate preexisting device 226 */ 227 228 vn = dev->si_drv1; 229 KKASSERT(vn != NULL); 230 231 /* 232 * Update si_bsize fields for device. This data will be overriden by 233 * the slice/parition code for vn accesses through partitions, and 234 * used directly if you open the 'whole disk' device. 235 * 236 * si_bsize_best must be reinitialized in case VN has been 237 * reconfigured, plus make it at least VN_BSIZE_BEST for efficiency. 238 */ 239 dev->si_bsize_phys = vn->sc_secsize; 240 dev->si_bsize_best = vn->sc_secsize; 241 if (dev->si_bsize_best < VN_BSIZE_BEST) 242 dev->si_bsize_best = VN_BSIZE_BEST; 243 244 if ((ap->a_oflags & FWRITE) && (vn->sc_flags & VNF_READONLY)) 245 return (EACCES); 246 247 IFOPT(vn, VN_FOLLOW) 248 kprintf("vnopen(%s, 0x%x, 0x%x)\n", 249 devtoname(dev), ap->a_oflags, ap->a_devtype); 250 251 vn->sc_flags |= VNF_OPENED; 252 return(0); 253 } 254 255 /* 256 * vnstrategy: 257 * 258 * Run strategy routine for VN device. We use VOP_READ/VOP_WRITE calls 259 * for vnode-backed vn's, and the swap_pager_strategy() call for 260 * vm_object-backed vn's. 261 */ 262 static int 263 vnstrategy(struct dev_strategy_args *ap) 264 { 265 cdev_t dev = ap->a_head.a_dev; 266 struct bio *bio = ap->a_bio; 267 struct buf *bp; 268 struct bio *nbio; 269 int unit; 270 struct vn_softc *vn; 271 int error; 272 273 unit = dkunit(dev); 274 vn = dev->si_drv1; 275 KKASSERT(vn != NULL); 276 277 bp = bio->bio_buf; 278 279 IFOPT(vn, VN_DEBUG) 280 kprintf("vnstrategy(%p): unit %d\n", bp, unit); 281 282 if ((vn->sc_flags & VNF_INITED) == 0) { 283 bp->b_error = ENXIO; 284 bp->b_flags |= B_ERROR; 285 biodone(bio); 286 return(0); 287 } 288 289 bp->b_resid = bp->b_bcount; 290 291 /* 292 * The vnode device is using disk/slice label support. 293 * 294 * The dscheck() function is called for validating the 295 * slices that exist ON the vnode device itself, and 296 * translate the "slice-relative" block number, again. 297 * dscheck() will call biodone() and return NULL if 298 * we are at EOF or beyond the device size. 299 */ 300 301 nbio = bio; 302 303 /* 304 * Use the translated nbio from this point on 305 */ 306 if (vn->sc_vp && bp->b_cmd == BUF_CMD_FREEBLKS) { 307 /* 308 * Freeblks is not handled for vnode-backed elements yet. 309 */ 310 bp->b_resid = 0; 311 /* operation complete */ 312 } else if (vn->sc_vp) { 313 /* 314 * VNODE I/O 315 * 316 * If an error occurs, we set B_ERROR but we do not set 317 * B_INVAL because (for a write anyway), the buffer is 318 * still valid. 319 */ 320 struct uio auio; 321 struct iovec aiov; 322 323 bzero(&auio, sizeof(auio)); 324 325 aiov.iov_base = bp->b_data; 326 aiov.iov_len = bp->b_bcount; 327 auio.uio_iov = &aiov; 328 auio.uio_iovcnt = 1; 329 auio.uio_offset = nbio->bio_offset; 330 auio.uio_segflg = UIO_SYSSPACE; 331 if (bp->b_cmd == BUF_CMD_READ) 332 auio.uio_rw = UIO_READ; 333 else 334 auio.uio_rw = UIO_WRITE; 335 auio.uio_resid = bp->b_bcount; 336 auio.uio_td = curthread; 337 338 /* 339 * Don't use IO_DIRECT here, it really gets in the way 340 * due to typical blocksize differences between the 341 * fs backing the VN device and whatever is running on 342 * the VN device. 343 */ 344 switch (bp->b_cmd) { 345 case (BUF_CMD_READ): 346 vn_lock(vn->sc_vp, LK_SHARED | LK_RETRY); 347 error = VOP_READ(vn->sc_vp, &auio, IO_RECURSE, 348 vn->sc_cred); 349 break; 350 351 case (BUF_CMD_WRITE): 352 vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY); 353 error = VOP_WRITE(vn->sc_vp, &auio, IO_RECURSE, 354 vn->sc_cred); 355 break; 356 357 case (BUF_CMD_FLUSH): 358 auio.uio_resid = 0; 359 vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY); 360 error = VOP_FSYNC(vn->sc_vp, MNT_WAIT, 0); 361 break; 362 default: 363 auio.uio_resid = 0; 364 error = 0; 365 goto breakunlocked; 366 } 367 vn_unlock(vn->sc_vp); 368 breakunlocked: 369 bp->b_resid = auio.uio_resid; 370 if (error) { 371 bp->b_error = error; 372 bp->b_flags |= B_ERROR; 373 } 374 /* operation complete */ 375 } else if (vn->sc_object) { 376 /* 377 * OBJT_SWAP I/O (handles read, write, freebuf) 378 * 379 * We have nothing to do if freeing blocks on a reserved 380 * swap area, othrewise execute the op. 381 */ 382 if (bp->b_cmd == BUF_CMD_FREEBLKS && TESTOPT(vn, VN_RESERVE)) { 383 bp->b_resid = 0; 384 /* operation complete */ 385 } else { 386 swap_pager_strategy(vn->sc_object, nbio); 387 return(0); 388 /* NOT REACHED */ 389 } 390 } else { 391 bp->b_resid = bp->b_bcount; 392 bp->b_flags |= B_ERROR | B_INVAL; 393 bp->b_error = EINVAL; 394 /* operation complete */ 395 } 396 biodone(nbio); 397 return(0); 398 } 399 400 /* ARGSUSED */ 401 static int 402 vnioctl(struct dev_ioctl_args *ap) 403 { 404 cdev_t dev = ap->a_head.a_dev; 405 struct vn_softc *vn; 406 struct vn_ioctl *vio; 407 int error; 408 u_long *f; 409 410 vn = dev->si_drv1; 411 IFOPT(vn,VN_FOLLOW) { 412 kprintf("vnioctl(%s, 0x%lx, %p, 0x%x): unit %d\n", 413 devtoname(dev), ap->a_cmd, ap->a_data, ap->a_fflag, 414 dkunit(dev)); 415 } 416 417 switch (ap->a_cmd) { 418 case VNIOCATTACH: 419 case VNIOCDETACH: 420 case VNIOCGSET: 421 case VNIOCGCLEAR: 422 case VNIOCGET: 423 case VNIOCUSET: 424 case VNIOCUCLEAR: 425 goto vn_specific; 426 } 427 428 #if 0 429 if (dkslice(dev) != WHOLE_DISK_SLICE || 430 dkpart(dev) != WHOLE_SLICE_PART) 431 return (ENOTTY); 432 #endif 433 434 vn_specific: 435 436 error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0); 437 if (error) 438 return (error); 439 440 vio = (struct vn_ioctl *)ap->a_data; 441 f = (u_long*)ap->a_data; 442 443 switch (ap->a_cmd) { 444 case VNIOCATTACH: 445 if (vn->sc_flags & VNF_INITED) 446 return(EBUSY); 447 448 if (vn->sc_flags & VNF_DESTROY) 449 return(ENXIO); 450 451 if (vio->vn_file == NULL) 452 error = vniocattach_swap(vn, vio, dev, ap->a_fflag, ap->a_cred); 453 else 454 error = vniocattach_file(vn, vio, dev, ap->a_fflag, ap->a_cred); 455 break; 456 457 case VNIOCDETACH: 458 if ((vn->sc_flags & VNF_INITED) == 0) 459 return(ENXIO); 460 /* 461 * XXX handle i/o in progress. Return EBUSY, or wait, or 462 * flush the i/o. 463 * XXX handle multiple opens of the device. Return EBUSY, 464 * or revoke the fd's. 465 * How are these problems handled for removable and failing 466 * hardware devices? (Hint: They are not) 467 */ 468 if ((disk_getopencount(&vn->sc_disk)) > 1) 469 return (EBUSY); 470 471 vnclear(vn); 472 IFOPT(vn, VN_FOLLOW) 473 kprintf("vnioctl: CLRed\n"); 474 475 if (dkunit(dev) >= VN_PREALLOCATED_UNITS) { 476 vn->sc_flags |= VNF_DESTROY; 477 } 478 479 break; 480 481 case VNIOCGET: 482 error = vnget(dev, vn, (struct vn_user *) ap->a_data); 483 break; 484 485 case VNIOCGSET: 486 vn_options |= *f; 487 *f = vn_options; 488 break; 489 490 case VNIOCGCLEAR: 491 vn_options &= ~(*f); 492 *f = vn_options; 493 break; 494 495 case VNIOCUSET: 496 vn->sc_options |= *f; 497 *f = vn->sc_options; 498 break; 499 500 case VNIOCUCLEAR: 501 vn->sc_options &= ~(*f); 502 *f = vn->sc_options; 503 break; 504 505 default: 506 error = ENOTTY; 507 break; 508 } 509 return(error); 510 } 511 512 /* 513 * vniocattach_file: 514 * 515 * Attach a file to a VN partition. Return the size in the vn_size 516 * field. 517 */ 518 519 static int 520 vniocattach_file(struct vn_softc *vn, struct vn_ioctl *vio, cdev_t dev, 521 int flag, struct ucred *cred) 522 { 523 struct vattr vattr; 524 struct nlookupdata nd; 525 int error, flags; 526 struct vnode *vp; 527 struct disk_info info; 528 529 flags = FREAD|FWRITE; 530 error = nlookup_init(&nd, vio->vn_file, 531 UIO_USERSPACE, NLC_FOLLOW|NLC_LOCKVP); 532 if (error) 533 return (error); 534 if ((error = vn_open(&nd, NULL, flags, 0)) != 0) { 535 if (error != EACCES && error != EPERM && error != EROFS) 536 goto done; 537 flags &= ~FWRITE; 538 nlookup_done(&nd); 539 error = nlookup_init(&nd, vio->vn_file, UIO_USERSPACE, NLC_FOLLOW|NLC_LOCKVP); 540 if (error) 541 return (error); 542 if ((error = vn_open(&nd, NULL, flags, 0)) != 0) 543 goto done; 544 } 545 vp = nd.nl_open_vp; 546 if (vp->v_type != VREG || 547 (error = VOP_GETATTR(vp, &vattr))) { 548 if (error == 0) 549 error = EINVAL; 550 goto done; 551 } 552 vn_unlock(vp); 553 vn->sc_secsize = DEV_BSIZE; 554 vn->sc_vp = vp; 555 nd.nl_open_vp = NULL; 556 557 /* 558 * If the size is specified, override the file attributes. Note that 559 * the vn_size argument is in PAGE_SIZE sized blocks. 560 */ 561 if (vio->vn_size) 562 vn->sc_size = vio->vn_size * PAGE_SIZE / vn->sc_secsize; 563 else 564 vn->sc_size = vattr.va_size / vn->sc_secsize; 565 error = vnsetcred(vn, cred); 566 if (error) { 567 vn->sc_vp = NULL; 568 vn_close(vp, flags, NULL); 569 goto done; 570 } 571 vn->sc_flags |= VNF_INITED; 572 if (flags == FREAD) 573 vn->sc_flags |= VNF_READONLY; 574 575 /* 576 * Set the disk info so that probing is triggered 577 */ 578 bzero(&info, sizeof(struct disk_info)); 579 info.d_media_blksize = vn->sc_secsize; 580 info.d_media_blocks = vn->sc_size; 581 /* 582 * reserve mbr sector for backwards compatibility 583 * when no slices exist. 584 */ 585 info.d_dsflags = DSO_COMPATMBR | DSO_RAWPSIZE; 586 info.d_secpertrack = 32; 587 info.d_nheads = 64 / (vn->sc_secsize / DEV_BSIZE); 588 info.d_secpercyl = info.d_secpertrack * info.d_nheads; 589 info.d_ncylinders = vn->sc_size / info.d_secpercyl; 590 disk_setdiskinfo_sync(&vn->sc_disk, &info); 591 592 error = dev_dopen(dev, flag, S_IFCHR, cred, NULL); 593 if (error) 594 vnclear(vn); 595 596 IFOPT(vn, VN_FOLLOW) 597 kprintf("vnioctl: SET vp %p size %llx blks\n", 598 vn->sc_vp, (long long)vn->sc_size); 599 done: 600 nlookup_done(&nd); 601 return(error); 602 } 603 604 /* 605 * vniocattach_swap: 606 * 607 * Attach swap backing store to a VN partition of the size specified 608 * in vn_size. 609 */ 610 611 static int 612 vniocattach_swap(struct vn_softc *vn, struct vn_ioctl *vio, cdev_t dev, 613 int flag, struct ucred *cred) 614 { 615 int error; 616 struct disk_info info; 617 618 /* 619 * Range check. Disallow negative sizes or any size less then the 620 * size of a page. Then round to a page. 621 */ 622 623 if (vio->vn_size <= 0) 624 return(EDOM); 625 626 /* 627 * Allocate an OBJT_SWAP object. 628 * 629 * sc_secsize is PAGE_SIZE'd 630 * 631 * vio->vn_size is in PAGE_SIZE'd chunks. 632 * sc_size must be in PAGE_SIZE'd chunks. 633 * Note the truncation. 634 */ 635 636 vn->sc_secsize = PAGE_SIZE; 637 vn->sc_size = vio->vn_size; 638 vn->sc_object = swap_pager_alloc(NULL, 639 vn->sc_secsize * (off_t)vio->vn_size, 640 VM_PROT_DEFAULT, 0); 641 IFOPT(vn, VN_RESERVE) { 642 if (swap_pager_reserve(vn->sc_object, 0, vn->sc_size) < 0) { 643 vm_pager_deallocate(vn->sc_object); 644 vn->sc_object = NULL; 645 return(EDOM); 646 } 647 } 648 vn->sc_flags |= VNF_INITED; 649 650 error = vnsetcred(vn, cred); 651 if (error == 0) { 652 /* 653 * Set the disk info so that probing is triggered 654 */ 655 bzero(&info, sizeof(struct disk_info)); 656 info.d_media_blksize = vn->sc_secsize; 657 info.d_media_blocks = vn->sc_size; 658 /* 659 * reserve mbr sector for backwards compatibility 660 * when no slices exist. 661 */ 662 info.d_dsflags = DSO_COMPATMBR | DSO_RAWPSIZE; 663 info.d_secpertrack = 32; 664 info.d_nheads = 64 / (vn->sc_secsize / DEV_BSIZE); 665 info.d_secpercyl = info.d_secpertrack * info.d_nheads; 666 info.d_ncylinders = vn->sc_size / info.d_secpercyl; 667 disk_setdiskinfo_sync(&vn->sc_disk, &info); 668 669 error = dev_dopen(dev, flag, S_IFCHR, cred, NULL); 670 } 671 if (error == 0) { 672 IFOPT(vn, VN_FOLLOW) { 673 kprintf("vnioctl: SET vp %p size %llx\n", 674 vn->sc_vp, (long long)vn->sc_size); 675 } 676 } 677 if (error) 678 vnclear(vn); 679 return(error); 680 } 681 682 /* 683 * Duplicate the current processes' credentials. Since we are called only 684 * as the result of a SET ioctl and only root can do that, any future access 685 * to this "disk" is essentially as root. Note that credentials may change 686 * if some other uid can write directly to the mapped file (NFS). 687 */ 688 int 689 vnsetcred(struct vn_softc *vn, struct ucred *cred) 690 { 691 char *tmpbuf; 692 int error = 0; 693 694 /* 695 * Set credits in our softc 696 */ 697 698 if (vn->sc_cred) 699 crfree(vn->sc_cred); 700 vn->sc_cred = crdup(cred); 701 702 /* 703 * Horrible kludge to establish credentials for NFS XXX. 704 */ 705 706 if (vn->sc_vp) { 707 struct uio auio; 708 struct iovec aiov; 709 710 tmpbuf = kmalloc(vn->sc_secsize, M_TEMP, M_WAITOK); 711 bzero(&auio, sizeof(auio)); 712 713 aiov.iov_base = tmpbuf; 714 aiov.iov_len = vn->sc_secsize; 715 auio.uio_iov = &aiov; 716 auio.uio_iovcnt = 1; 717 auio.uio_offset = 0; 718 auio.uio_rw = UIO_READ; 719 auio.uio_segflg = UIO_SYSSPACE; 720 auio.uio_resid = aiov.iov_len; 721 vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY); 722 error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred); 723 vn_unlock(vn->sc_vp); 724 kfree(tmpbuf, M_TEMP); 725 } 726 return (error); 727 } 728 729 void 730 vnclear(struct vn_softc *vn) 731 { 732 IFOPT(vn, VN_FOLLOW) 733 kprintf("vnclear(%p): vp=%p\n", vn, vn->sc_vp); 734 vn->sc_flags &= ~VNF_INITED; 735 if (vn->sc_vp != NULL) { 736 vn_close(vn->sc_vp, 737 (vn->sc_flags & VNF_READONLY) ? FREAD : (FREAD|FWRITE), 738 NULL); 739 vn->sc_vp = NULL; 740 } 741 vn->sc_flags &= ~VNF_READONLY; 742 if (vn->sc_cred) { 743 crfree(vn->sc_cred); 744 vn->sc_cred = NULL; 745 } 746 if (vn->sc_object != NULL) { 747 vm_pager_deallocate(vn->sc_object); 748 vn->sc_object = NULL; 749 } 750 751 disk_unprobe(&vn->sc_disk); 752 753 vn->sc_size = 0; 754 } 755 756 /* 757 * vnget: 758 * 759 * populate a struct vn_user for the VNIOCGET ioctl. 760 * interface conventions defined in sys/sys/vnioctl.h. 761 */ 762 763 static int 764 vnget(cdev_t dev, struct vn_softc *vn, struct vn_user *vnu) 765 { 766 int error, found = 0; 767 char *freepath, *fullpath; 768 struct vattr vattr; 769 770 if (vnu->vnu_unit == -1) { 771 vnu->vnu_unit = dkunit(dev); 772 } 773 else if (vnu->vnu_unit < 0) 774 return (EINVAL); 775 776 SLIST_FOREACH(vn, &vn_list, sc_list) { 777 778 if(vn->sc_unit != vnu->vnu_unit) 779 continue; 780 781 found = 1; 782 783 if (vn->sc_flags & VNF_INITED && vn->sc_vp != NULL) { 784 785 /* note: u_cred checked in vnioctl above */ 786 error = VOP_GETATTR(vn->sc_vp, &vattr); 787 if (error) { 788 kprintf("vnget: VOP_GETATTR for %p failed\n", 789 vn->sc_vp); 790 return (error); 791 } 792 793 error = vn_fullpath(curproc, vn->sc_vp, 794 &fullpath, &freepath, 0); 795 796 if (error) { 797 kprintf("vnget: unable to resolve vp %p\n", 798 vn->sc_vp); 799 return(error); 800 } 801 802 strlcpy(vnu->vnu_file, fullpath, 803 sizeof(vnu->vnu_file)); 804 kfree(freepath, M_TEMP); 805 vnu->vnu_dev = vattr.va_fsid; 806 vnu->vnu_ino = vattr.va_fileid; 807 808 } 809 else if (vn->sc_flags & VNF_INITED && vn->sc_object != NULL){ 810 811 strlcpy(vnu->vnu_file, _VN_USER_SWAP, 812 sizeof(vnu->vnu_file)); 813 vnu->vnu_size = vn->sc_size; 814 vnu->vnu_secsize = vn->sc_secsize; 815 816 } else { 817 818 bzero(vnu->vnu_file, sizeof(vnu->vnu_file)); 819 vnu->vnu_dev = 0; 820 vnu->vnu_ino = 0; 821 822 } 823 break; 824 } 825 826 if (!found) 827 return(ENXIO); 828 829 return(0); 830 } 831 832 static int 833 vnsize(struct dev_psize_args *ap) 834 { 835 cdev_t dev = ap->a_head.a_dev; 836 struct vn_softc *vn; 837 838 vn = dev->si_drv1; 839 if (!vn) 840 return(ENXIO); 841 if ((vn->sc_flags & VNF_INITED) == 0) 842 return(ENXIO); 843 ap->a_result = (int64_t)vn->sc_size; 844 return(0); 845 } 846 847 static cdev_t 848 vn_create(int unit, struct devfs_bitmap *bitmap, int clone) 849 { 850 struct vn_softc *vn; 851 struct disk_info info; 852 cdev_t dev, ret_dev; 853 854 vn = vncreatevn(); 855 if (clone) { 856 /* 857 * For clone devices we need to return the top-level cdev, 858 * not the raw dev we'd normally work with. 859 */ 860 dev = disk_create_clone(unit, &vn->sc_disk, &vn_ops); 861 ret_dev = vn->sc_disk.d_cdev; 862 } else { 863 ret_dev = dev = disk_create(unit, &vn->sc_disk, &vn_ops); 864 } 865 vninitvn(vn, dev); 866 867 bzero(&info, sizeof(struct disk_info)); 868 info.d_media_blksize = 512; 869 info.d_media_blocks = 0; 870 info.d_dsflags = DSO_MBRQUIET | DSO_RAWPSIZE; 871 info.d_secpertrack = 32; 872 info.d_nheads = 64; 873 info.d_secpercyl = info.d_secpertrack * info.d_nheads; 874 info.d_ncylinders = 0; 875 disk_setdiskinfo_sync(&vn->sc_disk, &info); 876 877 if (bitmap != NULL) 878 devfs_clone_bitmap_set(bitmap, unit); 879 880 return ret_dev; 881 } 882 883 static int 884 vn_modevent(module_t mod, int type, void *data) 885 { 886 struct vn_softc *vn; 887 static cdev_t dev = NULL; 888 int i; 889 890 switch (type) { 891 case MOD_LOAD: 892 dev = make_autoclone_dev(&vn_ops, &DEVFS_CLONE_BITMAP(vn), vnclone, UID_ROOT, 893 GID_OPERATOR, 0640, "vn"); 894 895 for (i = 0; i < VN_PREALLOCATED_UNITS; i++) { 896 vn_create(i, &DEVFS_CLONE_BITMAP(vn), 0); 897 } 898 break; 899 900 case MOD_UNLOAD: 901 case MOD_SHUTDOWN: 902 while ((vn = SLIST_FIRST(&vn_list)) != NULL) { 903 /* 904 * XXX: no idea if we can return EBUSY even in the 905 * shutdown case, so err on the side of caution 906 * and just rip stuff out on shutdown. 907 */ 908 if (type != MOD_SHUTDOWN) { 909 if (vn->sc_flags & VNF_OPENED) 910 return (EBUSY); 911 } 912 913 disk_destroy(&vn->sc_disk); 914 915 SLIST_REMOVE_HEAD(&vn_list, sc_list); 916 917 if (vn->sc_flags & VNF_INITED) 918 vnclear(vn); 919 920 kfree(vn, M_VN); 921 } 922 destroy_autoclone_dev(dev, &DEVFS_CLONE_BITMAP(vn)); 923 dev_ops_remove_all(&vn_ops); 924 break; 925 default: 926 break; 927 } 928 return 0; 929 } 930 931 DEV_MODULE(vn, vn_modevent, 0); 932