137486Smckusick /* 237486Smckusick * Copyright (c) 1989 The Regents of the University of California. 337486Smckusick * All rights reserved. 437486Smckusick * 537486Smckusick * Redistribution and use in source and binary forms are permitted 637486Smckusick * provided that the above copyright notice and this paragraph are 737486Smckusick * duplicated in all such forms and that any documentation, 837486Smckusick * advertising materials, and other materials related to such 937486Smckusick * distribution and use acknowledge that the software was developed 1037486Smckusick * by the University of California, Berkeley. The name of the 1137486Smckusick * University may not be used to endorse or promote products derived 1237486Smckusick * from this software without specific prior written permission. 1337486Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437486Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537486Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637486Smckusick * 17*38777Smckusick * @(#)spec_vnops.c 7.5 (Berkeley) 08/26/89 1837486Smckusick */ 1937486Smckusick 2037486Smckusick #include "param.h" 2137486Smckusick #include "systm.h" 2237725Smckusick #include "user.h" 2337725Smckusick #include "kernel.h" 2437486Smckusick #include "conf.h" 2537486Smckusick #include "buf.h" 2637486Smckusick #include "vnode.h" 2737486Smckusick #include "../ufs/inode.h" 2837486Smckusick #include "stat.h" 2937486Smckusick #include "errno.h" 3037486Smckusick #include "malloc.h" 3137486Smckusick 3237486Smckusick int blk_open(), 3337486Smckusick blk_read(), 3437486Smckusick blk_write(), 3537486Smckusick blk_strategy(), 3637486Smckusick blk_ioctl(), 3737486Smckusick blk_select(), 3837486Smckusick blk_lock(), 3937486Smckusick blk_unlock(), 4037486Smckusick blk_close(), 4137486Smckusick blk_badop(), 4237486Smckusick blk_nullop(); 4337486Smckusick 4437486Smckusick int ufs_getattr(), 4537725Smckusick ufs_setattr(), 4637725Smckusick ufs_access(), 4737725Smckusick ufs_inactive(); 4837486Smckusick 4937486Smckusick struct vnodeops blk_vnodeops = { 5037486Smckusick blk_badop, 5137486Smckusick blk_badop, 5237486Smckusick blk_badop, 5337486Smckusick blk_open, 5437486Smckusick blk_close, 5537725Smckusick ufs_access, 5637486Smckusick ufs_getattr, 5737486Smckusick ufs_setattr, 5837486Smckusick blk_read, 5937486Smckusick blk_write, 6037486Smckusick blk_ioctl, 6137486Smckusick blk_select, 6237486Smckusick blk_badop, 6337486Smckusick blk_nullop, 6437486Smckusick blk_badop, 6537486Smckusick blk_badop, 6637486Smckusick blk_badop, 6737486Smckusick blk_badop, 6837486Smckusick blk_badop, 6937486Smckusick blk_badop, 7037486Smckusick blk_badop, 7137486Smckusick blk_badop, 7237486Smckusick blk_badop, 7337486Smckusick blk_badop, 7437725Smckusick ufs_inactive, 7537486Smckusick blk_lock, 7637486Smckusick blk_unlock, 7737486Smckusick blk_badop, 7837486Smckusick blk_strategy, 7937486Smckusick }; 8037486Smckusick 8137486Smckusick /* 8237486Smckusick * Open called to allow handler 8337486Smckusick * of special files to initialize and 8437486Smckusick * validate before actual IO. 8537486Smckusick */ 8637725Smckusick /* ARGSUSED */ 8737486Smckusick blk_open(vp, mode, cred) 8837486Smckusick register struct vnode *vp; 8937486Smckusick int mode; 9037486Smckusick struct ucred *cred; 9137486Smckusick { 9237486Smckusick dev_t dev = (dev_t)vp->v_rdev; 9337486Smckusick register int maj = major(dev); 9437486Smckusick 9537486Smckusick switch (vp->v_type) { 9637486Smckusick 9737486Smckusick case VCHR: 9837486Smckusick if ((u_int)maj >= nchrdev) 9937486Smckusick return (ENXIO); 10037486Smckusick return ((*cdevsw[maj].d_open)(dev, mode, S_IFCHR)); 10137486Smckusick 10237486Smckusick case VBLK: 10337486Smckusick if ((u_int)maj >= nblkdev) 10437486Smckusick return (ENXIO); 10537486Smckusick return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK)); 10637486Smckusick } 10737486Smckusick return (0); 10837486Smckusick } 10937486Smckusick 11037486Smckusick /* 11137486Smckusick * Check access permissions for a block device. 11237486Smckusick */ 11337486Smckusick blk_access(vp, mode, cred) 11437486Smckusick struct vnode *vp; 11537486Smckusick int mode; 11637486Smckusick struct ucred *cred; 11737486Smckusick { 11837486Smckusick 11937725Smckusick return (iaccess(VTOI(vp), mode, cred)); 12037486Smckusick } 12137486Smckusick 12237486Smckusick /* 12337486Smckusick * Vnode op for read 12437486Smckusick */ 12537486Smckusick blk_read(vp, uio, offp, ioflag, cred) 12637486Smckusick register struct vnode *vp; 12737486Smckusick struct uio *uio; 12837486Smckusick off_t *offp; 12937486Smckusick int ioflag; 13037486Smckusick struct ucred *cred; 13137486Smckusick { 13237486Smckusick int count, error; 13337486Smckusick 13437725Smckusick if (vp->v_type == VBLK && vp->v_data) 13537725Smckusick VOP_LOCK(vp); 13637486Smckusick uio->uio_offset = *offp; 13737486Smckusick count = uio->uio_resid; 13837725Smckusick error = readblkvp(vp, uio, cred, ioflag); 13937486Smckusick *offp += count - uio->uio_resid; 14037725Smckusick if (vp->v_type == VBLK && vp->v_data) 14137725Smckusick VOP_UNLOCK(vp); 14237486Smckusick return (error); 14337486Smckusick } 14437486Smckusick 14537486Smckusick /* 14637486Smckusick * Vnode op for write 14737486Smckusick */ 14837486Smckusick blk_write(vp, uio, offp, ioflag, cred) 14937486Smckusick register struct vnode *vp; 15037486Smckusick struct uio *uio; 15137486Smckusick off_t *offp; 15237486Smckusick int ioflag; 15337486Smckusick struct ucred *cred; 15437486Smckusick { 15537486Smckusick int count, error; 15637486Smckusick 15737725Smckusick if (vp->v_type == VBLK && vp->v_data) 15837725Smckusick VOP_LOCK(vp); 15937486Smckusick uio->uio_offset = *offp; 16037486Smckusick count = uio->uio_resid; 16137725Smckusick error = writeblkvp(vp, uio, cred, ioflag); 16237486Smckusick *offp += count - uio->uio_resid; 16337725Smckusick if (vp->v_type == VBLK && vp->v_data) 16437725Smckusick VOP_UNLOCK(vp); 16537486Smckusick return (error); 16637486Smckusick } 16737486Smckusick 16837486Smckusick /* 16937486Smckusick * Device ioctl operation. 17037486Smckusick */ 17137725Smckusick /* ARGSUSED */ 17237486Smckusick blk_ioctl(vp, com, data, fflag, cred) 17337486Smckusick struct vnode *vp; 17437486Smckusick register int com; 17537486Smckusick caddr_t data; 17637486Smckusick int fflag; 17737486Smckusick struct ucred *cred; 17837486Smckusick { 17937725Smckusick dev_t dev = vp->v_rdev; 18037486Smckusick 18137486Smckusick switch (vp->v_type) { 18237486Smckusick 18337486Smckusick case VCHR: 18437486Smckusick return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data, fflag)); 18537486Smckusick 18637486Smckusick case VBLK: 18737486Smckusick return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data, fflag)); 18837486Smckusick 18937486Smckusick default: 19037486Smckusick panic("blk_ioctl"); 19137486Smckusick /* NOTREACHED */ 19237486Smckusick } 19337486Smckusick } 19437486Smckusick 19537725Smckusick /* ARGSUSED */ 19637486Smckusick blk_select(vp, which, cred) 19737486Smckusick struct vnode *vp; 19837486Smckusick int which; 19937486Smckusick struct ucred *cred; 20037486Smckusick { 20137486Smckusick register dev_t dev; 20237486Smckusick 20337486Smckusick switch (vp->v_type) { 20437486Smckusick 20537486Smckusick default: 20637486Smckusick return (1); /* XXX */ 20737486Smckusick 20837486Smckusick case VCHR: 20937725Smckusick dev = vp->v_rdev; 21037486Smckusick return (*cdevsw[major(dev)].d_select)(dev, which); 21137486Smckusick } 21237486Smckusick } 21337486Smckusick 21437486Smckusick /* 21537486Smckusick * Just call the device strategy routine 21637486Smckusick */ 21737486Smckusick blk_strategy(bp) 21837486Smckusick register struct buf *bp; 21937486Smckusick { 22037486Smckusick (*bdevsw[major(bp->b_dev)].d_strategy)(bp); 22137486Smckusick return (0); 22237486Smckusick } 22337486Smckusick 22437486Smckusick blk_lock(vp) 22537486Smckusick struct vnode *vp; 22637486Smckusick { 22737486Smckusick register struct inode *ip = VTOI(vp); 22837486Smckusick 22937486Smckusick if (ip) 23037486Smckusick ILOCK(ip); 23137486Smckusick return (0); 23237486Smckusick } 23337486Smckusick 23437486Smckusick blk_unlock(vp) 23537486Smckusick struct vnode *vp; 23637486Smckusick { 23737486Smckusick register struct inode *ip = VTOI(vp); 23837486Smckusick 23937486Smckusick if (ip) 24037486Smckusick IUNLOCK(ip); 24137486Smckusick return (0); 24237486Smckusick } 24337486Smckusick 24437486Smckusick /* 24537486Smckusick * Device close routine 24637486Smckusick */ 24737725Smckusick /* ARGSUSED */ 24837486Smckusick blk_close(vp, flag, cred) 24937725Smckusick register struct vnode *vp; 25037486Smckusick int flag; 25137486Smckusick struct ucred *cred; 25237486Smckusick { 25337725Smckusick register struct inode *ip = VTOI(vp); 25437486Smckusick dev_t dev = vp->v_rdev; 25537725Smckusick int (*cfunc)(); 25637725Smckusick int error, mode; 25737486Smckusick 25837725Smckusick if (vp->v_count > 1 && !(ip->i_flag & ILOCKED)) 25937725Smckusick ITIMES(ip, &time, &time); 26037725Smckusick 26137725Smckusick switch (vp->v_type) { 26237725Smckusick 26337725Smckusick case VCHR: 26437725Smckusick if (vp->v_count > 1) 26537725Smckusick return (0); 26637725Smckusick cfunc = cdevsw[major(dev)].d_close; 26737725Smckusick mode = IFCHR; 26837725Smckusick break; 26937725Smckusick 27037725Smckusick case VBLK: 27137725Smckusick /* 27237725Smckusick * On last close of a block device (that isn't mounted) 27337725Smckusick * we must invalidate any in core blocks, so that 27437725Smckusick * we can, for instance, change floppy disks. 27537725Smckusick */ 276*38777Smckusick bflush(vp->v_mount); 277*38777Smckusick if (binval(vp->v_mount)) 27838613Smckusick return (0); 27937725Smckusick /* 28037725Smckusick * We don't want to really close the device if it is still 28137725Smckusick * in use. Since every use (buffer, inode, swap, cmap) 28237725Smckusick * holds a reference to the vnode, and because we ensure 28337725Smckusick * that there cannot be more than one vnode per device, 28437725Smckusick * we need only check that we are down to the last 28537725Smckusick * reference before closing. 28637725Smckusick */ 28737725Smckusick if (vp->v_count > 1) 28837725Smckusick return (0); 28937725Smckusick cfunc = bdevsw[major(dev)].d_close; 29037725Smckusick mode = IFBLK; 29137725Smckusick break; 29237725Smckusick 29337725Smckusick default: 29437725Smckusick panic("blk_close: not special"); 29537725Smckusick } 29637725Smckusick 29737725Smckusick /* XXX what is this doing below the vnode op call */ 29837725Smckusick if (setjmp(&u.u_qsave)) { 29937725Smckusick /* 30037725Smckusick * If device close routine is interrupted, 30137725Smckusick * must return so closef can clean up. 30237725Smckusick */ 30337725Smckusick error = EINTR; 30437725Smckusick } else 30537725Smckusick error = (*cfunc)(dev, flag, mode); 30637725Smckusick /* 30737725Smckusick * Most device close routines don't return errors, 30837725Smckusick * and dup2() doesn't work right on error. 30937725Smckusick */ 31037725Smckusick error = 0; /* XXX */ 31137725Smckusick return (error); 31237486Smckusick } 31337486Smckusick 31437486Smckusick /* 31537486Smckusick * Block device bad operation 31637486Smckusick */ 31737486Smckusick blk_badop() 31837486Smckusick { 31937486Smckusick 32037486Smckusick printf("blk_badop called\n"); 32137486Smckusick return (ENXIO); 32237486Smckusick } 32337486Smckusick 32437486Smckusick /* 32537486Smckusick * Block device null operation 32637486Smckusick */ 32737486Smckusick blk_nullop() 32837486Smckusick { 32937486Smckusick 33037486Smckusick return (0); 33137486Smckusick } 332