|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1988 University of Utah. ! 28: * Copyright (c) 1990, 1993 ! 29: * The Regents of the University of California. All rights reserved. ! 30: * ! 31: * This code is derived from software contributed to Berkeley by ! 32: * the Systems Programming Group of the University of Utah Computer ! 33: * Science Department. ! 34: * ! 35: * Redistribution and use in source and binary forms, with or without ! 36: * modification, are permitted provided that the following conditions ! 37: * are met: ! 38: * 1. Redistributions of source code must retain the above copyright ! 39: * notice, this list of conditions and the following disclaimer. ! 40: * 2. Redistributions in binary form must reproduce the above copyright ! 41: * notice, this list of conditions and the following disclaimer in the ! 42: * documentation and/or other materials provided with the distribution. ! 43: * 3. All advertising materials mentioning features or use of this software ! 44: * must display the following acknowledgement: ! 45: * This product includes software developed by the University of ! 46: * California, Berkeley and its contributors. ! 47: * 4. Neither the name of the University nor the names of its contributors ! 48: * may be used to endorse or promote products derived from this software ! 49: * without specific prior written permission. ! 50: * ! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 61: * SUCH DAMAGE. ! 62: * ! 63: * from: Utah $Hdr: vn.c 1.13 94/04/02$ ! 64: * ! 65: * @(#)vn.c 8.9 (Berkeley) 5/14/95 ! 66: */ ! 67: ! 68: /* ! 69: * Vnode disk driver. ! 70: * ! 71: * Block/character interface to a vnode. Allows one to treat a file ! 72: * as a disk (e.g. build a filesystem in it, mount it, etc.). ! 73: * ! 74: * NOTE 1: This uses the VOP_BMAP/VOP_STRATEGY interface to the vnode ! 75: * instead of a simple VOP_RDWR. We do this to avoid distorting the ! 76: * local buffer cache. ! 77: * ! 78: * NOTE 2: There is a security issue involved with this driver. ! 79: * Once mounted all access to the contents of the "mapped" file via ! 80: * the special file is controlled by the permissions on the special ! 81: * file, the protection of the mapped file is ignored (effectively, ! 82: * by using root credentials in all transactions). ! 83: * ! 84: * NOTE 3: Doesn't interact with leases, should it? ! 85: */ ! 86: #include "vnd.h" ! 87: #if NVND > 0 ! 88: ! 89: #include <sys/param.h> ! 90: #include <sys/systm.h> ! 91: #include <sys/namei.h> ! 92: #include <sys/proc.h> ! 93: #include <sys/errno.h> ! 94: #include <sys/dkstat.h> ! 95: #include <sys/buf.h> ! 96: #include <sys/malloc.h> ! 97: #include <sys/ioctl.h> ! 98: #include <sys/disklabel.h> ! 99: #include <sys/mount.h> ! 100: #include <sys/vnode.h> ! 101: #include <sys/file.h> ! 102: #include <sys/uio.h> ! 103: ! 104: #include <miscfs/specfs/specdev.h> ! 105: ! 106: #include <dev/vndioctl.h> ! 107: ! 108: #ifdef DEBUG ! 109: int dovndcluster = 1; ! 110: int vnddebug = 0x00; ! 111: #define VDB_FOLLOW 0x01 ! 112: #define VDB_INIT 0x02 ! 113: #define VDB_IO 0x04 ! 114: #endif ! 115: ! 116: #define b_cylin b_resid ! 117: ! 118: #define vndunit(x) DISKUNIT(x) ! 119: ! 120: struct vndbuf { ! 121: struct buf vb_buf; ! 122: struct buf *vb_obp; ! 123: }; ! 124: ! 125: //#define getvndbuf() \ ! 126: // ((struct vndbuf *)malloc(sizeof(struct vndbuf), M_DEVBUF, M_WAITOK)) ! 127: #define putvndbuf(vbp) \ ! 128: free((caddr_t)(vbp), M_DEVBUF) ! 129: ! 130: struct vnd_softc { ! 131: int sc_flags; /* flags */ ! 132: size_t sc_size; /* size of vnd */ ! 133: struct vnode *sc_vp; /* vnode */ ! 134: struct ucred *sc_cred; /* credentials */ ! 135: int sc_maxactive; /* max # of active requests */ ! 136: struct buf sc_tab; /* transfer queue */ ! 137: }; ! 138: ! 139: /* sc_flags */ ! 140: #define VNF_ALIVE 0x01 ! 141: #define VNF_INITED 0x02 ! 142: ! 143: #if 0 /* if you need static allocation */ ! 144: struct vnd_softc vn_softc[NVND]; ! 145: int numvnd = NVND; ! 146: #else ! 147: struct vnd_softc *vnd_softc; ! 148: int numvnd; ! 149: #endif ! 150: ! 151: void vndclear __P((struct vnd_softc *)); ! 152: void vndstart __P((struct vnd_softc *)); ! 153: int vndsetcred __P((struct vnd_softc *, struct ucred *)); ! 154: void vndthrottle __P((struct vnd_softc *, struct vnode *)); ! 155: ! 156: void ! 157: vndattach(num) ! 158: int num; ! 159: { ! 160: char *mem; ! 161: register u_long size; ! 162: ! 163: if (num <= 0) ! 164: return; ! 165: size = num * sizeof(struct vnd_softc); ! 166: // mem = malloc(size, M_DEVBUF, M_NOWAIT); ! 167: MALLOC(mem, char *, size, M_DEVBUF, M_NOWAIT); ! 168: if (mem == NULL) { ! 169: printf("WARNING: no memory for vnode disks\n"); ! 170: return; ! 171: } ! 172: bzero(mem, size); ! 173: vnd_softc = (struct vnd_softc *)mem; ! 174: numvnd = num; ! 175: } ! 176: ! 177: int ! 178: vndopen(dev, flags, mode, p) ! 179: dev_t dev; ! 180: int flags, mode; ! 181: struct proc *p; ! 182: { ! 183: int unit = vndunit(dev); ! 184: ! 185: #ifdef DEBUG ! 186: if (vnddebug & VDB_FOLLOW) ! 187: printf("vndopen(%x, %x, %x, %x)\n", dev, flags, mode, p); ! 188: #endif ! 189: if (unit >= numvnd) ! 190: return(ENXIO); ! 191: return(0); ! 192: } ! 193: ! 194: int ! 195: vndclose(dev, flags, mode, p) ! 196: dev_t dev; ! 197: int flags, mode; ! 198: struct proc *p; ! 199: { ! 200: #ifdef DEBUG ! 201: if (vnddebug & VDB_FOLLOW) ! 202: printf("vndclose(%x, %x, %x, %x)\n", dev, flags, mode, p); ! 203: #endif ! 204: return 0; ! 205: } ! 206: ! 207: /* ! 208: * Break the request into bsize pieces and submit using VOP_BMAP/VOP_STRATEGY. ! 209: * Note that this driver can only be used for swapping over NFS on the hp ! 210: * since nfs_strategy on the vax cannot handle u-areas and page tables. ! 211: */ ! 212: void ! 213: vndstrategy(bp) ! 214: register struct buf *bp; ! 215: { ! 216: int unit = vndunit(bp->b_dev); ! 217: register struct vnd_softc *vnd = &vnd_softc[unit]; ! 218: register struct vndbuf *nbp; ! 219: register int bn, bsize, resid; ! 220: register caddr_t addr; ! 221: int sz, flags, error; ! 222: extern void vndiodone(); ! 223: ! 224: #ifdef DEBUG ! 225: if (vnddebug & VDB_FOLLOW) ! 226: printf("vndstrategy(%x): unit %d\n", bp, unit); ! 227: #endif ! 228: if ((vnd->sc_flags & VNF_INITED) == 0) { ! 229: bp->b_error = ENXIO; ! 230: bp->b_flags |= B_ERROR; ! 231: biodone(bp); ! 232: return; ! 233: } ! 234: bn = bp->b_blkno; ! 235: sz = howmany(bp->b_bcount, DEV_BSIZE); ! 236: bp->b_resid = bp->b_bcount; ! 237: if (bn < 0 || bn + sz > vnd->sc_size) { ! 238: if (bn != vnd->sc_size) { ! 239: bp->b_error = EINVAL; ! 240: bp->b_flags |= B_ERROR; ! 241: } ! 242: biodone(bp); ! 243: return; ! 244: } ! 245: bn = dbtob(bn); ! 246: bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize; ! 247: addr = bp->b_data; ! 248: flags = bp->b_flags | B_CALL; ! 249: for (resid = bp->b_resid; resid; resid -= sz) { ! 250: struct vnode *vp; ! 251: daddr_t nbn; ! 252: int off, s, nra; ! 253: ! 254: nra = 0; ! 255: error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra); ! 256: if (error == 0 && (long)nbn == -1) ! 257: error = EIO; ! 258: #ifdef DEBUG ! 259: if (!dovndcluster) ! 260: nra = 0; ! 261: #endif ! 262: ! 263: if (off = bn % bsize) ! 264: sz = bsize - off; ! 265: else ! 266: sz = (1 + nra) * bsize; ! 267: if (resid < sz) ! 268: sz = resid; ! 269: #ifdef DEBUG ! 270: if (vnddebug & VDB_IO) ! 271: printf("vndstrategy: vp %x/%x bn %x/%x sz %x\n", ! 272: vnd->sc_vp, vp, bn, nbn, sz); ! 273: #endif ! 274: ! 275: // nbp = getvndbuf(); ! 276: MALLOC(nbp, struct vndbuf *, sizeof(struct vndbuf),M_DEVBUF, M_WAITOK); ! 277: nbp->vb_buf.b_flags = flags; ! 278: nbp->vb_buf.b_bcount = sz; ! 279: nbp->vb_buf.b_bufsize = bp->b_bufsize; ! 280: nbp->vb_buf.b_error = 0; ! 281: if (vp->v_type == VBLK || vp->v_type == VCHR) ! 282: nbp->vb_buf.b_dev = vp->v_rdev; ! 283: else ! 284: nbp->vb_buf.b_dev = NODEV; ! 285: nbp->vb_buf.b_data = addr; ! 286: nbp->vb_buf.b_blkno = nbn + btodb(off); ! 287: nbp->vb_buf.b_proc = bp->b_proc; ! 288: nbp->vb_buf.b_iodone = vndiodone; ! 289: nbp->vb_buf.b_vp = vp; ! 290: nbp->vb_buf.b_rcred = vnd->sc_cred; /* XXX crdup? */ ! 291: nbp->vb_buf.b_wcred = vnd->sc_cred; /* XXX crdup? */ ! 292: nbp->vb_buf.b_dirtyoff = bp->b_dirtyoff; ! 293: nbp->vb_buf.b_dirtyend = bp->b_dirtyend; ! 294: nbp->vb_buf.b_validoff = bp->b_validoff; ! 295: nbp->vb_buf.b_validend = bp->b_validend; ! 296: ! 297: /* save a reference to the old buffer */ ! 298: nbp->vb_obp = bp; ! 299: ! 300: /* ! 301: * If there was an error or a hole in the file...punt. ! 302: * Note that we deal with this after the nbp allocation. ! 303: * This ensures that we properly clean up any operations ! 304: * that we have already fired off. ! 305: * ! 306: * XXX we could deal with holes here but it would be ! 307: * a hassle (in the write case). ! 308: */ ! 309: if (error) { ! 310: nbp->vb_buf.b_error = error; ! 311: nbp->vb_buf.b_flags |= B_ERROR; ! 312: bp->b_resid -= (resid - sz); ! 313: biodone(&nbp->vb_buf); ! 314: return; ! 315: } ! 316: /* ! 317: * Just sort by block number ! 318: */ ! 319: nbp->vb_buf.b_cylin = nbp->vb_buf.b_blkno; ! 320: s = splbio(); ! 321: disksort(&vnd->sc_tab, &nbp->vb_buf); ! 322: if (vnd->sc_tab.b_active < vnd->sc_maxactive) { ! 323: vnd->sc_tab.b_active++; ! 324: vndstart(vnd); ! 325: } ! 326: splx(s); ! 327: bn += sz; ! 328: addr += sz; ! 329: } ! 330: } ! 331: ! 332: /* ! 333: * Feed requests sequentially. ! 334: * We do it this way to keep from flooding NFS servers if we are connected ! 335: * to an NFS file. This places the burden on the client rather than the ! 336: * server. ! 337: */ ! 338: void ! 339: vndstart(vnd) ! 340: register struct vnd_softc *vnd; ! 341: { ! 342: register struct buf *bp; ! 343: ! 344: /* ! 345: * Dequeue now since lower level strategy routine might ! 346: * queue using same links ! 347: */ ! 348: bp = vnd->sc_tab.b_actf; ! 349: vnd->sc_tab.b_actf = bp->b_actf; ! 350: #ifdef DEBUG ! 351: if (vnddebug & VDB_IO) ! 352: printf("vndstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n", ! 353: vnd-vnd_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data, ! 354: bp->b_bcount); ! 355: #endif ! 356: if ((bp->b_flags & B_READ) == 0) ! 357: bp->b_vp->v_numoutput++; ! 358: VOP_STRATEGY(bp); ! 359: } ! 360: ! 361: void ! 362: vndiodone(vbp) ! 363: register struct vndbuf *vbp; ! 364: { ! 365: register struct buf *pbp = vbp->vb_obp; ! 366: register struct vnd_softc *vnd = &vnd_softc[vndunit(pbp->b_dev)]; ! 367: int s; ! 368: ! 369: s = splbio(); ! 370: #ifdef DEBUG ! 371: if (vnddebug & VDB_IO) ! 372: printf("vndiodone(%d): vbp %x vp %x blkno %x addr %x cnt %x\n", ! 373: vnd-vnd_softc, vbp, vbp->vb_buf.b_vp, vbp->vb_buf.b_blkno, ! 374: vbp->vb_buf.b_data, vbp->vb_buf.b_bcount); ! 375: #endif ! 376: if (vbp->vb_buf.b_error) { ! 377: #ifdef DEBUG ! 378: if (vnddebug & VDB_IO) ! 379: printf("vndiodone: vbp %x error %d\n", vbp, ! 380: vbp->vb_buf.b_error); ! 381: #endif ! 382: pbp->b_flags |= B_ERROR; ! 383: pbp->b_error = biowait(&vbp->vb_buf); ! 384: } ! 385: pbp->b_resid -= vbp->vb_buf.b_bcount; ! 386: putvndbuf(vbp); ! 387: if (pbp->b_resid == 0) { ! 388: #ifdef DEBUG ! 389: if (vnddebug & VDB_IO) ! 390: printf("vndiodone: pbp %x iodone\n", pbp); ! 391: #endif ! 392: biodone(pbp); ! 393: } ! 394: if (vnd->sc_tab.b_actf) ! 395: vndstart(vnd); ! 396: else ! 397: vnd->sc_tab.b_active--; ! 398: splx(s); ! 399: } ! 400: ! 401: /* ARGSUSED */ ! 402: int ! 403: vndioctl(dev, cmd, data, flag, p) ! 404: dev_t dev; ! 405: u_long cmd; ! 406: caddr_t data; ! 407: int flag; ! 408: struct proc *p; ! 409: { ! 410: int unit = vndunit(dev); ! 411: register struct vnd_softc *vnd; ! 412: struct vnd_ioctl *vio; ! 413: struct vattr vattr; ! 414: struct nameidata nd; ! 415: int error; ! 416: ! 417: #ifdef DEBUG ! 418: if (vnddebug & VDB_FOLLOW) ! 419: printf("vndioctl(%x, %lx, %x, %x, %x): unit %d\n", ! 420: dev, cmd, data, flag, p, unit); ! 421: #endif ! 422: error = suser(p->p_ucred, &p->p_acflag); ! 423: if (error) ! 424: return (error); ! 425: if (unit >= numvnd) ! 426: return (ENXIO); ! 427: ! 428: vnd = &vnd_softc[unit]; ! 429: vio = (struct vnd_ioctl *)data; ! 430: switch (cmd) { ! 431: ! 432: case VNDIOCSET: ! 433: if (vnd->sc_flags & VNF_INITED) ! 434: return(EBUSY); ! 435: /* ! 436: * Always open for read and write. ! 437: * This is probably bogus, but it lets vn_open() ! 438: * weed out directories, sockets, etc. so we don't ! 439: * have to worry about them. ! 440: */ ! 441: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p); ! 442: if (error = vn_open(&nd, FREAD|FWRITE, 0)) ! 443: return(error); ! 444: if (error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p)) { ! 445: VOP_UNLOCK(nd.ni_vp); ! 446: (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p); ! 447: return(error); ! 448: } ! 449: VOP_UNLOCK(nd.ni_vp); ! 450: vnd->sc_vp = nd.ni_vp; ! 451: vnd->sc_size = btodb(vattr.va_size); /* note truncation */ ! 452: if (error = vndsetcred(vnd, p->p_ucred)) { ! 453: (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p); ! 454: return(error); ! 455: } ! 456: vndthrottle(vnd, vnd->sc_vp); ! 457: vio->vnd_size = dbtob(vnd->sc_size); ! 458: vnd->sc_flags |= VNF_INITED; ! 459: #ifdef DEBUG ! 460: if (vnddebug & VDB_INIT) ! 461: printf("vndioctl: SET vp %x size %x\n", ! 462: vnd->sc_vp, vnd->sc_size); ! 463: #endif ! 464: break; ! 465: ! 466: case VNDIOCCLR: ! 467: if ((vnd->sc_flags & VNF_INITED) == 0) ! 468: return(ENXIO); ! 469: vndclear(vnd); ! 470: #ifdef DEBUG ! 471: if (vnddebug & VDB_INIT) ! 472: printf("vndioctl: CLRed\n"); ! 473: #endif ! 474: break; ! 475: ! 476: default: ! 477: return(ENOTTY); ! 478: } ! 479: return(0); ! 480: } ! 481: ! 482: /* ! 483: * Duplicate the current processes' credentials. Since we are called only ! 484: * as the result of a SET ioctl and only root can do that, any future access ! 485: * to this "disk" is essentially as root. Note that credentials may change ! 486: * if some other uid can write directly to the mapped file (NFS). ! 487: */ ! 488: int ! 489: vndsetcred(vnd, cred) ! 490: register struct vnd_softc *vnd; ! 491: struct ucred *cred; ! 492: { ! 493: struct uio auio; ! 494: struct iovec aiov; ! 495: char *tmpbuf; ! 496: int error; ! 497: ! 498: vnd->sc_cred = crdup(cred); ! 499: // tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK); ! 500: MALLOC(tmpbuf, char *, DEV_BSIZE, M_TEMP, M_WAITOK); ! 501: ! 502: /* XXX: Horrible kludge to establish credentials for NFS */ ! 503: aiov.iov_base = tmpbuf; ! 504: aiov.iov_len = min(DEV_BSIZE, dbtob(vnd->sc_size)); ! 505: auio.uio_iov = &aiov; ! 506: auio.uio_iovcnt = 1; ! 507: auio.uio_offset = 0; ! 508: auio.uio_rw = UIO_READ; ! 509: auio.uio_segflg = UIO_SYSSPACE; ! 510: auio.uio_resid = aiov.iov_len; ! 511: error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred); ! 512: ! 513: free(tmpbuf, M_TEMP); ! 514: return (error); ! 515: } ! 516: ! 517: /* ! 518: * Set maxactive based on FS type ! 519: */ ! 520: void ! 521: vndthrottle(vnd, vp) ! 522: register struct vnd_softc *vnd; ! 523: struct vnode *vp; ! 524: { ! 525: #ifdef NFSCLIENT ! 526: extern int (**nfsv2_vnodeop_p)(); ! 527: ! 528: if (vp->v_op == nfsv2_vnodeop_p) ! 529: vnd->sc_maxactive = 2; ! 530: else ! 531: #endif ! 532: vnd->sc_maxactive = 8; ! 533: ! 534: if (vnd->sc_maxactive < 1) ! 535: vnd->sc_maxactive = 1; ! 536: } ! 537: ! 538: void ! 539: vndshutdown() ! 540: { ! 541: register struct vnd_softc *vnd; ! 542: ! 543: for (vnd = &vnd_softc[0]; vnd < &vnd_softc[numvnd]; vnd++) ! 544: if (vnd->sc_flags & VNF_INITED) ! 545: vndclear(vnd); ! 546: } ! 547: ! 548: void ! 549: vndclear(vnd) ! 550: register struct vnd_softc *vnd; ! 551: { ! 552: register struct vnode *vp = vnd->sc_vp; ! 553: struct proc *p = curproc; /* XXX */ ! 554: struct ucred *cred; ! 555: ! 556: #ifdef DEBUG ! 557: if (vnddebug & VDB_FOLLOW) ! 558: printf("vndclear(%x): vp %x\n", vp); ! 559: #endif ! 560: vnd->sc_flags &= ~VNF_INITED; ! 561: if (vp == (struct vnode *)0) ! 562: panic("vndioctl: null vp"); ! 563: (void) vn_close(vp, FREAD|FWRITE, vnd->sc_cred, p); ! 564: cred = vnd->sc_cred; ! 565: if (cred != NOCRED) { ! 566: vnd->sc_cred = NOCRED; ! 567: crfree(cred); ! 568: } ! 569: vnd->sc_vp = (struct vnode *)0; ! 570: vnd->sc_size = 0; ! 571: } ! 572: ! 573: int ! 574: vndsize(dev) ! 575: dev_t dev; ! 576: { ! 577: int unit = vndunit(dev); ! 578: register struct vnd_softc *vnd = &vnd_softc[unit]; ! 579: ! 580: if (unit >= numvnd || (vnd->sc_flags & VNF_INITED) == 0) ! 581: return(-1); ! 582: return(vnd->sc_size); ! 583: } ! 584: ! 585: int ! 586: vnddump(dev) ! 587: dev_t dev; ! 588: { ! 589: ! 590: return(ENXIO); ! 591: } ! 592: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.