1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)spec_vnops.c 7.37 (Berkeley) 5/30/91 34 * $Id: spec_vnops.c,v 1.5 1993/08/23 05:02:06 cgd Exp $ 35 */ 36 37 #include "param.h" 38 #include "proc.h" 39 #include "systm.h" 40 #include "kernel.h" 41 #include "conf.h" 42 #include "buf.h" 43 #include "mount.h" 44 #include "namei.h" 45 #include "vnode.h" 46 #include "specdev.h" 47 #include "stat.h" 48 #include "errno.h" 49 #include "ioctl.h" 50 #include "file.h" 51 #include "dkbad.h" /* XXX */ 52 #include "disklabel.h" 53 54 /* symbolic sleep message strings for devices */ 55 char devopn[] = "devopn"; 56 char devio[] = "devio"; 57 char devwait[] = "devwait"; 58 char devin[] = "devin"; 59 char devout[] = "devout"; 60 char devioc[] = "devioc"; 61 char devcls[] = "devcls"; 62 63 struct vnodeops spec_vnodeops = { 64 spec_lookup, /* lookup */ 65 spec_create, /* create */ 66 spec_mknod, /* mknod */ 67 spec_open, /* open */ 68 spec_close, /* close */ 69 spec_access, /* access */ 70 spec_getattr, /* getattr */ 71 spec_setattr, /* setattr */ 72 spec_read, /* read */ 73 spec_write, /* write */ 74 spec_ioctl, /* ioctl */ 75 spec_select, /* select */ 76 spec_mmap, /* mmap */ 77 spec_fsync, /* fsync */ 78 spec_seek, /* seek */ 79 spec_remove, /* remove */ 80 spec_link, /* link */ 81 spec_rename, /* rename */ 82 spec_mkdir, /* mkdir */ 83 spec_rmdir, /* rmdir */ 84 spec_symlink, /* symlink */ 85 spec_readdir, /* readdir */ 86 spec_readlink, /* readlink */ 87 spec_abortop, /* abortop */ 88 spec_inactive, /* inactive */ 89 spec_reclaim, /* reclaim */ 90 spec_lock, /* lock */ 91 spec_unlock, /* unlock */ 92 spec_bmap, /* bmap */ 93 spec_strategy, /* strategy */ 94 spec_print, /* print */ 95 spec_islocked, /* islocked */ 96 spec_advlock, /* advlock */ 97 }; 98 99 /* 100 * Trivial lookup routine that always fails. 101 */ 102 int 103 spec_lookup(vp, ndp, p) 104 struct vnode *vp; 105 struct nameidata *ndp; 106 struct proc *p; 107 { 108 109 ndp->ni_dvp = vp; 110 ndp->ni_vp = NULL; 111 return (ENOTDIR); 112 } 113 114 /* 115 * Open a special file: Don't allow open if fs is mounted -nodev, 116 * and don't allow opens of block devices that are currently mounted. 117 * Otherwise, call device driver open function. 118 */ 119 /* ARGSUSED */ 120 int 121 spec_open(vp, mode, cred, p) 122 register struct vnode *vp; 123 int mode; 124 struct ucred *cred; 125 struct proc *p; 126 { 127 dev_t dev = (dev_t)vp->v_rdev; 128 register int maj = major(dev); 129 int error; 130 131 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) 132 return (ENXIO); 133 134 switch (vp->v_type) { 135 136 case VCHR: 137 if ((u_int)maj >= nchrdev) 138 return (ENXIO); 139 VOP_UNLOCK(vp); 140 error = (*cdevsw[maj].d_open)(dev, mode, S_IFCHR, p); 141 VOP_LOCK(vp); 142 return (error); 143 144 case VBLK: 145 if ((u_int)maj >= nblkdev) 146 return (ENXIO); 147 if (error = mountedon(vp)) 148 return (error); 149 return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK, p)); 150 151 default: 152 return (0); 153 } 154 } 155 156 /* 157 * Vnode op for read 158 */ 159 /* ARGSUSED */ 160 int 161 spec_read(vp, uio, ioflag, cred) 162 register struct vnode *vp; 163 register struct uio *uio; 164 int ioflag; 165 struct ucred *cred; 166 { 167 struct proc *p = uio->uio_procp; 168 struct buf *bp; 169 daddr_t bn; 170 long bsize, bscale; 171 struct partinfo dpart; 172 register int n, on; 173 int error = 0; 174 extern int mem_no; 175 176 #ifdef DIAGNOSTIC 177 if (uio->uio_rw != UIO_READ) 178 panic("spec_read mode"); 179 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 180 panic("spec_read proc"); 181 #endif 182 if (uio->uio_resid == 0) 183 return (0); 184 185 switch (vp->v_type) { 186 187 case VCHR: 188 /* 189 * Negative offsets allowed only for /dev/kmem 190 */ 191 if (uio->uio_offset < 0 && major(vp->v_rdev) != mem_no) 192 return (EINVAL); 193 VOP_UNLOCK(vp); 194 error = (*cdevsw[major(vp->v_rdev)].d_read) 195 (vp->v_rdev, uio, ioflag); 196 VOP_LOCK(vp); 197 return (error); 198 199 case VBLK: 200 if (uio->uio_offset < 0) 201 return (EINVAL); 202 bsize = BLKDEV_IOSIZE; 203 if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, 204 (caddr_t)&dpart, FREAD, p) == 0) { 205 if (dpart.part->p_fstype == FS_BSDFFS && 206 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 207 bsize = dpart.part->p_frag * 208 dpart.part->p_fsize; 209 } 210 bscale = bsize / DEV_BSIZE; 211 do { 212 bn = (uio->uio_offset / DEV_BSIZE) &~ (bscale - 1); 213 on = uio->uio_offset % bsize; 214 n = MIN((unsigned)(bsize - on), uio->uio_resid); 215 if (vp->v_lastr + bscale == bn) 216 error = breada(vp, bn, (int)bsize, bn + bscale, 217 (int)bsize, NOCRED, &bp); 218 else 219 error = bread(vp, bn, (int)bsize, NOCRED, &bp); 220 vp->v_lastr = bn; 221 n = MIN(n, bsize - bp->b_resid); 222 if (error) { 223 brelse(bp); 224 return (error); 225 } 226 error = uiomove(bp->b_un.b_addr + on, n, uio); 227 #ifdef OMIT /* 20 Aug 92*/ 228 if (n + on == bsize) 229 bp->b_flags |= B_AGE; 230 #endif /* OMIT*/ 231 brelse(bp); 232 } while (error == 0 && uio->uio_resid > 0 && n != 0); 233 return (error); 234 235 default: 236 panic("spec_read type"); 237 } 238 /* NOTREACHED */ 239 } 240 241 /* 242 * Vnode op for write 243 */ 244 /* ARGSUSED */ 245 int 246 spec_write(vp, uio, ioflag, cred) 247 register struct vnode *vp; 248 register struct uio *uio; 249 int ioflag; 250 struct ucred *cred; 251 { 252 struct proc *p = uio->uio_procp; 253 struct buf *bp; 254 daddr_t bn; 255 int bsize, blkmask; 256 struct partinfo dpart; 257 register int n, on; 258 int error = 0; 259 extern int mem_no; 260 261 #ifdef DIAGNOSTIC 262 if (uio->uio_rw != UIO_WRITE) 263 panic("spec_write mode"); 264 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 265 panic("spec_write proc"); 266 #endif 267 268 switch (vp->v_type) { 269 270 case VCHR: 271 /* 272 * Negative offsets allowed only for /dev/kmem 273 */ 274 if (uio->uio_offset < 0 && major(vp->v_rdev) != mem_no) 275 return (EINVAL); 276 VOP_UNLOCK(vp); 277 error = (*cdevsw[major(vp->v_rdev)].d_write) 278 (vp->v_rdev, uio, ioflag); 279 VOP_LOCK(vp); 280 return (error); 281 282 case VBLK: 283 if (uio->uio_resid == 0) 284 return (0); 285 if (uio->uio_offset < 0) 286 return (EINVAL); 287 bsize = BLKDEV_IOSIZE; 288 if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, 289 (caddr_t)&dpart, FREAD, p) == 0) { 290 if (dpart.part->p_fstype == FS_BSDFFS && 291 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 292 bsize = dpart.part->p_frag * 293 dpart.part->p_fsize; 294 } 295 blkmask = (bsize / DEV_BSIZE) - 1; 296 do { 297 bn = (uio->uio_offset / DEV_BSIZE) &~ blkmask; 298 on = uio->uio_offset % bsize; 299 n = MIN((unsigned)(bsize - on), uio->uio_resid); 300 if (n == bsize) 301 bp = getblk(vp, bn, bsize); 302 else 303 error = bread(vp, bn, bsize, NOCRED, &bp); 304 n = MIN(n, bsize - bp->b_resid); 305 if (error) { 306 brelse(bp); 307 return (error); 308 } 309 error = uiomove(bp->b_un.b_addr + on, n, uio); 310 if (n + on == bsize) { 311 bp->b_flags |= B_AGE; 312 bawrite(bp); 313 } else 314 bdwrite(bp); 315 } while (error == 0 && uio->uio_resid > 0 && n != 0); 316 return (error); 317 318 default: 319 panic("spec_write type"); 320 } 321 /* NOTREACHED */ 322 } 323 324 /* 325 * Device ioctl operation. 326 */ 327 /* ARGSUSED */ 328 int 329 spec_ioctl(vp, com, data, fflag, cred, p) 330 struct vnode *vp; 331 int com; 332 caddr_t data; 333 int fflag; 334 struct ucred *cred; 335 struct proc *p; 336 { 337 dev_t dev = vp->v_rdev; 338 339 switch (vp->v_type) { 340 341 case VCHR: 342 return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data, 343 fflag, p)); 344 345 case VBLK: 346 if (com == 0 && (int)data == B_TAPE) 347 if (bdevsw[major(dev)].d_flags & B_TAPE) 348 return (0); 349 else 350 return (1); 351 return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data, 352 fflag, p)); 353 354 default: 355 panic("spec_ioctl"); 356 /* NOTREACHED */ 357 } 358 } 359 360 /* ARGSUSED */ 361 int 362 spec_select(vp, which, fflags, cred, p) 363 struct vnode *vp; 364 int which, fflags; 365 struct ucred *cred; 366 struct proc *p; 367 { 368 register dev_t dev; 369 370 switch (vp->v_type) { 371 372 default: 373 return (1); /* XXX */ 374 375 case VCHR: 376 dev = vp->v_rdev; 377 return (*cdevsw[major(dev)].d_select)(dev, which, p); 378 } 379 } 380 381 /* 382 * Just call the device strategy routine 383 */ 384 int 385 spec_strategy(bp) 386 register struct buf *bp; 387 { 388 389 (*bdevsw[major(bp->b_dev)].d_strategy)(bp); 390 return (0); 391 } 392 393 /* 394 * This is a noop, simply returning what one has been given. 395 */ 396 int 397 spec_bmap(vp, bn, vpp, bnp) 398 struct vnode *vp; 399 daddr_t bn; 400 struct vnode **vpp; 401 daddr_t *bnp; 402 { 403 404 if (vpp != NULL) 405 *vpp = vp; 406 if (bnp != NULL) 407 *bnp = bn; 408 return (0); 409 } 410 411 /* 412 * At the moment we do not do any locking. 413 */ 414 /* ARGSUSED */ 415 int 416 spec_lock(vp) 417 struct vnode *vp; 418 { 419 420 return (0); 421 } 422 423 /* ARGSUSED */ 424 int 425 spec_unlock(vp) 426 struct vnode *vp; 427 { 428 429 return (0); 430 } 431 432 /* 433 * Device close routine 434 */ 435 /* ARGSUSED */ 436 int 437 spec_close(vp, flag, cred, p) 438 register struct vnode *vp; 439 int flag; 440 struct ucred *cred; 441 struct proc *p; 442 { 443 dev_t dev = vp->v_rdev; 444 int (*devclose) __P((dev_t, int, int, struct proc *)); 445 int mode; 446 447 switch (vp->v_type) { 448 449 case VCHR: 450 /* 451 * If the vnode is locked, then we are in the midst 452 * of forcably closing the device, otherwise we only 453 * close on last reference. 454 */ 455 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) 456 return (0); 457 devclose = cdevsw[major(dev)].d_close; 458 mode = S_IFCHR; 459 break; 460 461 case VBLK: 462 /* 463 * On last close of a block device (that isn't mounted) 464 * we must invalidate any in core blocks, so that 465 * we can, for instance, change floppy disks. 466 */ 467 vflushbuf(vp, 0); 468 if (vinvalbuf(vp, 1)) 469 return (0); 470 /* 471 * We do not want to really close the device if it 472 * is still in use unless we are trying to close it 473 * forcibly. Since every use (buffer, vnode, swap, cmap) 474 * holds a reference to the vnode, and because we mark 475 * any other vnodes that alias this device, when the 476 * sum of the reference counts on all the aliased 477 * vnodes descends to one, we are on last close. 478 */ 479 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) 480 return (0); 481 devclose = bdevsw[major(dev)].d_close; 482 mode = S_IFBLK; 483 break; 484 485 #ifdef DEBUG 486 case VBAD: 487 vprint("spec_close: close VBAD vnode", vp); 488 break; 489 #endif 490 491 default: 492 panic("spec_close: not special"); 493 } 494 495 return ((*devclose)(dev, flag, mode, p)); 496 } 497 498 /* 499 * Print out the contents of a special device vnode. 500 */ 501 void 502 spec_print(vp) 503 struct vnode *vp; 504 { 505 506 printf("tag VT_NON, dev %d, %d\n", major(vp->v_rdev), 507 minor(vp->v_rdev)); 508 } 509 510 /* 511 * Special device advisory byte-level locks. 512 */ 513 /* ARGSUSED */ 514 int 515 spec_advlock(vp, id, op, fl, flags) 516 struct vnode *vp; 517 caddr_t id; 518 int op; 519 struct flock *fl; 520 int flags; 521 { 522 523 return (EOPNOTSUPP); 524 } 525 526 /* 527 * Special device failed operation 528 */ 529 int 530 spec_ebadf() 531 { 532 533 return (EBADF); 534 } 535 536 /* 537 * Special device bad operation 538 */ 539 int 540 spec_badop() 541 { 542 543 panic("spec_badop called"); 544 /* NOTREACHED */ 545 } 546