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*37725Smckusick * @(#)spec_vnops.c 7.3 (Berkeley) 05/09/89 1837486Smckusick */ 1937486Smckusick 2037486Smckusick #include "param.h" 2137486Smckusick #include "systm.h" 22*37725Smckusick #include "user.h" 23*37725Smckusick #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(), 45*37725Smckusick ufs_setattr(), 46*37725Smckusick ufs_access(), 47*37725Smckusick ufs_inactive(); 4837486Smckusick 4937486Smckusick struct vnodeops blk_vnodeops = { 5037486Smckusick blk_badop, 5137486Smckusick blk_badop, 5237486Smckusick blk_badop, 5337486Smckusick blk_open, 5437486Smckusick blk_close, 55*37725Smckusick 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, 74*37725Smckusick 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 */ 86*37725Smckusick /* 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 119*37725Smckusick 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 134*37725Smckusick if (vp->v_type == VBLK && vp->v_data) 135*37725Smckusick VOP_LOCK(vp); 13637486Smckusick uio->uio_offset = *offp; 13737486Smckusick count = uio->uio_resid; 138*37725Smckusick error = readblkvp(vp, uio, cred, ioflag); 13937486Smckusick *offp += count - uio->uio_resid; 140*37725Smckusick if (vp->v_type == VBLK && vp->v_data) 141*37725Smckusick 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 157*37725Smckusick if (vp->v_type == VBLK && vp->v_data) 158*37725Smckusick VOP_LOCK(vp); 15937486Smckusick uio->uio_offset = *offp; 16037486Smckusick count = uio->uio_resid; 161*37725Smckusick error = writeblkvp(vp, uio, cred, ioflag); 16237486Smckusick *offp += count - uio->uio_resid; 163*37725Smckusick if (vp->v_type == VBLK && vp->v_data) 164*37725Smckusick VOP_UNLOCK(vp); 16537486Smckusick return (error); 16637486Smckusick } 16737486Smckusick 16837486Smckusick /* 16937486Smckusick * Device ioctl operation. 17037486Smckusick */ 171*37725Smckusick /* 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 { 179*37725Smckusick 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 195*37725Smckusick /* 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: 209*37725Smckusick 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 */ 247*37725Smckusick /* ARGSUSED */ 24837486Smckusick blk_close(vp, flag, cred) 249*37725Smckusick register struct vnode *vp; 25037486Smckusick int flag; 25137486Smckusick struct ucred *cred; 25237486Smckusick { 253*37725Smckusick register struct inode *ip = VTOI(vp); 25437486Smckusick dev_t dev = vp->v_rdev; 255*37725Smckusick int (*cfunc)(); 256*37725Smckusick int error, mode; 25737486Smckusick 258*37725Smckusick if (vp->v_count > 1 && !(ip->i_flag & ILOCKED)) 259*37725Smckusick ITIMES(ip, &time, &time); 260*37725Smckusick 261*37725Smckusick switch (vp->v_type) { 262*37725Smckusick 263*37725Smckusick case VCHR: 264*37725Smckusick if (vp->v_count > 1) 265*37725Smckusick return (0); 266*37725Smckusick cfunc = cdevsw[major(dev)].d_close; 267*37725Smckusick mode = IFCHR; 268*37725Smckusick break; 269*37725Smckusick 270*37725Smckusick case VBLK: 271*37725Smckusick /* 272*37725Smckusick * On last close of a block device (that isn't mounted) 273*37725Smckusick * we must invalidate any in core blocks, so that 274*37725Smckusick * we can, for instance, change floppy disks. 275*37725Smckusick */ 276*37725Smckusick bflush(dev); 277*37725Smckusick binval(dev); 278*37725Smckusick /* 279*37725Smckusick * We don't want to really close the device if it is still 280*37725Smckusick * in use. Since every use (buffer, inode, swap, cmap) 281*37725Smckusick * holds a reference to the vnode, and because we ensure 282*37725Smckusick * that there cannot be more than one vnode per device, 283*37725Smckusick * we need only check that we are down to the last 284*37725Smckusick * reference before closing. 285*37725Smckusick */ 286*37725Smckusick if (vp->v_count > 1) 287*37725Smckusick return (0); 288*37725Smckusick cfunc = bdevsw[major(dev)].d_close; 289*37725Smckusick mode = IFBLK; 290*37725Smckusick break; 291*37725Smckusick 292*37725Smckusick default: 293*37725Smckusick panic("blk_close: not special"); 294*37725Smckusick } 295*37725Smckusick 296*37725Smckusick /* XXX what is this doing below the vnode op call */ 297*37725Smckusick if (setjmp(&u.u_qsave)) { 298*37725Smckusick /* 299*37725Smckusick * If device close routine is interrupted, 300*37725Smckusick * must return so closef can clean up. 301*37725Smckusick */ 302*37725Smckusick error = EINTR; 303*37725Smckusick } else 304*37725Smckusick error = (*cfunc)(dev, flag, mode); 305*37725Smckusick /* 306*37725Smckusick * Most device close routines don't return errors, 307*37725Smckusick * and dup2() doesn't work right on error. 308*37725Smckusick */ 309*37725Smckusick error = 0; /* XXX */ 310*37725Smckusick return (error); 31137486Smckusick } 31237486Smckusick 31337486Smckusick /* 31437486Smckusick * Block device bad operation 31537486Smckusick */ 31637486Smckusick blk_badop() 31737486Smckusick { 31837486Smckusick 31937486Smckusick printf("blk_badop called\n"); 32037486Smckusick return (ENXIO); 32137486Smckusick } 32237486Smckusick 32337486Smckusick /* 32437486Smckusick * Block device null operation 32537486Smckusick */ 32637486Smckusick blk_nullop() 32737486Smckusick { 32837486Smckusick 32937486Smckusick return (0); 33037486Smckusick } 331