137486Smckusick /* 237486Smckusick * Copyright (c) 1989 The Regents of the University of California. 337486Smckusick * All rights reserved. 437486Smckusick * 544443Sbostic * %sccs.include.redist.c% 637486Smckusick * 7*52320Sheideman * @(#)spec_vnops.c 7.41 (Berkeley) 02/04/92 837486Smckusick */ 937486Smckusick 1051457Sbostic #include <sys/param.h> 1151457Sbostic #include <sys/proc.h> 1251457Sbostic #include <sys/systm.h> 1351457Sbostic #include <sys/kernel.h> 1451457Sbostic #include <sys/conf.h> 1551457Sbostic #include <sys/buf.h> 1651457Sbostic #include <sys/mount.h> 1751457Sbostic #include <sys/namei.h> 1851457Sbostic #include <sys/vnode.h> 1951457Sbostic #include <sys/specdev.h> 2051457Sbostic #include <sys/stat.h> 2151457Sbostic #include <sys/errno.h> 2251457Sbostic #include <sys/ioctl.h> 2351457Sbostic #include <sys/file.h> 2451457Sbostic #include <sys/disklabel.h> 2537486Smckusick 2640707Skarels /* symbolic sleep message strings for devices */ 2740707Skarels char devopn[] = "devopn"; 2840707Skarels char devio[] = "devio"; 2940707Skarels char devwait[] = "devwait"; 3040707Skarels char devin[] = "devin"; 3140707Skarels char devout[] = "devout"; 3240707Skarels char devioc[] = "devioc"; 3340707Skarels char devcls[] = "devcls"; 3440707Skarels 3539446Smckusick struct vnodeops spec_vnodeops = { 3639507Smckusick spec_lookup, /* lookup */ 3748015Smckusick spec_create, /* create */ 3848015Smckusick spec_mknod, /* mknod */ 3939507Smckusick spec_open, /* open */ 4039507Smckusick spec_close, /* close */ 4148015Smckusick spec_access, /* access */ 4248015Smckusick spec_getattr, /* getattr */ 4348015Smckusick spec_setattr, /* setattr */ 4439507Smckusick spec_read, /* read */ 4539507Smckusick spec_write, /* write */ 4639507Smckusick spec_ioctl, /* ioctl */ 4739507Smckusick spec_select, /* select */ 4848015Smckusick spec_mmap, /* mmap */ 4948015Smckusick spec_fsync, /* fsync */ 5048015Smckusick spec_seek, /* seek */ 5148015Smckusick spec_remove, /* remove */ 5248015Smckusick spec_link, /* link */ 5348015Smckusick spec_rename, /* rename */ 5448015Smckusick spec_mkdir, /* mkdir */ 5548015Smckusick spec_rmdir, /* rmdir */ 5648015Smckusick spec_symlink, /* symlink */ 5748015Smckusick spec_readdir, /* readdir */ 5848015Smckusick spec_readlink, /* readlink */ 5948015Smckusick spec_abortop, /* abortop */ 6048015Smckusick spec_inactive, /* inactive */ 6148015Smckusick spec_reclaim, /* reclaim */ 6239507Smckusick spec_lock, /* lock */ 6339507Smckusick spec_unlock, /* unlock */ 6439666Smckusick spec_bmap, /* bmap */ 6539507Smckusick spec_strategy, /* strategy */ 6639666Smckusick spec_print, /* print */ 6748015Smckusick spec_islocked, /* islocked */ 6846196Smckusick spec_advlock, /* advlock */ 6951567Smckusick spec_blkatoff, /* blkatoff */ 7051567Smckusick spec_vget, /* vget */ 7151567Smckusick spec_valloc, /* valloc */ 7251567Smckusick spec_vfree, /* vfree */ 7351567Smckusick spec_truncate, /* truncate */ 7451567Smckusick spec_update, /* update */ 7551567Smckusick spec_bwrite, /* bwrite */ 7637486Smckusick }; 7737486Smckusick 7837486Smckusick /* 7939292Smckusick * Trivial lookup routine that always fails. 8039292Smckusick */ 81*52320Sheideman int 82*52320Sheideman spec_lookup(dvp, vpp, cnp) 83*52320Sheideman struct vnode *dvp; 84*52320Sheideman struct vnode **vpp; 85*52320Sheideman struct componentname *cnp; 8639292Smckusick { 8739292Smckusick 88*52320Sheideman *vpp = NULL; 8939292Smckusick return (ENOTDIR); 9039292Smckusick } 9139292Smckusick 9239292Smckusick /* 9349273Skarels * Open a special file: Don't allow open if fs is mounted -nodev, 9449273Skarels * and don't allow opens of block devices that are currently mounted. 9549273Skarels * Otherwise, call device driver open function. 9637486Smckusick */ 9737725Smckusick /* ARGSUSED */ 9848015Smckusick spec_open(vp, mode, cred, p) 9937486Smckusick register struct vnode *vp; 10037486Smckusick int mode; 10137486Smckusick struct ucred *cred; 10248015Smckusick struct proc *p; 10337486Smckusick { 10437486Smckusick dev_t dev = (dev_t)vp->v_rdev; 10537486Smckusick register int maj = major(dev); 10640375Smckusick int error; 10737486Smckusick 10841400Smckusick if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) 10939365Smckusick return (ENXIO); 11039365Smckusick 11137486Smckusick switch (vp->v_type) { 11237486Smckusick 11337486Smckusick case VCHR: 11437486Smckusick if ((u_int)maj >= nchrdev) 11537486Smckusick return (ENXIO); 11649944Smckusick VOP_UNLOCK(vp); 11749944Smckusick error = (*cdevsw[maj].d_open)(dev, mode, S_IFCHR, p); 11849944Smckusick VOP_LOCK(vp); 11949944Smckusick return (error); 12037486Smckusick 12137486Smckusick case VBLK: 12237486Smckusick if ((u_int)maj >= nblkdev) 12337486Smckusick return (ENXIO); 12451457Sbostic if (error = ufs_mountedon(vp)) 12540375Smckusick return (error); 12647540Skarels return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK, p)); 12737486Smckusick } 12837486Smckusick return (0); 12937486Smckusick } 13037486Smckusick 13137486Smckusick /* 13237486Smckusick * Vnode op for read 13337486Smckusick */ 13441961Smckusick /* ARGSUSED */ 13539588Smckusick spec_read(vp, uio, ioflag, cred) 13637486Smckusick register struct vnode *vp; 13739614Smckusick register struct uio *uio; 13837486Smckusick int ioflag; 13937486Smckusick struct ucred *cred; 14037486Smckusick { 14148015Smckusick struct proc *p = uio->uio_procp; 14239614Smckusick struct buf *bp; 14339614Smckusick daddr_t bn; 14439614Smckusick long bsize, bscale; 14539614Smckusick struct partinfo dpart; 14639614Smckusick register int n, on; 14739614Smckusick int error = 0; 14837486Smckusick 14948015Smckusick #ifdef DIAGNOSTIC 15039588Smckusick if (uio->uio_rw != UIO_READ) 15139588Smckusick panic("spec_read mode"); 15248015Smckusick if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 15348015Smckusick panic("spec_read proc"); 15448015Smckusick #endif 15539588Smckusick if (uio->uio_resid == 0) 15639588Smckusick return (0); 15739588Smckusick 15839588Smckusick switch (vp->v_type) { 15939588Smckusick 16039588Smckusick case VCHR: 16139588Smckusick VOP_UNLOCK(vp); 16239588Smckusick error = (*cdevsw[major(vp->v_rdev)].d_read) 16349121Skarels (vp->v_rdev, uio, ioflag); 16437725Smckusick VOP_LOCK(vp); 16539588Smckusick return (error); 16639588Smckusick 16739588Smckusick case VBLK: 16839588Smckusick if (uio->uio_offset < 0) 16939588Smckusick return (EINVAL); 17039614Smckusick bsize = BLKDEV_IOSIZE; 17139614Smckusick if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, 17247540Skarels (caddr_t)&dpart, FREAD, p) == 0) { 17339614Smckusick if (dpart.part->p_fstype == FS_BSDFFS && 17439614Smckusick dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 17539614Smckusick bsize = dpart.part->p_frag * 17639614Smckusick dpart.part->p_fsize; 17739614Smckusick } 17839614Smckusick bscale = bsize / DEV_BSIZE; 17939614Smckusick do { 18039614Smckusick bn = (uio->uio_offset / DEV_BSIZE) &~ (bscale - 1); 18139614Smckusick on = uio->uio_offset % bsize; 18239614Smckusick n = MIN((unsigned)(bsize - on), uio->uio_resid); 18339614Smckusick if (vp->v_lastr + bscale == bn) 18439614Smckusick error = breada(vp, bn, (int)bsize, bn + bscale, 18539614Smckusick (int)bsize, NOCRED, &bp); 18639614Smckusick else 18739614Smckusick error = bread(vp, bn, (int)bsize, NOCRED, &bp); 18839614Smckusick vp->v_lastr = bn; 18939614Smckusick n = MIN(n, bsize - bp->b_resid); 19039614Smckusick if (error) { 19139614Smckusick brelse(bp); 19239614Smckusick return (error); 19339614Smckusick } 19439614Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 19539614Smckusick if (n + on == bsize) 19639614Smckusick bp->b_flags |= B_AGE; 19739614Smckusick brelse(bp); 19839614Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 19939614Smckusick return (error); 20039588Smckusick 20139588Smckusick default: 20239588Smckusick panic("spec_read type"); 20339588Smckusick } 20439588Smckusick /* NOTREACHED */ 20537486Smckusick } 20637486Smckusick 20737486Smckusick /* 20837486Smckusick * Vnode op for write 20937486Smckusick */ 21041961Smckusick /* ARGSUSED */ 21139588Smckusick spec_write(vp, uio, ioflag, cred) 21237486Smckusick register struct vnode *vp; 21339614Smckusick register struct uio *uio; 21437486Smckusick int ioflag; 21537486Smckusick struct ucred *cred; 21637486Smckusick { 21748015Smckusick struct proc *p = uio->uio_procp; 21839614Smckusick struct buf *bp; 21939614Smckusick daddr_t bn; 22039614Smckusick int bsize, blkmask; 22139614Smckusick struct partinfo dpart; 22245731Smckusick register int n, on; 22345731Smckusick int error = 0; 22437486Smckusick 22548015Smckusick #ifdef DIAGNOSTIC 22639588Smckusick if (uio->uio_rw != UIO_WRITE) 22739588Smckusick panic("spec_write mode"); 22848015Smckusick if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 22948015Smckusick panic("spec_write proc"); 23048015Smckusick #endif 23139588Smckusick 23239588Smckusick switch (vp->v_type) { 23339588Smckusick 23439588Smckusick case VCHR: 23539588Smckusick VOP_UNLOCK(vp); 23639588Smckusick error = (*cdevsw[major(vp->v_rdev)].d_write) 23749121Skarels (vp->v_rdev, uio, ioflag); 23837725Smckusick VOP_LOCK(vp); 23939588Smckusick return (error); 24039588Smckusick 24139588Smckusick case VBLK: 24239588Smckusick if (uio->uio_resid == 0) 24339588Smckusick return (0); 24439588Smckusick if (uio->uio_offset < 0) 24539588Smckusick return (EINVAL); 24639614Smckusick bsize = BLKDEV_IOSIZE; 24739614Smckusick if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, 24847540Skarels (caddr_t)&dpart, FREAD, p) == 0) { 24939614Smckusick if (dpart.part->p_fstype == FS_BSDFFS && 25039614Smckusick dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 25139614Smckusick bsize = dpart.part->p_frag * 25239614Smckusick dpart.part->p_fsize; 25339614Smckusick } 25439614Smckusick blkmask = (bsize / DEV_BSIZE) - 1; 25539614Smckusick do { 25639614Smckusick bn = (uio->uio_offset / DEV_BSIZE) &~ blkmask; 25739614Smckusick on = uio->uio_offset % bsize; 25839614Smckusick n = MIN((unsigned)(bsize - on), uio->uio_resid); 25939614Smckusick if (n == bsize) 26039614Smckusick bp = getblk(vp, bn, bsize); 26139614Smckusick else 26239614Smckusick error = bread(vp, bn, bsize, NOCRED, &bp); 26339614Smckusick n = MIN(n, bsize - bp->b_resid); 26439614Smckusick if (error) { 26539614Smckusick brelse(bp); 26639614Smckusick return (error); 26739614Smckusick } 26839614Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 26939614Smckusick if (n + on == bsize) { 27039614Smckusick bp->b_flags |= B_AGE; 27139614Smckusick bawrite(bp); 27239614Smckusick } else 27339614Smckusick bdwrite(bp); 27439614Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 27539614Smckusick return (error); 27639588Smckusick 27739588Smckusick default: 27839588Smckusick panic("spec_write type"); 27939588Smckusick } 28039588Smckusick /* NOTREACHED */ 28137486Smckusick } 28237486Smckusick 28337486Smckusick /* 28437486Smckusick * Device ioctl operation. 28537486Smckusick */ 28637725Smckusick /* ARGSUSED */ 28748015Smckusick spec_ioctl(vp, com, data, fflag, cred, p) 28837486Smckusick struct vnode *vp; 28939666Smckusick int com; 29037486Smckusick caddr_t data; 29137486Smckusick int fflag; 29237486Smckusick struct ucred *cred; 29348015Smckusick struct proc *p; 29437486Smckusick { 29537725Smckusick dev_t dev = vp->v_rdev; 29637486Smckusick 29737486Smckusick switch (vp->v_type) { 29837486Smckusick 29937486Smckusick case VCHR: 30047540Skarels return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data, 30147540Skarels fflag, p)); 30237486Smckusick 30337486Smckusick case VBLK: 30439666Smckusick if (com == 0 && (int)data == B_TAPE) 30539666Smckusick if (bdevsw[major(dev)].d_flags & B_TAPE) 30639666Smckusick return (0); 30739666Smckusick else 30839666Smckusick return (1); 30947540Skarels return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data, 31047540Skarels fflag, p)); 31137486Smckusick 31237486Smckusick default: 31339446Smckusick panic("spec_ioctl"); 31437486Smckusick /* NOTREACHED */ 31537486Smckusick } 31637486Smckusick } 31737486Smckusick 31837725Smckusick /* ARGSUSED */ 31948015Smckusick spec_select(vp, which, fflags, cred, p) 32037486Smckusick struct vnode *vp; 32140189Smckusick int which, fflags; 32237486Smckusick struct ucred *cred; 32348015Smckusick struct proc *p; 32437486Smckusick { 32537486Smckusick register dev_t dev; 32637486Smckusick 32737486Smckusick switch (vp->v_type) { 32837486Smckusick 32937486Smckusick default: 33037486Smckusick return (1); /* XXX */ 33137486Smckusick 33237486Smckusick case VCHR: 33337725Smckusick dev = vp->v_rdev; 33447540Skarels return (*cdevsw[major(dev)].d_select)(dev, which, p); 33537486Smckusick } 33637486Smckusick } 33737486Smckusick 33837486Smckusick /* 33937486Smckusick * Just call the device strategy routine 34037486Smckusick */ 34139446Smckusick spec_strategy(bp) 34237486Smckusick register struct buf *bp; 34337486Smckusick { 34439666Smckusick 34537486Smckusick (*bdevsw[major(bp->b_dev)].d_strategy)(bp); 34637486Smckusick return (0); 34737486Smckusick } 34837486Smckusick 34939432Smckusick /* 35039666Smckusick * This is a noop, simply returning what one has been given. 35139666Smckusick */ 35239666Smckusick spec_bmap(vp, bn, vpp, bnp) 35339666Smckusick struct vnode *vp; 35439666Smckusick daddr_t bn; 35539666Smckusick struct vnode **vpp; 35639666Smckusick daddr_t *bnp; 35739666Smckusick { 35839666Smckusick 35939666Smckusick if (vpp != NULL) 36039666Smckusick *vpp = vp; 36139666Smckusick if (bnp != NULL) 36239666Smckusick *bnp = bn; 36339666Smckusick return (0); 36439666Smckusick } 36539666Smckusick 36639666Smckusick /* 36739432Smckusick * At the moment we do not do any locking. 36839432Smckusick */ 36939489Smckusick /* ARGSUSED */ 37039446Smckusick spec_lock(vp) 37137486Smckusick struct vnode *vp; 37237486Smckusick { 37337486Smckusick 37437486Smckusick return (0); 37537486Smckusick } 37637486Smckusick 37739489Smckusick /* ARGSUSED */ 37839446Smckusick spec_unlock(vp) 37937486Smckusick struct vnode *vp; 38037486Smckusick { 38137486Smckusick 38237486Smckusick return (0); 38337486Smckusick } 38437486Smckusick 38537486Smckusick /* 38637486Smckusick * Device close routine 38737486Smckusick */ 38837725Smckusick /* ARGSUSED */ 38948015Smckusick spec_close(vp, flag, cred, p) 39037725Smckusick register struct vnode *vp; 39137486Smckusick int flag; 39237486Smckusick struct ucred *cred; 39348015Smckusick struct proc *p; 39437486Smckusick { 39537486Smckusick dev_t dev = vp->v_rdev; 39649273Skarels int (*devclose) __P((dev_t, int, int, struct proc *)); 39740707Skarels int mode; 39837486Smckusick 39937725Smckusick switch (vp->v_type) { 40037725Smckusick 40137725Smckusick case VCHR: 40239485Smckusick /* 40339485Smckusick * If the vnode is locked, then we are in the midst 40439485Smckusick * of forcably closing the device, otherwise we only 40539485Smckusick * close on last reference. 40639485Smckusick */ 40739630Smckusick if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) 40837725Smckusick return (0); 40949273Skarels devclose = cdevsw[major(dev)].d_close; 41039432Smckusick mode = S_IFCHR; 41137725Smckusick break; 41237725Smckusick 41337725Smckusick case VBLK: 41437725Smckusick /* 41537725Smckusick * On last close of a block device (that isn't mounted) 41637725Smckusick * we must invalidate any in core blocks, so that 41737725Smckusick * we can, for instance, change floppy disks. 41837725Smckusick */ 41939666Smckusick vflushbuf(vp, 0); 42039666Smckusick if (vinvalbuf(vp, 1)) 42138613Smckusick return (0); 42237725Smckusick /* 42339485Smckusick * We do not want to really close the device if it 42439485Smckusick * is still in use unless we are trying to close it 42539485Smckusick * forcibly. Since every use (buffer, vnode, swap, cmap) 42639630Smckusick * holds a reference to the vnode, and because we mark 42739630Smckusick * any other vnodes that alias this device, when the 42839630Smckusick * sum of the reference counts on all the aliased 42939630Smckusick * vnodes descends to one, we are on last close. 43037725Smckusick */ 43139630Smckusick if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) 43237725Smckusick return (0); 43349273Skarels devclose = bdevsw[major(dev)].d_close; 43439432Smckusick mode = S_IFBLK; 43537725Smckusick break; 43637725Smckusick 43737725Smckusick default: 43839446Smckusick panic("spec_close: not special"); 43937725Smckusick } 44037725Smckusick 44149273Skarels return ((*devclose)(dev, flag, mode, p)); 44237486Smckusick } 44337486Smckusick 44437486Smckusick /* 44539666Smckusick * Print out the contents of a special device vnode. 44639666Smckusick */ 44739666Smckusick spec_print(vp) 44839666Smckusick struct vnode *vp; 44939666Smckusick { 45039666Smckusick 45139666Smckusick printf("tag VT_NON, dev %d, %d\n", major(vp->v_rdev), 45239666Smckusick minor(vp->v_rdev)); 45339666Smckusick } 45439666Smckusick 45539666Smckusick /* 45646196Smckusick * Special device advisory byte-level locks. 45746196Smckusick */ 45848015Smckusick /* ARGSUSED */ 45946196Smckusick spec_advlock(vp, id, op, fl, flags) 46046196Smckusick struct vnode *vp; 46146196Smckusick caddr_t id; 46246196Smckusick int op; 46346196Smckusick struct flock *fl; 46446196Smckusick int flags; 46546196Smckusick { 46646196Smckusick 46746196Smckusick return (EOPNOTSUPP); 46846196Smckusick } 46946196Smckusick 47046196Smckusick /* 47139507Smckusick * Special device failed operation 47237486Smckusick */ 47339507Smckusick spec_ebadf() 47439507Smckusick { 47539507Smckusick 47639507Smckusick return (EBADF); 47739507Smckusick } 47839507Smckusick 47939507Smckusick /* 48039507Smckusick * Special device bad operation 48139507Smckusick */ 48239446Smckusick spec_badop() 48337486Smckusick { 48437486Smckusick 48539446Smckusick panic("spec_badop called"); 48639292Smckusick /* NOTREACHED */ 48737486Smckusick } 488