xref: /netbsd-src/sys/miscfs/specfs/spec_vnops.c (revision 811e6386f8c5e4a3521c7003da29ec8673e344fa)
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
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
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"
57 #include "dkbad.h"	/* XXX */
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);
228 #ifdef OMIT	/* 20 Aug 92*/
229 			if (n + on == bsize)
230 				bp->b_flags |= B_AGE;
231 #endif	/* OMIT*/
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 }
529