]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/miscfs/specfs/spec_vnops.c
This commit was generated by cvs2svn to compensate for changes in r35516,
[FreeBSD/FreeBSD.git] / sys / miscfs / specfs / spec_vnops.c
1 /*
2  * Copyright (c) 1989, 1993, 1995
3  *      The Regents of the University of California.  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        8.14 (Berkeley) 5/21/95
34  * $Id: spec_vnops.c,v 1.60 1998/03/08 09:57:36 julian 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/vnode.h>
45 #include <sys/stat.h>
46 #include <sys/fcntl.h>
47 #include <sys/disklabel.h>
48 #include <sys/vmmeter.h>
49
50 #include <vm/vm.h>
51 #include <vm/vm_prot.h>
52 #include <vm/vm_object.h>
53 #include <vm/vm_page.h>
54 #include <vm/vm_pager.h>
55 #include <vm/vnode_pager.h>
56 #include <vm/vm_extern.h>
57
58 #include <miscfs/specfs/specdev.h>
59
60 static int      spec_getattr __P((struct  vop_getattr_args *));
61 static int      spec_badop __P((void));
62 static int      spec_strategy __P((struct vop_strategy_args *));
63 static int      spec_print __P((struct vop_print_args *));
64 static int      spec_lookup __P((struct vop_lookup_args *));
65 static int      spec_open __P((struct vop_open_args *));
66 static int      spec_close __P((struct vop_close_args *));
67 static int      spec_read __P((struct vop_read_args *));  
68 static int      spec_write __P((struct vop_write_args *));
69 static int      spec_ioctl __P((struct vop_ioctl_args *));
70 static int      spec_poll __P((struct vop_poll_args *));
71 static int      spec_inactive __P((struct  vop_inactive_args *));
72 static int      spec_fsync __P((struct  vop_fsync_args *));
73 static int      spec_bmap __P((struct vop_bmap_args *));
74 static int      spec_advlock __P((struct vop_advlock_args *));  
75 static int      spec_getpages __P((struct vop_getpages_args *));
76
77 struct vnode *speclisth[SPECHSZ];
78 vop_t **spec_vnodeop_p;
79 static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
80         { &vop_default_desc,            (vop_t *) vop_defaultop },
81         { &vop_access_desc,             (vop_t *) vop_ebadf },
82         { &vop_advlock_desc,            (vop_t *) spec_advlock },
83         { &vop_bmap_desc,               (vop_t *) spec_bmap },
84         { &vop_close_desc,              (vop_t *) spec_close },
85         { &vop_create_desc,             (vop_t *) spec_badop },
86         { &vop_fsync_desc,              (vop_t *) spec_fsync },
87         { &vop_getattr_desc,            (vop_t *) spec_getattr },
88         { &vop_getpages_desc,           (vop_t *) spec_getpages },
89         { &vop_inactive_desc,           (vop_t *) spec_inactive },
90         { &vop_ioctl_desc,              (vop_t *) spec_ioctl },
91         { &vop_lease_desc,              (vop_t *) vop_null },
92         { &vop_link_desc,               (vop_t *) spec_badop },
93         { &vop_lookup_desc,             (vop_t *) spec_lookup },
94         { &vop_mkdir_desc,              (vop_t *) spec_badop },
95         { &vop_mknod_desc,              (vop_t *) spec_badop },
96         { &vop_open_desc,               (vop_t *) spec_open },
97         { &vop_pathconf_desc,           (vop_t *) vop_stdpathconf },
98         { &vop_poll_desc,               (vop_t *) spec_poll },
99         { &vop_print_desc,              (vop_t *) spec_print },
100         { &vop_read_desc,               (vop_t *) spec_read },
101         { &vop_readdir_desc,            (vop_t *) spec_badop },
102         { &vop_readlink_desc,           (vop_t *) spec_badop },
103         { &vop_reallocblks_desc,        (vop_t *) spec_badop },
104         { &vop_reclaim_desc,            (vop_t *) vop_null },
105         { &vop_remove_desc,             (vop_t *) spec_badop },
106         { &vop_rename_desc,             (vop_t *) spec_badop },
107         { &vop_rmdir_desc,              (vop_t *) spec_badop },
108         { &vop_setattr_desc,            (vop_t *) vop_ebadf },
109         { &vop_strategy_desc,           (vop_t *) spec_strategy },
110         { &vop_symlink_desc,            (vop_t *) spec_badop },
111         { &vop_write_desc,              (vop_t *) spec_write },
112         { NULL, NULL }
113 };
114 static struct vnodeopv_desc spec_vnodeop_opv_desc =
115         { &spec_vnodeop_p, spec_vnodeop_entries };
116
117 VNODEOP_SET(spec_vnodeop_opv_desc);
118
119
120 int
121 spec_vnoperate(ap)
122         struct vop_generic_args /* {
123                 struct vnodeop_desc *a_desc;
124                 <other random data follows, presumably>
125         } */ *ap;
126 {
127         return (VOCALL(spec_vnodeop_p, ap->a_desc->vdesc_offset, ap));
128 }
129
130 static void spec_getpages_iodone __P((struct buf *bp));
131
132 /*
133  * Trivial lookup routine that always fails.
134  */
135 static int
136 spec_lookup(ap)
137         struct vop_lookup_args /* {
138                 struct vnode *a_dvp;
139                 struct vnode **a_vpp;
140                 struct componentname *a_cnp;
141         } */ *ap;
142 {
143
144         *ap->a_vpp = NULL;
145         return (ENOTDIR);
146 }
147
148 /*
149  * Open a special file.
150  */
151 /* ARGSUSED */
152 static int
153 spec_open(ap)
154         struct vop_open_args /* {
155                 struct vnode *a_vp;
156                 int  a_mode;
157                 struct ucred *a_cred;
158                 struct proc *a_p;
159         } */ *ap;
160 {
161         struct proc *p = ap->a_p;
162         struct vnode *bvp, *vp = ap->a_vp;
163         dev_t bdev, dev = (dev_t)vp->v_rdev;
164         int maj = major(dev);
165         int error;
166
167         /*
168          * Don't allow open if fs is mounted -nodev.
169          */
170         if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
171                 return (ENXIO);
172
173         switch (vp->v_type) {
174
175         case VCHR:
176                 if ((u_int)maj >= nchrdev)
177                         return (ENXIO);
178                 if ( (cdevsw[maj] == NULL) || (cdevsw[maj]->d_open == NULL))
179                         return ENXIO;
180                 if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
181                         /*
182                          * When running in very secure mode, do not allow
183                          * opens for writing of any disk character devices.
184                          */
185                         if (securelevel >= 2
186                             && cdevsw[maj]->d_bdev
187                             && (cdevsw[maj]->d_bdev->d_flags & D_TYPEMASK) == 
188                             D_DISK)
189                                 return (EPERM);
190                         /*
191                          * When running in secure mode, do not allow opens
192                          * for writing of /dev/mem, /dev/kmem, or character
193                          * devices whose corresponding block devices are
194                          * currently mounted.
195                          */
196                         if (securelevel >= 1) {
197                                 if ((bdev = chrtoblk(dev)) != NODEV &&
198                                     vfinddev(bdev, VBLK, &bvp) &&
199                                     bvp->v_usecount > 0 &&
200                                     (error = vfs_mountedon(bvp)))
201                                         return (error);
202                                 if (iskmemdev(dev))
203                                         return (EPERM);
204                         }
205                 }
206 #if 0
207                 /*
208                  * Lite2 stuff.  We will almost certainly do this
209                  * differently with devfs.  The only use of this flag
210                  * is in dead_read to make ttys return EOF instead of
211                  * EIO when they are dead.  Pre-lite2 FreeBSD returns
212                  * EOF for all character devices.
213                  */
214                 if (cdevsw[maj]->d_type == D_TTY)
215                         vp->v_flag |= VISTTY;
216 #endif
217                 VOP_UNLOCK(vp, 0, p);
218                 error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, p);
219                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
220                 return (error);
221
222         case VBLK:
223                 if ((u_int)maj >= nblkdev)
224                         return (ENXIO);
225                 if ( (bdevsw[maj] == NULL) || (bdevsw[maj]->d_open == NULL))
226                         return ENXIO;
227                 /*
228                  * When running in very secure mode, do not allow
229                  * opens for writing of any disk block devices.
230                  */
231                 if (securelevel >= 2 && ap->a_cred != FSCRED &&
232                     (ap->a_mode & FWRITE) &&
233                     (bdevsw[maj]->d_flags & D_TYPEMASK) == D_DISK)
234                         return (EPERM);
235
236                 /*
237                  * Do not allow opens of block devices that are
238                  * currently mounted.
239                  */
240                 error = vfs_mountedon(vp);
241                 if (error)
242                         return (error);
243                 return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, p));
244         }
245         return (0);
246 }
247
248 /*
249  * Vnode op for read
250  */
251 /* ARGSUSED */
252 static int
253 spec_read(ap)
254         struct vop_read_args /* {
255                 struct vnode *a_vp;
256                 struct uio *a_uio;
257                 int  a_ioflag;
258                 struct ucred *a_cred;
259         } */ *ap;
260 {
261         register struct vnode *vp = ap->a_vp;
262         register struct uio *uio = ap->a_uio;
263         struct proc *p = uio->uio_procp;
264         struct buf *bp;
265         daddr_t bn, nextbn;
266         long bsize, bscale;
267         struct partinfo dpart;
268         int n, on, majordev;
269         d_ioctl_t *ioctl;
270         int error = 0;
271         dev_t dev;
272
273 #ifdef DIAGNOSTIC
274         if (uio->uio_rw != UIO_READ)
275                 panic("spec_read mode");
276         if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
277                 panic("spec_read proc");
278 #endif
279         if (uio->uio_resid == 0)
280                 return (0);
281
282         switch (vp->v_type) {
283
284         case VCHR:
285                 VOP_UNLOCK(vp, 0, p);
286                 error = (*cdevsw[major(vp->v_rdev)]->d_read)
287                         (vp->v_rdev, uio, ap->a_ioflag);
288                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
289                 return (error);
290
291         case VBLK:
292                 if (uio->uio_offset < 0)
293                         return (EINVAL);
294                 bsize = BLKDEV_IOSIZE;
295                 dev = vp->v_rdev;
296                 if ((majordev = major(dev)) < nblkdev &&
297                     (ioctl = bdevsw[majordev]->d_ioctl) != NULL &&
298                     (*ioctl)(dev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0 &&
299                     dpart.part->p_fstype == FS_BSDFFS &&
300                     dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
301                         bsize = dpart.part->p_frag * dpart.part->p_fsize;
302                 bscale = btodb(bsize);
303                 do {
304                         bn = btodb(uio->uio_offset) & ~(bscale - 1);
305                         on = uio->uio_offset % bsize;
306                         n = min((unsigned)(bsize - on), uio->uio_resid);
307                         if (vp->v_lastr + bscale == bn) {
308                                 nextbn = bn + bscale;
309                                 error = breadn(vp, bn, (int)bsize, &nextbn,
310                                         (int *)&bsize, 1, NOCRED, &bp);
311                         } else
312                                 error = bread(vp, bn, (int)bsize, NOCRED, &bp);
313                         vp->v_lastr = bn;
314                         n = min(n, bsize - bp->b_resid);
315                         if (error) {
316                                 brelse(bp);
317                                 return (error);
318                         }
319                         error = uiomove((char *)bp->b_data + on, n, uio);
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 */
334 static int
335 spec_write(ap)
336         struct vop_write_args /* {
337                 struct vnode *a_vp;
338                 struct uio *a_uio;
339                 int  a_ioflag;
340                 struct ucred *a_cred;
341         } */ *ap;
342 {
343         register struct vnode *vp = ap->a_vp;
344         register struct uio *uio = ap->a_uio;
345         struct proc *p = uio->uio_procp;
346         struct buf *bp;
347         daddr_t bn;
348         int bsize, blkmask;
349         struct partinfo dpart;
350         register int n, on;
351         int error = 0;
352
353 #ifdef DIAGNOSTIC
354         if (uio->uio_rw != UIO_WRITE)
355                 panic("spec_write mode");
356         if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
357                 panic("spec_write proc");
358 #endif
359
360         switch (vp->v_type) {
361
362         case VCHR:
363                 VOP_UNLOCK(vp, 0, p);
364                 error = (*cdevsw[major(vp->v_rdev)]->d_write)
365                         (vp->v_rdev, uio, ap->a_ioflag);
366                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
367                 return (error);
368
369         case VBLK:
370                 if (uio->uio_resid == 0)
371                         return (0);
372                 if (uio->uio_offset < 0)
373                         return (EINVAL);
374                 bsize = BLKDEV_IOSIZE;
375                 if ((*bdevsw[major(vp->v_rdev)]->d_ioctl)(vp->v_rdev, DIOCGPART,
376                     (caddr_t)&dpart, FREAD, p) == 0) {
377                         if (dpart.part->p_fstype == FS_BSDFFS &&
378                             dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
379                                 bsize = dpart.part->p_frag *
380                                     dpart.part->p_fsize;
381                 }
382                 blkmask = btodb(bsize) - 1;
383                 do {
384                         bn = btodb(uio->uio_offset) & ~blkmask;
385                         on = uio->uio_offset % bsize;
386                         n = min((unsigned)(bsize - on), uio->uio_resid);
387                         if (n == bsize)
388                                 bp = getblk(vp, bn, bsize, 0, 0);
389                         else
390                                 error = bread(vp, bn, bsize, NOCRED, &bp);
391                         n = min(n, bsize - bp->b_resid);
392                         if (error) {
393                                 brelse(bp);
394                                 return (error);
395                         }
396                         error = uiomove((char *)bp->b_data + on, n, uio);
397                         if (n + on == bsize)
398                                 bawrite(bp);
399                         else
400                                 bdwrite(bp);
401                 } while (error == 0 && uio->uio_resid > 0 && n != 0);
402                 return (error);
403
404         default:
405                 panic("spec_write type");
406         }
407         /* NOTREACHED */
408 }
409
410 /*
411  * Device ioctl operation.
412  */
413 /* ARGSUSED */
414 static int
415 spec_ioctl(ap)
416         struct vop_ioctl_args /* {
417                 struct vnode *a_vp;
418                 int  a_command;
419                 caddr_t  a_data;
420                 int  a_fflag;
421                 struct ucred *a_cred;
422                 struct proc *a_p;
423         } */ *ap;
424 {
425         dev_t dev = ap->a_vp->v_rdev;
426
427         switch (ap->a_vp->v_type) {
428
429         case VCHR:
430                 return ((*cdevsw[major(dev)]->d_ioctl)(dev, ap->a_command, ap->a_data,
431                     ap->a_fflag, ap->a_p));
432
433         case VBLK:
434                 if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
435                         if ((bdevsw[major(dev)]->d_flags & D_TYPEMASK) ==
436                             D_TAPE)
437                                 return (0);
438                         else
439                                 return (1);
440                 return ((*bdevsw[major(dev)]->d_ioctl)(dev, ap->a_command, ap->a_data,
441                    ap->a_fflag, ap->a_p));
442
443         default:
444                 panic("spec_ioctl");
445                 /* NOTREACHED */
446         }
447 }
448
449 /* ARGSUSED */
450 static int
451 spec_poll(ap)
452         struct vop_poll_args /* {
453                 struct vnode *a_vp;
454                 int  a_events;
455                 struct ucred *a_cred;
456                 struct proc *a_p;
457         } */ *ap;
458 {
459         register dev_t dev;
460
461         switch (ap->a_vp->v_type) {
462
463         case VCHR:
464                 dev = ap->a_vp->v_rdev;
465                 return (*cdevsw[major(dev)]->d_poll)(dev, ap->a_events, ap->a_p);
466         default:
467                 return (vop_defaultop((struct vop_generic_args *)ap));
468
469         }
470 }
471 /*
472  * Synch buffers associated with a block device
473  */
474 /* ARGSUSED */
475 static int
476 spec_fsync(ap)
477         struct vop_fsync_args /* {
478                 struct vnode *a_vp;
479                 struct ucred *a_cred;
480                 int  a_waitfor;
481                 struct proc *a_p;
482         } */ *ap;
483 {
484         register struct vnode *vp = ap->a_vp;
485         register struct buf *bp;
486         struct buf *nbp;
487         int s;
488
489         if (vp->v_type == VCHR)
490                 return (0);
491         /*
492          * Flush all dirty buffers associated with a block device.
493          */
494 loop:
495         s = splbio();
496         for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
497                 nbp = bp->b_vnbufs.le_next;
498                 if ((bp->b_flags & B_BUSY))
499                         continue;
500                 if ((bp->b_flags & B_DELWRI) == 0)
501                         panic("spec_fsync: not dirty");
502                 if ((vp->v_flag & VOBJBUF) && (bp->b_flags & B_CLUSTEROK)) {
503                         vfs_bio_awrite(bp);
504                         splx(s);
505                 } else {
506                         bremfree(bp);
507                         bp->b_flags |= B_BUSY;
508                         splx(s);
509                         bawrite(bp);
510                 }
511                 goto loop;
512         }
513         if (ap->a_waitfor == MNT_WAIT) {
514                 while (vp->v_numoutput) {
515                         vp->v_flag |= VBWAIT;
516                         (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "spfsyn", 0);
517                 }
518 #ifdef DIAGNOSTIC
519                 if (vp->v_dirtyblkhd.lh_first) {
520                         vprint("spec_fsync: dirty", vp);
521                         splx(s);
522                         goto loop;
523                 }
524 #endif
525         }
526         splx(s);
527         return (0);
528 }
529
530 static int
531 spec_inactive(ap)
532         struct vop_inactive_args /* {
533                 struct vnode *a_vp;
534                 struct proc *a_p;
535         } */ *ap;
536 {
537
538         VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
539         return (0);
540 }
541
542 /*
543  * Just call the device strategy routine
544  */
545 static int
546 spec_strategy(ap)
547         struct vop_strategy_args /* {
548                 struct buf *a_bp;
549         } */ *ap;
550 {
551         struct buf *bp;
552
553         bp = ap->a_bp;
554         if ((LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
555                 (*bioops.io_start)(bp);
556         (*bdevsw[major(bp->b_dev)]->d_strategy)(bp);
557         return (0);
558 }
559
560 /*
561  * This is a noop, simply returning what one has been given.
562  */
563 static int
564 spec_bmap(ap)
565         struct vop_bmap_args /* {
566                 struct vnode *a_vp;
567                 daddr_t  a_bn;
568                 struct vnode **a_vpp;
569                 daddr_t *a_bnp;
570                 int *a_runp;
571                 int *a_runb;
572         } */ *ap;
573 {
574
575         if (ap->a_vpp != NULL)
576                 *ap->a_vpp = ap->a_vp;
577         if (ap->a_bnp != NULL)
578                 *ap->a_bnp = ap->a_bn;
579         if (ap->a_runp != NULL)
580                 *ap->a_runp = 0;
581         if (ap->a_runb != NULL)
582                 *ap->a_runb = 0;
583         return (0);
584 }
585
586 /*
587  * Device close routine
588  */
589 /* ARGSUSED */
590 static int
591 spec_close(ap)
592         struct vop_close_args /* {
593                 struct vnode *a_vp;
594                 int  a_fflag;
595                 struct ucred *a_cred;
596                 struct proc *a_p;
597         } */ *ap;
598 {
599         register struct vnode *vp = ap->a_vp;
600         struct proc *p = ap->a_p;
601         dev_t dev = vp->v_rdev;
602         d_close_t *devclose;
603         int mode, error;
604
605         switch (vp->v_type) {
606
607         case VCHR:
608                 /*
609                  * Hack: a tty device that is a controlling terminal
610                  * has a reference from the session structure.
611                  * We cannot easily tell that a character device is
612                  * a controlling terminal, unless it is the closing
613                  * process' controlling terminal.  In that case,
614                  * if the reference count is 2 (this last descriptor
615                  * plus the session), release the reference from the session.
616                  */
617                 if (vcount(vp) == 2 && ap->a_p &&
618                     (vp->v_flag & VXLOCK) == 0 &&
619                     vp == ap->a_p->p_session->s_ttyvp) {
620                         vrele(vp);
621                         ap->a_p->p_session->s_ttyvp = NULL;
622                 }
623                 /*
624                  * If the vnode is locked, then we are in the midst
625                  * of forcably closing the device, otherwise we only
626                  * close on last reference.
627                  */
628                 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
629                         return (0);
630                 devclose = cdevsw[major(dev)]->d_close;
631                 mode = S_IFCHR;
632                 break;
633
634         case VBLK:
635                 /*
636                  * On last close of a block device (that isn't mounted)
637                  * we must invalidate any in core blocks, so that
638                  * we can, for instance, change floppy disks.
639                  */
640                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);
641                 error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
642                 VOP_UNLOCK(vp, 0, ap->a_p);
643                 if (error)
644                         return (error);
645
646                 /*
647                  * We do not want to really close the device if it
648                  * is still in use unless we are trying to close it
649                  * forcibly. Since every use (buffer, vnode, swap, cmap)
650                  * holds a reference to the vnode, and because we mark
651                  * any other vnodes that alias this device, when the
652                  * sum of the reference counts on all the aliased
653                  * vnodes descends to one, we are on last close.
654                  */
655                 if ((vcount(vp) > 1) && (vp->v_flag & VXLOCK) == 0)
656                         return (0);
657
658                 devclose = bdevsw[major(dev)]->d_close;
659                 mode = S_IFBLK;
660                 break;
661
662         default:
663                 panic("spec_close: not special");
664         }
665
666         return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
667 }
668
669 /*
670  * Print out the contents of a special device vnode.
671  */
672 static int
673 spec_print(ap)
674         struct vop_print_args /* {
675                 struct vnode *a_vp;
676         } */ *ap;
677 {
678
679         printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
680                 minor(ap->a_vp->v_rdev));
681         return (0);
682 }
683
684 /*
685  * Special device advisory byte-level locks.
686  */
687 /* ARGSUSED */
688 static int
689 spec_advlock(ap)
690         struct vop_advlock_args /* {
691                 struct vnode *a_vp;
692                 caddr_t  a_id;
693                 int  a_op;
694                 struct flock *a_fl;
695                 int  a_flags;
696         } */ *ap;
697 {
698
699         return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
700 }
701
702 /*
703  * Special device bad operation
704  */
705 static int
706 spec_badop()
707 {
708
709         panic("spec_badop called");
710         /* NOTREACHED */
711 }
712
713 static void
714 spec_getpages_iodone(bp)
715         struct buf *bp;
716 {
717
718         bp->b_flags |= B_DONE;
719         wakeup(bp);
720 }
721
722 static int
723 spec_getpages(ap)
724         struct vop_getpages_args *ap;
725 {
726         vm_offset_t kva;
727         int error;
728         int i, pcount, size, s;
729         daddr_t blkno;
730         struct buf *bp;
731         vm_page_t m;
732         vm_ooffset_t offset;
733         int toff, nextoff, nread;
734         struct vnode *vp = ap->a_vp;
735         int blksiz;
736         int gotreqpage;
737
738         error = 0;
739         pcount = round_page(ap->a_count) / PAGE_SIZE;
740
741         /*
742          * Calculate the offset of the transfer.
743          */
744         offset = IDX_TO_OFF(ap->a_m[0]->pindex) + ap->a_offset;
745
746         /* XXX sanity check before we go into details. */
747         /* XXX limits should be defined elsewhere. */
748 #define DADDR_T_BIT     32
749 #define OFFSET_MAX      ((1LL << (DADDR_T_BIT + DEV_BSHIFT)) - 1)
750         if (offset < 0 || offset > OFFSET_MAX) {
751                 /* XXX still no %q in kernel. */
752                 printf("spec_getpages: preposterous offset 0x%x%08x\n",
753                        (u_int)((u_quad_t)offset >> 32),
754                        (u_int)(offset & 0xffffffff));
755                 return (VM_PAGER_ERROR);
756         }
757
758         blkno = btodb(offset);
759
760         /*
761          * Round up physical size for real devices, use the
762          * fundamental blocksize of the fs if possible.
763          */
764         if (vp && vp->v_mount) {
765                 if (vp->v_type != VBLK) {
766                         vprint("Non VBLK", vp);
767                 }
768                 blksiz = vp->v_mount->mnt_stat.f_bsize;
769                 if (blksiz < DEV_BSIZE) {
770                         blksiz = DEV_BSIZE;
771                 }
772         }
773         else
774                 blksiz = DEV_BSIZE;
775         size = (ap->a_count + blksiz - 1) & ~(blksiz - 1);
776
777         bp = getpbuf();
778         kva = (vm_offset_t)bp->b_data;
779
780         /*
781          * Map the pages to be read into the kva.
782          */
783         pmap_qenter(kva, ap->a_m, pcount);
784
785         /* Build a minimal buffer header. */
786         bp->b_flags = B_BUSY | B_READ | B_CALL;
787         bp->b_iodone = spec_getpages_iodone;
788
789         /* B_PHYS is not set, but it is nice to fill this in. */
790         bp->b_proc = curproc;
791         bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
792         if (bp->b_rcred != NOCRED)
793                 crhold(bp->b_rcred);
794         if (bp->b_wcred != NOCRED)
795                 crhold(bp->b_wcred);
796         bp->b_blkno = blkno;
797         bp->b_lblkno = blkno;
798         pbgetvp(ap->a_vp, bp);
799         bp->b_bcount = size;
800         bp->b_bufsize = size;
801         bp->b_resid = 0;
802
803         cnt.v_vnodein++;
804         cnt.v_vnodepgsin += pcount;
805
806         /* Do the input. */
807         VOP_STRATEGY(bp);
808
809         s = splbio();
810
811         /* We definitely need to be at splbio here. */
812         while ((bp->b_flags & B_DONE) == 0)
813                 tsleep(bp, PVM, "spread", 0);
814
815         splx(s);
816
817         if ((bp->b_flags & B_ERROR) != 0) {
818                 if (bp->b_error)
819                         error = bp->b_error;
820                 else
821                         error = EIO;
822         }
823
824         nread = size - bp->b_resid;
825
826         if (nread < ap->a_count) {
827                 bzero((caddr_t)kva + nread,
828                         ap->a_count - nread);
829         }
830         pmap_qremove(kva, pcount);
831
832
833         gotreqpage = 0;
834         for (i = 0, toff = 0; i < pcount; i++, toff = nextoff) {
835                 nextoff = toff + PAGE_SIZE;
836                 m = ap->a_m[i];
837
838                 m->flags &= ~PG_ZERO;
839
840                 if (nextoff <= nread) {
841                         m->valid = VM_PAGE_BITS_ALL;
842                         m->dirty = 0;
843                 } else if (toff < nread) {
844                         int nvalid = ((nread + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1);
845                         vm_page_set_validclean(m, 0, nvalid);
846                 } else {
847                         m->valid = 0;
848                         m->dirty = 0;
849                 }
850
851                 if (i != ap->a_reqpage) {
852                         /*
853                          * Just in case someone was asking for this page we
854                          * now tell them that it is ok to use.
855                          */
856                         if (!error || (m->valid == VM_PAGE_BITS_ALL)) {
857                                 if (m->valid) {
858                                         if (m->flags & PG_WANTED) {
859                                                 vm_page_activate(m);
860                                         } else {
861                                                 vm_page_deactivate(m);
862                                         }
863                                         PAGE_WAKEUP(m);
864                                 } else {
865                                         vm_page_free(m);
866                                 }
867                         } else {
868                                 vm_page_free(m);
869                         }
870                 } else if (m->valid) {
871                         gotreqpage = 1;
872                 }
873         }
874         if (!gotreqpage) {
875                 m = ap->a_m[ap->a_reqpage];
876 #ifndef MAX_PERF
877                 printf("spec_getpages: I/O read failure: (error code=%d)\n", error);
878                 printf("               size: %d, resid: %d, a_count: %d, valid: 0x%x\n",
879                                 size, bp->b_resid, ap->a_count, m->valid);
880                 printf("               nread: %d, reqpage: %d, pindex: %d, pcount: %d\n",
881                                 nread, ap->a_reqpage, m->pindex, pcount);
882 #endif
883                 /*
884                  * Free the buffer header back to the swap buffer pool.
885                  */
886                 relpbuf(bp);
887                 return VM_PAGER_ERROR;
888         }
889         /*
890          * Free the buffer header back to the swap buffer pool.
891          */
892         relpbuf(bp);
893         return VM_PAGER_OK;
894 }
895
896 /* ARGSUSED */
897 static int
898 spec_getattr(ap)
899         struct vop_getattr_args /* {
900                 struct vnode *a_vp;
901                 struct vattr *a_vap;
902                 struct ucred *a_cred;
903                 struct proc *a_p;
904         } */ *ap;
905 {
906         register struct vnode *vp = ap->a_vp;
907         register struct vattr *vap = ap->a_vap;
908         struct partinfo dpart;
909
910         bzero(vap, sizeof (*vap));
911
912         if (vp->v_type == VBLK)
913                 vap->va_blocksize = BLKDEV_IOSIZE;
914         else if (vp->v_type == VCHR)
915                 vap->va_blocksize = MAXBSIZE;
916
917         if ((*bdevsw[major(vp->v_rdev)]->d_ioctl)(vp->v_rdev, DIOCGPART,
918             (caddr_t)&dpart, FREAD, ap->a_p) == 0) {
919                 vap->va_bytes = dbtob(dpart.disklab->d_partitions
920                                       [minor(vp->v_rdev)].p_size);
921                 vap->va_size = vap->va_bytes;
922         }
923         return (0);
924 }