|
|
1.1 root 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: * @(#)spec_vnops.c 7.37 (Berkeley) 5/30/91
1.1.1.3 ! root 34: *
! 35: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
! 36: * -------------------- ----- ----------------------
! 37: * CURRENT PATCH LEVEL: 1 00007
! 38: * -------------------- ----- ----------------------
! 39: *
! 40: * 20 Aug 92 David Greenman Fixed incorrect setting of B_AGE on
1.1 root 41: */
42:
43: #include "param.h"
44: #include "proc.h"
45: #include "systm.h"
46: #include "kernel.h"
47: #include "conf.h"
48: #include "buf.h"
49: #include "mount.h"
50: #include "namei.h"
51: #include "vnode.h"
52: #include "specdev.h"
53: #include "stat.h"
54: #include "errno.h"
55: #include "ioctl.h"
56: #include "file.h"
1.1.1.2 root 57: #include "dkbad.h" /* XXX */
1.1 root 58: #include "disklabel.h"
59:
60: /* symbolic sleep message strings for devices */
61: char devopn[] = "devopn";
62: char devio[] = "devio";
63: char devwait[] = "devwait";
64: char devin[] = "devin";
65: char devout[] = "devout";
66: char devioc[] = "devioc";
67: char devcls[] = "devcls";
68:
69: struct vnodeops spec_vnodeops = {
70: spec_lookup, /* lookup */
71: spec_create, /* create */
72: spec_mknod, /* mknod */
73: spec_open, /* open */
74: spec_close, /* close */
75: spec_access, /* access */
76: spec_getattr, /* getattr */
77: spec_setattr, /* setattr */
78: spec_read, /* read */
79: spec_write, /* write */
80: spec_ioctl, /* ioctl */
81: spec_select, /* select */
82: spec_mmap, /* mmap */
83: spec_fsync, /* fsync */
84: spec_seek, /* seek */
85: spec_remove, /* remove */
86: spec_link, /* link */
87: spec_rename, /* rename */
88: spec_mkdir, /* mkdir */
89: spec_rmdir, /* rmdir */
90: spec_symlink, /* symlink */
91: spec_readdir, /* readdir */
92: spec_readlink, /* readlink */
93: spec_abortop, /* abortop */
94: spec_inactive, /* inactive */
95: spec_reclaim, /* reclaim */
96: spec_lock, /* lock */
97: spec_unlock, /* unlock */
98: spec_bmap, /* bmap */
99: spec_strategy, /* strategy */
100: spec_print, /* print */
101: spec_islocked, /* islocked */
102: spec_advlock, /* advlock */
103: };
104:
105: /*
106: * Trivial lookup routine that always fails.
107: */
108: spec_lookup(vp, ndp, p)
109: struct vnode *vp;
110: struct nameidata *ndp;
111: struct proc *p;
112: {
113:
114: ndp->ni_dvp = vp;
115: ndp->ni_vp = NULL;
116: return (ENOTDIR);
117: }
118:
119: /*
120: * Open a special file: Don't allow open if fs is mounted -nodev,
121: * and don't allow opens of block devices that are currently mounted.
122: * Otherwise, call device driver open function.
123: */
124: /* ARGSUSED */
125: spec_open(vp, mode, cred, p)
126: register struct vnode *vp;
127: int mode;
128: struct ucred *cred;
129: struct proc *p;
130: {
131: dev_t dev = (dev_t)vp->v_rdev;
132: register int maj = major(dev);
133: int error;
134:
135: if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
136: return (ENXIO);
137:
138: switch (vp->v_type) {
139:
140: case VCHR:
141: if ((u_int)maj >= nchrdev)
142: return (ENXIO);
143: VOP_UNLOCK(vp);
144: error = (*cdevsw[maj].d_open)(dev, mode, S_IFCHR, p);
145: VOP_LOCK(vp);
146: return (error);
147:
148: case VBLK:
149: if ((u_int)maj >= nblkdev)
150: return (ENXIO);
151: if (error = mountedon(vp))
152: return (error);
153: return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK, p));
154: }
155: return (0);
156: }
157:
158: /*
159: * Vnode op for read
160: */
161: /* ARGSUSED */
162: spec_read(vp, uio, ioflag, cred)
163: register struct vnode *vp;
164: register struct uio *uio;
165: int ioflag;
166: struct ucred *cred;
167: {
168: struct proc *p = uio->uio_procp;
169: struct buf *bp;
170: daddr_t bn;
171: long bsize, bscale;
172: struct partinfo dpart;
173: register int n, on;
174: int error = 0;
175: extern int mem_no;
176:
177: #ifdef DIAGNOSTIC
178: if (uio->uio_rw != UIO_READ)
179: panic("spec_read mode");
180: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
181: panic("spec_read proc");
182: #endif
183: if (uio->uio_resid == 0)
184: return (0);
185:
186: switch (vp->v_type) {
187:
188: case VCHR:
189: /*
190: * Negative offsets allowed only for /dev/kmem
191: */
192: if (uio->uio_offset < 0 && major(vp->v_rdev) != mem_no)
193: return (EINVAL);
194: VOP_UNLOCK(vp);
195: error = (*cdevsw[major(vp->v_rdev)].d_read)
196: (vp->v_rdev, uio, ioflag);
197: VOP_LOCK(vp);
198: return (error);
199:
200: case VBLK:
201: if (uio->uio_offset < 0)
202: return (EINVAL);
203: bsize = BLKDEV_IOSIZE;
204: if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
205: (caddr_t)&dpart, FREAD, p) == 0) {
206: if (dpart.part->p_fstype == FS_BSDFFS &&
207: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
208: bsize = dpart.part->p_frag *
209: dpart.part->p_fsize;
210: }
211: bscale = bsize / DEV_BSIZE;
212: do {
213: bn = (uio->uio_offset / DEV_BSIZE) &~ (bscale - 1);
214: on = uio->uio_offset % bsize;
215: n = MIN((unsigned)(bsize - on), uio->uio_resid);
216: if (vp->v_lastr + bscale == bn)
217: error = breada(vp, bn, (int)bsize, bn + bscale,
218: (int)bsize, NOCRED, &bp);
219: else
220: error = bread(vp, bn, (int)bsize, NOCRED, &bp);
221: vp->v_lastr = bn;
222: n = MIN(n, bsize - bp->b_resid);
223: if (error) {
224: brelse(bp);
225: return (error);
226: }
227: error = uiomove(bp->b_un.b_addr + on, n, uio);
1.1.1.3 ! root 228: #ifdef OMIT /* 20 Aug 92*/
1.1 root 229: if (n + on == bsize)
230: bp->b_flags |= B_AGE;
1.1.1.3 ! root 231: #endif /* OMIT*/
1.1 root 232: brelse(bp);
233: } while (error == 0 && uio->uio_resid > 0 && n != 0);
234: return (error);
235:
236: default:
237: panic("spec_read type");
238: }
239: /* NOTREACHED */
240: }
241:
242: /*
243: * Vnode op for write
244: */
245: /* ARGSUSED */
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: spec_ioctl(vp, com, data, fflag, cred, p)
329: struct vnode *vp;
330: int com;
331: caddr_t data;
332: int fflag;
333: struct ucred *cred;
334: struct proc *p;
335: {
336: dev_t dev = vp->v_rdev;
337:
338: switch (vp->v_type) {
339:
340: case VCHR:
341: return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data,
342: fflag, p));
343:
344: case VBLK:
345: if (com == 0 && (int)data == B_TAPE)
346: if (bdevsw[major(dev)].d_flags & B_TAPE)
347: return (0);
348: else
349: return (1);
350: return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data,
351: fflag, p));
352:
353: default:
354: panic("spec_ioctl");
355: /* NOTREACHED */
356: }
357: }
358:
359: /* ARGSUSED */
360: spec_select(vp, which, fflags, cred, p)
361: struct vnode *vp;
362: int which, fflags;
363: struct ucred *cred;
364: struct proc *p;
365: {
366: register dev_t dev;
367:
368: switch (vp->v_type) {
369:
370: default:
371: return (1); /* XXX */
372:
373: case VCHR:
374: dev = vp->v_rdev;
375: return (*cdevsw[major(dev)].d_select)(dev, which, p);
376: }
377: }
378:
379: /*
380: * Just call the device strategy routine
381: */
382: spec_strategy(bp)
383: register struct buf *bp;
384: {
385:
386: (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
387: return (0);
388: }
389:
390: /*
391: * This is a noop, simply returning what one has been given.
392: */
393: spec_bmap(vp, bn, vpp, bnp)
394: struct vnode *vp;
395: daddr_t bn;
396: struct vnode **vpp;
397: daddr_t *bnp;
398: {
399:
400: if (vpp != NULL)
401: *vpp = vp;
402: if (bnp != NULL)
403: *bnp = bn;
404: return (0);
405: }
406:
407: /*
408: * At the moment we do not do any locking.
409: */
410: /* ARGSUSED */
411: spec_lock(vp)
412: struct vnode *vp;
413: {
414:
415: return (0);
416: }
417:
418: /* ARGSUSED */
419: spec_unlock(vp)
420: struct vnode *vp;
421: {
422:
423: return (0);
424: }
425:
426: /*
427: * Device close routine
428: */
429: /* ARGSUSED */
430: spec_close(vp, flag, cred, p)
431: register struct vnode *vp;
432: int flag;
433: struct ucred *cred;
434: struct proc *p;
435: {
436: dev_t dev = vp->v_rdev;
437: int (*devclose) __P((dev_t, int, int, struct proc *));
438: int mode;
439:
440: switch (vp->v_type) {
441:
442: case VCHR:
443: /*
444: * If the vnode is locked, then we are in the midst
445: * of forcably closing the device, otherwise we only
446: * close on last reference.
447: */
448: if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
449: return (0);
450: devclose = cdevsw[major(dev)].d_close;
451: mode = S_IFCHR;
452: break;
453:
454: case VBLK:
455: /*
456: * On last close of a block device (that isn't mounted)
457: * we must invalidate any in core blocks, so that
458: * we can, for instance, change floppy disks.
459: */
460: vflushbuf(vp, 0);
461: if (vinvalbuf(vp, 1))
462: return (0);
463: /*
464: * We do not want to really close the device if it
465: * is still in use unless we are trying to close it
466: * forcibly. Since every use (buffer, vnode, swap, cmap)
467: * holds a reference to the vnode, and because we mark
468: * any other vnodes that alias this device, when the
469: * sum of the reference counts on all the aliased
470: * vnodes descends to one, we are on last close.
471: */
472: if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
473: return (0);
474: devclose = bdevsw[major(dev)].d_close;
475: mode = S_IFBLK;
476: break;
477:
478: default:
479: panic("spec_close: not special");
480: }
481:
482: return ((*devclose)(dev, flag, mode, p));
483: }
484:
485: /*
486: * Print out the contents of a special device vnode.
487: */
488: spec_print(vp)
489: struct vnode *vp;
490: {
491:
492: printf("tag VT_NON, dev %d, %d\n", major(vp->v_rdev),
493: minor(vp->v_rdev));
494: }
495:
496: /*
497: * Special device advisory byte-level locks.
498: */
499: /* ARGSUSED */
500: spec_advlock(vp, id, op, fl, flags)
501: struct vnode *vp;
502: caddr_t id;
503: int op;
504: struct flock *fl;
505: int flags;
506: {
507:
508: return (EOPNOTSUPP);
509: }
510:
511: /*
512: * Special device failed operation
513: */
514: spec_ebadf()
515: {
516:
517: return (EBADF);
518: }
519:
520: /*
521: * Special device bad operation
522: */
523: spec_badop()
524: {
525:
526: panic("spec_badop called");
527: /* NOTREACHED */
528: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.