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