Annotation of src/sys/miscfs/specfs/spec_vnops.c, Revision 1.54.2.4
1.54.2.4! jdolecek 1: /* $NetBSD: spec_vnops.c,v 1.54.2.3 2002/01/10 20:01:46 thorpej Exp $ */
1.16 cgd 2:
1.1 cgd 3: /*
1.15 mycroft 4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
1.39 fvdl 35: * @(#)spec_vnops.c 8.15 (Berkeley) 7/14/95
1.1 cgd 36: */
37:
1.54.2.3 thorpej 38: #include <sys/cdefs.h>
1.54.2.4! jdolecek 39: __KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.54.2.3 2002/01/10 20:01:46 thorpej Exp $");
1.54.2.3 thorpej 40:
1.9 mycroft 41: #include <sys/param.h>
42: #include <sys/proc.h>
43: #include <sys/systm.h>
44: #include <sys/kernel.h>
45: #include <sys/conf.h>
46: #include <sys/buf.h>
47: #include <sys/mount.h>
48: #include <sys/namei.h>
49: #include <sys/vnode.h>
50: #include <sys/stat.h>
51: #include <sys/errno.h>
52: #include <sys/ioctl.h>
53: #include <sys/file.h>
54: #include <sys/disklabel.h>
1.35 kleink 55: #include <sys/lockf.h>
1.28 christos 56:
1.30 mycroft 57: #include <miscfs/genfs/genfs.h>
1.15 mycroft 58: #include <miscfs/specfs/specdev.h>
1.1 cgd 59:
60: /* symbolic sleep message strings for devices */
1.37 mycroft 61: const char devopn[] = "devopn";
62: const char devio[] = "devio";
63: const char devwait[] = "devwait";
64: const char devin[] = "devin";
65: const char devout[] = "devout";
66: const char devioc[] = "devioc";
67: const char devcls[] = "devcls";
1.54.2.4! jdolecek 68:
! 69: struct vnode *speclisth[SPECHSZ];
1.46 sommerfe 70:
71: /*
72: * This vnode operations vector is used for two things only:
73: * - special device nodes created from whole cloth by the kernel.
74: * - as a temporary vnodeops replacement for vnodes which were found to
75: * be aliased by callers of checkalias().
76: * For the ops vector for vnodes built from special devices found in a
77: * filesystem, see (e.g) ffs_specop_entries[] in ffs_vnops.c or the
78: * equivalent for other filesystems.
79: */
1.1 cgd 80:
1.28 christos 81: int (**spec_vnodeop_p) __P((void *));
1.53 jdolecek 82: const struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
1.15 mycroft 83: { &vop_default_desc, vn_default_error },
84: { &vop_lookup_desc, spec_lookup }, /* lookup */
85: { &vop_create_desc, spec_create }, /* create */
86: { &vop_mknod_desc, spec_mknod }, /* mknod */
87: { &vop_open_desc, spec_open }, /* open */
88: { &vop_close_desc, spec_close }, /* close */
89: { &vop_access_desc, spec_access }, /* access */
90: { &vop_getattr_desc, spec_getattr }, /* getattr */
91: { &vop_setattr_desc, spec_setattr }, /* setattr */
92: { &vop_read_desc, spec_read }, /* read */
93: { &vop_write_desc, spec_write }, /* write */
1.21 mycroft 94: { &vop_lease_desc, spec_lease_check }, /* lease */
1.47 sommerfe 95: { &vop_fcntl_desc, spec_fcntl }, /* fcntl */
1.15 mycroft 96: { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
1.32 mycroft 97: { &vop_poll_desc, spec_poll }, /* poll */
1.54.2.1 lukem 98: { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */
1.39 fvdl 99: { &vop_revoke_desc, spec_revoke }, /* revoke */
1.15 mycroft 100: { &vop_mmap_desc, spec_mmap }, /* mmap */
101: { &vop_fsync_desc, spec_fsync }, /* fsync */
102: { &vop_seek_desc, spec_seek }, /* seek */
103: { &vop_remove_desc, spec_remove }, /* remove */
104: { &vop_link_desc, spec_link }, /* link */
105: { &vop_rename_desc, spec_rename }, /* rename */
106: { &vop_mkdir_desc, spec_mkdir }, /* mkdir */
107: { &vop_rmdir_desc, spec_rmdir }, /* rmdir */
108: { &vop_symlink_desc, spec_symlink }, /* symlink */
109: { &vop_readdir_desc, spec_readdir }, /* readdir */
110: { &vop_readlink_desc, spec_readlink }, /* readlink */
111: { &vop_abortop_desc, spec_abortop }, /* abortop */
112: { &vop_inactive_desc, spec_inactive }, /* inactive */
113: { &vop_reclaim_desc, spec_reclaim }, /* reclaim */
114: { &vop_lock_desc, spec_lock }, /* lock */
115: { &vop_unlock_desc, spec_unlock }, /* unlock */
116: { &vop_bmap_desc, spec_bmap }, /* bmap */
117: { &vop_strategy_desc, spec_strategy }, /* strategy */
118: { &vop_print_desc, spec_print }, /* print */
119: { &vop_islocked_desc, spec_islocked }, /* islocked */
120: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
121: { &vop_advlock_desc, spec_advlock }, /* advlock */
122: { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */
123: { &vop_valloc_desc, spec_valloc }, /* valloc */
124: { &vop_vfree_desc, spec_vfree }, /* vfree */
125: { &vop_truncate_desc, spec_truncate }, /* truncate */
126: { &vop_update_desc, spec_update }, /* update */
1.28 christos 127: { &vop_bwrite_desc, spec_bwrite }, /* bwrite */
1.54.2.2 thorpej 128: { &vop_getpages_desc, spec_getpages }, /* getpages */
129: { &vop_putpages_desc, spec_putpages }, /* putpages */
130: { NULL, NULL }
1.1 cgd 131: };
1.53 jdolecek 132: const struct vnodeopv_desc spec_vnodeop_opv_desc =
1.15 mycroft 133: { &spec_vnodeop_p, spec_vnodeop_entries };
1.1 cgd 134:
135: /*
136: * Trivial lookup routine that always fails.
137: */
1.4 andrew 138: int
1.28 christos 139: spec_lookup(v)
140: void *v;
141: {
1.15 mycroft 142: struct vop_lookup_args /* {
143: struct vnode *a_dvp;
144: struct vnode **a_vpp;
145: struct componentname *a_cnp;
1.28 christos 146: } */ *ap = v;
1.1 cgd 147:
1.15 mycroft 148: *ap->a_vpp = NULL;
1.1 cgd 149: return (ENOTDIR);
150: }
151:
152: /*
1.15 mycroft 153: * Open a special file.
1.1 cgd 154: */
155: /* ARGSUSED */
1.28 christos 156: int
157: spec_open(v)
158: void *v;
159: {
1.15 mycroft 160: struct vop_open_args /* {
161: struct vnode *a_vp;
162: int a_mode;
163: struct ucred *a_cred;
164: struct proc *a_p;
1.28 christos 165: } */ *ap = v;
1.39 fvdl 166: struct proc *p = ap->a_p;
1.15 mycroft 167: struct vnode *bvp, *vp = ap->a_vp;
168: dev_t bdev, dev = (dev_t)vp->v_rdev;
1.48 augustss 169: int maj = major(dev);
1.1 cgd 170: int error;
1.54.2.2 thorpej 171: struct partinfo pi;
1.1 cgd 172:
1.15 mycroft 173: /*
174: * Don't allow open if fs is mounted -nodev.
175: */
1.1 cgd 176: if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
177: return (ENXIO);
178:
179: switch (vp->v_type) {
180:
181: case VCHR:
182: if ((u_int)maj >= nchrdev)
183: return (ENXIO);
1.15 mycroft 184: if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
185: /*
186: * When running in very secure mode, do not allow
187: * opens for writing of any disk character devices.
188: */
1.23 mycroft 189: if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK)
1.15 mycroft 190: return (EPERM);
191: /*
192: * When running in secure mode, do not allow opens
193: * for writing of /dev/mem, /dev/kmem, or character
194: * devices whose corresponding block devices are
195: * currently mounted.
196: */
197: if (securelevel >= 1) {
1.38 christos 198: if ((bdev = chrtoblk(dev)) != (dev_t)NODEV &&
1.15 mycroft 199: vfinddev(bdev, VBLK, &bvp) &&
200: (error = vfs_mountedon(bvp)))
201: return (error);
202: if (iskmemdev(dev))
203: return (EPERM);
204: }
205: }
1.23 mycroft 206: if (cdevsw[maj].d_type == D_TTY)
207: vp->v_flag |= VISTTY;
1.39 fvdl 208: VOP_UNLOCK(vp, 0);
209: error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, p);
210: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1 cgd 211: return (error);
212:
213: case VBLK:
214: if ((u_int)maj >= nblkdev)
215: return (ENXIO);
1.15 mycroft 216: /*
217: * When running in very secure mode, do not allow
218: * opens for writing of any disk block devices.
219: */
220: if (securelevel >= 2 && ap->a_cred != FSCRED &&
1.23 mycroft 221: (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK)
1.15 mycroft 222: return (EPERM);
223: /*
224: * Do not allow opens of block devices that are
225: * currently mounted.
226: */
1.28 christos 227: if ((error = vfs_mountedon(vp)) != 0)
1.1 cgd 228: return (error);
1.54.2.2 thorpej 229: error = (*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p);
230: if (error) {
231: return error;
232: }
233: error = (*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev,
234: DIOCGPART, (caddr_t)&pi, FREAD, curproc);
235: if (error == 0) {
1.54.2.3 thorpej 236: vp->v_size = (voff_t)pi.disklab->d_secsize *
1.54.2.2 thorpej 237: pi.part->p_size;
238: }
239: return 0;
240:
1.28 christos 241: case VNON:
242: case VLNK:
243: case VDIR:
244: case VREG:
245: case VBAD:
246: case VFIFO:
247: case VSOCK:
248: break;
1.1 cgd 249: }
1.15 mycroft 250: return (0);
1.1 cgd 251: }
252:
253: /*
254: * Vnode op for read
255: */
256: /* ARGSUSED */
1.28 christos 257: int
258: spec_read(v)
259: void *v;
260: {
1.15 mycroft 261: struct vop_read_args /* {
262: struct vnode *a_vp;
263: struct uio *a_uio;
264: int a_ioflag;
265: struct ucred *a_cred;
1.28 christos 266: } */ *ap = v;
1.48 augustss 267: struct vnode *vp = ap->a_vp;
268: struct uio *uio = ap->a_uio;
1.15 mycroft 269: struct proc *p = uio->uio_procp;
1.1 cgd 270: struct buf *bp;
1.54.2.3 thorpej 271: daddr_t bn;
272: int bsize, bscale;
1.1 cgd 273: struct partinfo dpart;
1.28 christos 274: int n, on, majordev;
275: int (*ioctl) __P((dev_t, u_long, caddr_t, int, struct proc *));
1.1 cgd 276: int error = 0;
277:
278: #ifdef DIAGNOSTIC
279: if (uio->uio_rw != UIO_READ)
280: panic("spec_read mode");
281: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
282: panic("spec_read proc");
283: #endif
284: if (uio->uio_resid == 0)
285: return (0);
286:
287: switch (vp->v_type) {
288:
289: case VCHR:
1.39 fvdl 290: VOP_UNLOCK(vp, 0);
1.1 cgd 291: error = (*cdevsw[major(vp->v_rdev)].d_read)
1.15 mycroft 292: (vp->v_rdev, uio, ap->a_ioflag);
1.54.2.3 thorpej 293: vn_lock(vp, LK_SHARED | LK_RETRY);
1.1 cgd 294: return (error);
295:
296: case VBLK:
297: if (uio->uio_offset < 0)
298: return (EINVAL);
299: bsize = BLKDEV_IOSIZE;
1.24 mycroft 300: if ((majordev = major(vp->v_rdev)) < nblkdev &&
1.15 mycroft 301: (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
1.24 mycroft 302: (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
1.17 paulus 303: if (dpart.part->p_fstype == FS_BSDFFS &&
304: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
305: bsize = dpart.part->p_frag *
306: dpart.part->p_fsize;
307: }
1.54.2.3 thorpej 308: bscale = bsize >> DEV_BSHIFT;
1.1 cgd 309: do {
1.54.2.3 thorpej 310: bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1);
1.1 cgd 311: on = uio->uio_offset % bsize;
1.14 cgd 312: n = min((unsigned)(bsize - on), uio->uio_resid);
1.54.2.3 thorpej 313: error = bread(vp, bn, bsize, NOCRED, &bp);
1.14 cgd 314: n = min(n, bsize - bp->b_resid);
1.1 cgd 315: if (error) {
316: brelse(bp);
317: return (error);
318: }
1.15 mycroft 319: error = uiomove((char *)bp->b_data + on, n, uio);
1.1 cgd 320: brelse(bp);
321: } while (error == 0 && uio->uio_resid > 0 && n != 0);
322: return (error);
323:
324: default:
325: panic("spec_read type");
326: }
327: /* NOTREACHED */
328: }
329:
330: /*
331: * Vnode op for write
332: */
333: /* ARGSUSED */
1.28 christos 334: int
335: spec_write(v)
336: void *v;
337: {
1.15 mycroft 338: struct vop_write_args /* {
339: struct vnode *a_vp;
340: struct uio *a_uio;
341: int a_ioflag;
342: struct ucred *a_cred;
1.28 christos 343: } */ *ap = v;
1.48 augustss 344: struct vnode *vp = ap->a_vp;
345: struct uio *uio = ap->a_uio;
1.1 cgd 346: struct proc *p = uio->uio_procp;
347: struct buf *bp;
348: daddr_t bn;
1.54.2.3 thorpej 349: int bsize, bscale;
1.1 cgd 350: struct partinfo dpart;
1.28 christos 351: int n, on, majordev;
352: int (*ioctl) __P((dev_t, u_long, caddr_t, int, struct proc *));
1.1 cgd 353: int error = 0;
354:
355: #ifdef DIAGNOSTIC
356: if (uio->uio_rw != UIO_WRITE)
357: panic("spec_write mode");
358: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
359: panic("spec_write proc");
360: #endif
361:
362: switch (vp->v_type) {
363:
364: case VCHR:
1.39 fvdl 365: VOP_UNLOCK(vp, 0);
1.1 cgd 366: error = (*cdevsw[major(vp->v_rdev)].d_write)
1.15 mycroft 367: (vp->v_rdev, uio, ap->a_ioflag);
1.39 fvdl 368: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1 cgd 369: return (error);
370:
371: case VBLK:
372: if (uio->uio_resid == 0)
373: return (0);
374: if (uio->uio_offset < 0)
375: return (EINVAL);
376: bsize = BLKDEV_IOSIZE;
1.24 mycroft 377: if ((majordev = major(vp->v_rdev)) < nblkdev &&
378: (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
379: (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
1.1 cgd 380: if (dpart.part->p_fstype == FS_BSDFFS &&
381: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
382: bsize = dpart.part->p_frag *
383: dpart.part->p_fsize;
384: }
1.54.2.3 thorpej 385: bscale = bsize >> DEV_BSHIFT;
1.1 cgd 386: do {
1.54.2.3 thorpej 387: bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1);
1.1 cgd 388: on = uio->uio_offset % bsize;
1.14 cgd 389: n = min((unsigned)(bsize - on), uio->uio_resid);
1.1 cgd 390: if (n == bsize)
1.13 cgd 391: bp = getblk(vp, bn, bsize, 0, 0);
1.1 cgd 392: else
393: error = bread(vp, bn, bsize, NOCRED, &bp);
394: if (error) {
395: brelse(bp);
396: return (error);
397: }
1.43 ross 398: n = min(n, bsize - bp->b_resid);
1.15 mycroft 399: error = uiomove((char *)bp->b_data + on, n, uio);
1.43 ross 400: if (error)
401: brelse(bp);
402: else {
403: if (n + on == bsize)
404: bawrite(bp);
405: else
406: bdwrite(bp);
407: if (bp->b_flags & B_ERROR)
408: error = bp->b_error;
409: }
1.1 cgd 410: } while (error == 0 && uio->uio_resid > 0 && n != 0);
411: return (error);
412:
413: default:
414: panic("spec_write type");
415: }
416: /* NOTREACHED */
417: }
418:
419: /*
420: * Device ioctl operation.
421: */
422: /* ARGSUSED */
1.28 christos 423: int
424: spec_ioctl(v)
425: void *v;
426: {
1.15 mycroft 427: struct vop_ioctl_args /* {
428: struct vnode *a_vp;
1.19 cgd 429: u_long a_command;
1.15 mycroft 430: caddr_t a_data;
431: int a_fflag;
432: struct ucred *a_cred;
433: struct proc *a_p;
1.28 christos 434: } */ *ap = v;
1.15 mycroft 435: dev_t dev = ap->a_vp->v_rdev;
1.23 mycroft 436: int maj = major(dev);
1.1 cgd 437:
1.15 mycroft 438: switch (ap->a_vp->v_type) {
1.1 cgd 439:
440: case VCHR:
1.23 mycroft 441: return ((*cdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
1.15 mycroft 442: ap->a_fflag, ap->a_p));
1.1 cgd 443:
444: case VBLK:
1.42 thorpej 445: if (ap->a_command == 0 && (long)ap->a_data == B_TAPE) {
1.23 mycroft 446: if (bdevsw[maj].d_type == D_TAPE)
1.1 cgd 447: return (0);
448: else
449: return (1);
1.42 thorpej 450: }
1.23 mycroft 451: return ((*bdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
1.15 mycroft 452: ap->a_fflag, ap->a_p));
1.1 cgd 453:
454: default:
455: panic("spec_ioctl");
456: /* NOTREACHED */
457: }
458: }
459:
460: /* ARGSUSED */
1.28 christos 461: int
1.32 mycroft 462: spec_poll(v)
1.28 christos 463: void *v;
464: {
1.32 mycroft 465: struct vop_poll_args /* {
1.15 mycroft 466: struct vnode *a_vp;
1.32 mycroft 467: int a_events;
1.15 mycroft 468: struct proc *a_p;
1.28 christos 469: } */ *ap = v;
1.48 augustss 470: dev_t dev;
1.1 cgd 471:
1.15 mycroft 472: switch (ap->a_vp->v_type) {
1.1 cgd 473:
474: case VCHR:
1.15 mycroft 475: dev = ap->a_vp->v_rdev;
1.32 mycroft 476: return (*cdevsw[major(dev)].d_poll)(dev, ap->a_events, ap->a_p);
1.30 mycroft 477:
478: default:
1.32 mycroft 479: return (genfs_poll(v));
1.15 mycroft 480: }
481: }
1.54.2.1 lukem 482:
483: /* ARGSUSED */
484: int
485: spec_kqfilter(v)
486: void *v;
487: {
488: struct vop_kqfilter_args /* {
489: struct vnode *a_vp;
490: struct proc *a_kn;
491: } */ *ap = v;
492: dev_t dev;
493:
494: switch (ap->a_vp->v_type) {
495:
496: case VCHR:
497: dev = ap->a_vp->v_rdev;
498: return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn);
499: default:
500: #if 1 /* XXXLUKEM; no genfs_kqfilter (yet) */
501: return (0);
502: #else
503: return (genfs_kqfilter(v));
504: #endif
505: }
506: }
507:
1.15 mycroft 508: /*
509: * Synch buffers associated with a block device
510: */
511: /* ARGSUSED */
512: int
1.28 christos 513: spec_fsync(v)
514: void *v;
515: {
1.15 mycroft 516: struct vop_fsync_args /* {
517: struct vnode *a_vp;
518: struct ucred *a_cred;
1.40 kleink 519: int a_flags;
1.50 fvdl 520: off_t offlo;
521: off_t offhi;
1.15 mycroft 522: struct proc *a_p;
1.28 christos 523: } */ *ap = v;
1.48 augustss 524: struct vnode *vp = ap->a_vp;
1.15 mycroft 525:
1.30 mycroft 526: if (vp->v_type == VBLK)
1.40 kleink 527: vflushbuf(vp, (ap->a_flags & FSYNC_WAIT) != 0);
1.15 mycroft 528: return (0);
1.1 cgd 529: }
530:
531: /*
532: * Just call the device strategy routine
533: */
1.28 christos 534: int
535: spec_strategy(v)
536: void *v;
537: {
1.15 mycroft 538: struct vop_strategy_args /* {
539: struct buf *a_bp;
1.28 christos 540: } */ *ap = v;
1.45 fvdl 541: struct buf *bp;
1.1 cgd 542:
1.45 fvdl 543: bp = ap->a_bp;
544: if (!(bp->b_flags & B_READ) &&
545: (LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
546: (*bioops.io_start)(bp);
547: (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
1.1 cgd 548: return (0);
549: }
550:
1.39 fvdl 551: int
552: spec_inactive(v)
553: void *v;
554: {
555: struct vop_inactive_args /* {
556: struct vnode *a_vp;
557: struct proc *a_p;
558: } */ *ap = v;
559:
560: VOP_UNLOCK(ap->a_vp, 0);
561: return (0);
562: }
563:
1.1 cgd 564: /*
565: * This is a noop, simply returning what one has been given.
566: */
1.28 christos 567: int
568: spec_bmap(v)
569: void *v;
570: {
1.15 mycroft 571: struct vop_bmap_args /* {
572: struct vnode *a_vp;
573: daddr_t a_bn;
574: struct vnode **a_vpp;
575: daddr_t *a_bnp;
1.39 fvdl 576: int *a_runp;
1.28 christos 577: } */ *ap = v;
1.1 cgd 578:
1.15 mycroft 579: if (ap->a_vpp != NULL)
580: *ap->a_vpp = ap->a_vp;
581: if (ap->a_bnp != NULL)
582: *ap->a_bnp = ap->a_bn;
1.39 fvdl 583: if (ap->a_runp != NULL)
1.54.2.2 thorpej 584: *ap->a_runp = (MAXBSIZE >> DEV_BSHIFT) - 1;
1.1 cgd 585: return (0);
586: }
587:
588: /*
589: * Device close routine
590: */
591: /* ARGSUSED */
1.28 christos 592: int
593: spec_close(v)
594: void *v;
595: {
1.15 mycroft 596: struct vop_close_args /* {
597: struct vnode *a_vp;
598: int a_fflag;
599: struct ucred *a_cred;
600: struct proc *a_p;
1.28 christos 601: } */ *ap = v;
1.48 augustss 602: struct vnode *vp = ap->a_vp;
1.1 cgd 603: dev_t dev = vp->v_rdev;
604: int (*devclose) __P((dev_t, int, int, struct proc *));
1.44 wrstuden 605: int mode, error, count, flags, flags1;
606:
1.54 thorpej 607: count = vcount(vp);
1.44 wrstuden 608: simple_lock(&vp->v_interlock);
609: flags = vp->v_flag;
610: simple_unlock(&vp->v_interlock);
1.1 cgd 611:
612: switch (vp->v_type) {
613:
614: case VCHR:
1.11 cgd 615: /*
616: * Hack: a tty device that is a controlling terminal
617: * has a reference from the session structure.
618: * We cannot easily tell that a character device is
619: * a controlling terminal, unless it is the closing
620: * process' controlling terminal. In that case,
621: * if the reference count is 2 (this last descriptor
622: * plus the session), release the reference from the session.
623: */
1.44 wrstuden 624: if (count == 2 && ap->a_p &&
1.15 mycroft 625: vp == ap->a_p->p_session->s_ttyvp) {
1.11 cgd 626: vrele(vp);
1.44 wrstuden 627: count--;
1.15 mycroft 628: ap->a_p->p_session->s_ttyvp = NULL;
1.11 cgd 629: }
1.1 cgd 630: /*
631: * If the vnode is locked, then we are in the midst
632: * of forcably closing the device, otherwise we only
633: * close on last reference.
634: */
1.44 wrstuden 635: if (count > 1 && (flags & VXLOCK) == 0)
1.1 cgd 636: return (0);
637: devclose = cdevsw[major(dev)].d_close;
638: mode = S_IFCHR;
639: break;
640:
641: case VBLK:
642: /*
643: * On last close of a block device (that isn't mounted)
644: * we must invalidate any in core blocks, so that
645: * we can, for instance, change floppy disks.
646: */
1.28 christos 647: error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
648: if (error)
1.15 mycroft 649: return (error);
1.1 cgd 650: /*
651: * We do not want to really close the device if it
652: * is still in use unless we are trying to close it
653: * forcibly. Since every use (buffer, vnode, swap, cmap)
654: * holds a reference to the vnode, and because we mark
655: * any other vnodes that alias this device, when the
656: * sum of the reference counts on all the aliased
657: * vnodes descends to one, we are on last close.
658: */
1.44 wrstuden 659: if (count > 1 && (flags & VXLOCK) == 0)
1.1 cgd 660: return (0);
661: devclose = bdevsw[major(dev)].d_close;
662: mode = S_IFBLK;
663: break;
1.5 cgd 664:
1.1 cgd 665: default:
666: panic("spec_close: not special");
667: }
668:
1.44 wrstuden 669: flags1 = ap->a_fflag;
670:
671: /*
672: * if VXLOCK is set, then we're going away soon, so make this
673: * non-blocking. Also ensures that we won't wedge in vn_lock below.
674: */
675: if (flags & VXLOCK)
676: flags1 |= FNONBLOCK;
677:
678: /*
679: * If we're able to block, release the vnode lock & reaquire. We
680: * might end up sleaping for someone else who wants our queues. They
681: * won't get them if we hold the vnode locked. Also, if VXLOCK is set,
682: * don't release the lock as we won't be able to regain it.
683: */
684: if (!(flags1 & FNONBLOCK))
685: VOP_UNLOCK(vp, 0);
686:
687: error = (*devclose)(dev, flags1, mode, ap->a_p);
688:
689: if (!(flags1 & FNONBLOCK))
690: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
691:
692: return (error);
1.1 cgd 693: }
694:
695: /*
696: * Print out the contents of a special device vnode.
697: */
1.28 christos 698: int
699: spec_print(v)
700: void *v;
701: {
1.15 mycroft 702: struct vop_print_args /* {
703: struct vnode *a_vp;
1.28 christos 704: } */ *ap = v;
1.15 mycroft 705:
1.34 christos 706: printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
1.33 christos 707: minor(ap->a_vp->v_rdev));
1.28 christos 708: return 0;
1.15 mycroft 709: }
710:
711: /*
712: * Return POSIX pathconf information applicable to special devices.
713: */
1.28 christos 714: int
715: spec_pathconf(v)
716: void *v;
717: {
1.15 mycroft 718: struct vop_pathconf_args /* {
719: struct vnode *a_vp;
720: int a_name;
1.18 cgd 721: register_t *a_retval;
1.28 christos 722: } */ *ap = v;
1.1 cgd 723:
1.15 mycroft 724: switch (ap->a_name) {
725: case _PC_LINK_MAX:
726: *ap->a_retval = LINK_MAX;
727: return (0);
728: case _PC_MAX_CANON:
729: *ap->a_retval = MAX_CANON;
730: return (0);
731: case _PC_MAX_INPUT:
732: *ap->a_retval = MAX_INPUT;
733: return (0);
734: case _PC_PIPE_BUF:
735: *ap->a_retval = PIPE_BUF;
736: return (0);
737: case _PC_CHOWN_RESTRICTED:
738: *ap->a_retval = 1;
739: return (0);
740: case _PC_VDISABLE:
741: *ap->a_retval = _POSIX_VDISABLE;
1.41 kleink 742: return (0);
743: case _PC_SYNC_IO:
744: *ap->a_retval = 1;
1.15 mycroft 745: return (0);
746: default:
747: return (EINVAL);
748: }
1.1 cgd 749: /* NOTREACHED */
1.35 kleink 750: }
751:
752: /*
753: * Advisory record locking support.
754: */
755: int
756: spec_advlock(v)
757: void *v;
758: {
759: struct vop_advlock_args /* {
760: struct vnode *a_vp;
761: caddr_t a_id;
762: int a_op;
763: struct flock *a_fl;
764: int a_flags;
765: } */ *ap = v;
1.48 augustss 766: struct vnode *vp = ap->a_vp;
1.35 kleink 767:
1.49 jdolecek 768: return lf_advlock(ap, &vp->v_speclockf, (off_t)0);
1.1 cgd 769: }
CVSweb <webmaster@jp.NetBSD.org>