1 /* $NetBSD: spec_vnops.c,v 1.126 2009/10/06 04:28:10 elad Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 1989, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * @(#)spec_vnops.c 8.15 (Berkeley) 7/14/95
60 #include <sys/cdefs.h>
61 __KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.126 2009/10/06 04:28:10 elad Exp $");
63 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/kernel.h>
69 #include <sys/mount.h>
70 #include <sys/namei.h>
71 #include <sys/vnode.h>
73 #include <sys/errno.h>
74 #include <sys/ioctl.h>
77 #include <sys/disklabel.h>
78 #include <sys/lockf.h>
80 #include <sys/kauth.h>
81 #include <sys/fstrans.h>
82 #include <sys/module.h>
84 #include <miscfs/genfs/genfs.h>
85 #include <miscfs/specfs/specdev.h>
87 /* symbolic sleep message strings for devices */
88 const char devopn
[] = "devopn";
89 const char devio
[] = "devio";
90 const char devwait
[] = "devwait";
91 const char devin
[] = "devin";
92 const char devout
[] = "devout";
93 const char devioc
[] = "devioc";
94 const char devcls
[] = "devcls";
96 vnode_t
*specfs_hash
[SPECHSZ
];
99 * This vnode operations vector is used for special device nodes
100 * created from whole cloth by the kernel. For the ops vector for
101 * vnodes built from special devices found in a filesystem, see (e.g)
102 * ffs_specop_entries[] in ffs_vnops.c or the equivalent for other
106 int (**spec_vnodeop_p
)(void *);
107 const struct vnodeopv_entry_desc spec_vnodeop_entries
[] = {
108 { &vop_default_desc
, vn_default_error
},
109 { &vop_lookup_desc
, spec_lookup
}, /* lookup */
110 { &vop_create_desc
, spec_create
}, /* create */
111 { &vop_mknod_desc
, spec_mknod
}, /* mknod */
112 { &vop_open_desc
, spec_open
}, /* open */
113 { &vop_close_desc
, spec_close
}, /* close */
114 { &vop_access_desc
, spec_access
}, /* access */
115 { &vop_getattr_desc
, spec_getattr
}, /* getattr */
116 { &vop_setattr_desc
, spec_setattr
}, /* setattr */
117 { &vop_read_desc
, spec_read
}, /* read */
118 { &vop_write_desc
, spec_write
}, /* write */
119 { &vop_fcntl_desc
, spec_fcntl
}, /* fcntl */
120 { &vop_ioctl_desc
, spec_ioctl
}, /* ioctl */
121 { &vop_poll_desc
, spec_poll
}, /* poll */
122 { &vop_kqfilter_desc
, spec_kqfilter
}, /* kqfilter */
123 { &vop_revoke_desc
, spec_revoke
}, /* revoke */
124 { &vop_mmap_desc
, spec_mmap
}, /* mmap */
125 { &vop_fsync_desc
, spec_fsync
}, /* fsync */
126 { &vop_seek_desc
, spec_seek
}, /* seek */
127 { &vop_remove_desc
, spec_remove
}, /* remove */
128 { &vop_link_desc
, spec_link
}, /* link */
129 { &vop_rename_desc
, spec_rename
}, /* rename */
130 { &vop_mkdir_desc
, spec_mkdir
}, /* mkdir */
131 { &vop_rmdir_desc
, spec_rmdir
}, /* rmdir */
132 { &vop_symlink_desc
, spec_symlink
}, /* symlink */
133 { &vop_readdir_desc
, spec_readdir
}, /* readdir */
134 { &vop_readlink_desc
, spec_readlink
}, /* readlink */
135 { &vop_abortop_desc
, spec_abortop
}, /* abortop */
136 { &vop_inactive_desc
, spec_inactive
}, /* inactive */
137 { &vop_reclaim_desc
, spec_reclaim
}, /* reclaim */
138 { &vop_lock_desc
, spec_lock
}, /* lock */
139 { &vop_unlock_desc
, spec_unlock
}, /* unlock */
140 { &vop_bmap_desc
, spec_bmap
}, /* bmap */
141 { &vop_strategy_desc
, spec_strategy
}, /* strategy */
142 { &vop_print_desc
, spec_print
}, /* print */
143 { &vop_islocked_desc
, spec_islocked
}, /* islocked */
144 { &vop_pathconf_desc
, spec_pathconf
}, /* pathconf */
145 { &vop_advlock_desc
, spec_advlock
}, /* advlock */
146 { &vop_bwrite_desc
, spec_bwrite
}, /* bwrite */
147 { &vop_getpages_desc
, spec_getpages
}, /* getpages */
148 { &vop_putpages_desc
, spec_putpages
}, /* putpages */
151 const struct vnodeopv_desc spec_vnodeop_opv_desc
=
152 { &spec_vnodeop_p
, spec_vnodeop_entries
};
154 static kauth_listener_t rawio_listener
;
156 /* Returns true if vnode is /dev/mem or /dev/kmem. */
158 iskmemvp(struct vnode
*vp
)
160 return ((vp
->v_type
== VCHR
) && iskmemdev(vp
->v_rdev
));
164 * Returns true if dev is /dev/mem or /dev/kmem.
169 /* mem_no is emitted by config(8) to generated devsw.c */
170 extern const int mem_no
;
172 /* minor 14 is /dev/io on i386 with COMPAT_10 */
173 return (major(dev
) == mem_no
&& (minor(dev
) < 2 || minor(dev
) == 14));
177 rawio_listener_cb(kauth_cred_t cred
, kauth_action_t action
, void *cookie
,
178 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
182 result
= KAUTH_RESULT_DEFER
;
184 if ((action
!= KAUTH_DEVICE_RAWIO_SPEC
) &&
185 (action
!= KAUTH_DEVICE_RAWIO_PASSTHRU
))
188 /* Access is mandated by permissions. */
189 result
= KAUTH_RESULT_ALLOW
;
198 rawio_listener
= kauth_listen_scope(KAUTH_SCOPE_DEVICE
,
199 rawio_listener_cb
, NULL
);
203 * Initialize a vnode that represents a device.
206 spec_node_init(vnode_t
*vp
, dev_t rdev
)
213 KASSERT(vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
);
214 KASSERT(vp
->v_specnode
== NULL
);
217 * Search the hash table for this device. If known, add a
218 * reference to the device structure. If not known, create
219 * a new entry to represent the device. In all cases add
220 * the vnode to the hash table.
222 sn
= kmem_alloc(sizeof(*sn
), KM_SLEEP
);
225 panic("spec_node_init: unable to allocate memory");
227 sd
= kmem_alloc(sizeof(*sd
), KM_SLEEP
);
230 panic("spec_node_init: unable to allocate memory");
232 mutex_enter(&device_lock
);
233 vpp
= &specfs_hash
[SPECHASH(rdev
)];
234 for (vp2
= *vpp
; vp2
!= NULL
; vp2
= vp2
->v_specnext
) {
235 KASSERT(vp2
->v_specnode
!= NULL
);
236 if (rdev
== vp2
->v_rdev
&& vp
->v_type
== vp2
->v_type
) {
241 /* No existing record, create a new one. */
243 sd
->sd_mountpoint
= NULL
;
247 sd
->sd_bdevvp
= NULL
;
251 /* Use the existing record. */
252 sn
->sn_dev
= vp2
->v_specnode
->sn_dev
;
253 sn
->sn_dev
->sd_refcnt
++;
255 /* Insert vnode into the hash chain. */
260 vp
->v_specnext
= *vpp
;
262 mutex_exit(&device_lock
);
264 /* Free the record we allocated if unused. */
266 kmem_free(sd
, sizeof(*sd
));
271 * A vnode representing a special device is going away. Close
272 * the device if the vnode holds it open.
275 spec_node_revoke(vnode_t
*vp
)
283 KASSERT(vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
);
284 KASSERT(vp
->v_specnode
!= NULL
);
285 KASSERT((vp
->v_iflag
& VI_XLOCK
) != 0);
286 KASSERT(sn
->sn_gone
== false);
288 mutex_enter(&device_lock
);
289 KASSERT(sn
->sn_opencnt
<= sd
->sd_opencnt
);
290 if (sn
->sn_opencnt
!= 0) {
291 sd
->sd_opencnt
-= (sn
->sn_opencnt
- 1);
294 mutex_exit(&device_lock
);
296 VOP_CLOSE(vp
, FNONBLOCK
, NOCRED
);
298 mutex_enter(&device_lock
);
299 KASSERT(sn
->sn_opencnt
== 0);
301 mutex_exit(&device_lock
);
305 * A vnode representing a special device is being recycled.
306 * Destroy the specfs component.
309 spec_node_destroy(vnode_t
*vp
)
319 KASSERT(vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
);
320 KASSERT(vp
->v_specnode
!= NULL
);
321 KASSERT(sn
->sn_opencnt
== 0);
323 mutex_enter(&device_lock
);
324 /* Remove from the hash and destroy the node. */
325 vpp
= &specfs_hash
[SPECHASH(vp
->v_rdev
)];
326 for (vp2
= *vpp
;; vp2
= vp2
->v_specnext
) {
328 panic("spec_node_destroy: corrupt hash");
332 *vpp
= vp
->v_specnext
;
335 if (vp2
->v_specnext
== vp
) {
336 vp2
->v_specnext
= vp
->v_specnext
;
341 vp
->v_specnode
= NULL
;
342 refcnt
= sd
->sd_refcnt
--;
344 mutex_exit(&device_lock
);
346 /* If the device is no longer in use, destroy our record. */
348 KASSERT(sd
->sd_opencnt
== 0);
349 KASSERT(sd
->sd_bdevvp
== NULL
);
350 kmem_free(sd
, sizeof(*sd
));
352 kmem_free(sn
, sizeof(*sn
));
356 * Trivial lookup routine that always fails.
361 struct vop_lookup_args
/* {
363 struct vnode **a_vpp;
364 struct componentname *a_cnp;
372 * Open a special file.
378 struct vop_open_args
/* {
388 enum kauth_device_req req
;
404 * Don't allow open if fs is mounted -nodev.
406 if (vp
->v_mount
&& (vp
->v_mount
->mnt_flag
& MNT_NODEV
))
409 switch (ap
->a_mode
& (FREAD
| FWRITE
)) {
411 req
= KAUTH_REQ_DEVICE_RAWIO_SPEC_RW
;
414 req
= KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE
;
417 req
= KAUTH_REQ_DEVICE_RAWIO_SPEC_READ
;
421 switch (vp
->v_type
) {
423 error
= kauth_authorize_device_spec(ap
->a_cred
, req
, vp
);
428 * Character devices can accept opens from multiple
431 mutex_enter(&device_lock
);
433 mutex_exit(&device_lock
);
438 mutex_exit(&device_lock
);
439 if (cdev_type(dev
) == D_TTY
)
440 vp
->v_vflag
|= VV_ISTTY
;
443 const struct cdevsw
*cdev
;
446 error
= cdev_open(dev
, ap
->a_mode
, S_IFCHR
, l
);
450 /* Check if we already have a valid driver */
451 mutex_enter(&device_lock
);
452 cdev
= cdevsw_lookup(dev
);
453 mutex_exit(&device_lock
);
457 /* Get device name from devsw_conv array */
458 if ((name
= cdevsw_getname(major(dev
))) == NULL
)
461 /* Try to autoload device module */
462 mutex_enter(&module_lock
);
463 (void) module_autoload(name
, MODULE_CLASS_DRIVER
);
464 mutex_exit(&module_lock
);
465 } while (gen
!= module_gen
);
467 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
471 error
= kauth_authorize_device_spec(ap
->a_cred
, req
, vp
);
476 * For block devices, permit only one open. The buffer
477 * cache cannot remain self-consistent with multiple
478 * vnodes holding a block device open.
480 mutex_enter(&device_lock
);
482 mutex_exit(&device_lock
);
485 if (sd
->sd_opencnt
!= 0) {
486 mutex_exit(&device_lock
);
492 mutex_exit(&device_lock
);
494 const struct bdevsw
*bdev
;
497 error
= bdev_open(dev
, ap
->a_mode
, S_IFBLK
, l
);
501 /* Check if we already have a valid driver */
502 mutex_enter(&device_lock
);
503 bdev
= bdevsw_lookup(dev
);
504 mutex_exit(&device_lock
);
508 /* Get device name from devsw_conv array */
509 if ((name
= bdevsw_getname(major(dev
))) == NULL
)
514 /* Try to autoload device module */
515 mutex_enter(&module_lock
);
516 (void) module_autoload(name
, MODULE_CLASS_DRIVER
);
517 mutex_exit(&module_lock
);
519 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
520 } while (gen
!= module_gen
);
535 mutex_enter(&device_lock
);
539 } else if (error
!= 0) {
542 if (vp
->v_type
== VBLK
)
543 sd
->sd_bdevvp
= NULL
;
546 mutex_exit(&device_lock
);
548 if (cdev_type(dev
) != D_DISK
|| error
!= 0)
551 if (vp
->v_type
== VCHR
)
552 error
= cdev_ioctl(vp
->v_rdev
, DIOCGPART
, &pi
, FREAD
, curlwp
);
554 error
= bdev_ioctl(vp
->v_rdev
, DIOCGPART
, &pi
, FREAD
, curlwp
);
557 (voff_t
)pi
.disklab
->d_secsize
* pi
.part
->p_size
);
568 struct vop_read_args
/* {
574 struct vnode
*vp
= ap
->a_vp
;
575 struct uio
*uio
= ap
->a_uio
;
576 struct lwp
*l
= curlwp
;
580 struct partinfo dpart
;
585 if (uio
->uio_rw
!= UIO_READ
)
586 panic("spec_read mode");
587 if (&uio
->uio_vmspace
->vm_map
!= kernel_map
&&
588 uio
->uio_vmspace
!= curproc
->p_vmspace
)
589 panic("spec_read proc");
591 if (uio
->uio_resid
== 0)
594 switch (vp
->v_type
) {
598 error
= cdev_read(vp
->v_rdev
, uio
, ap
->a_ioflag
);
599 vn_lock(vp
, LK_SHARED
| LK_RETRY
);
603 KASSERT(vp
== vp
->v_specnode
->sn_dev
->sd_bdevvp
);
604 if (uio
->uio_offset
< 0)
606 bsize
= BLKDEV_IOSIZE
;
607 if (bdev_ioctl(vp
->v_rdev
, DIOCGPART
, &dpart
, FREAD
, l
) == 0) {
608 if (dpart
.part
->p_fstype
== FS_BSDFFS
&&
609 dpart
.part
->p_frag
!= 0 && dpart
.part
->p_fsize
!= 0)
610 bsize
= dpart
.part
->p_frag
*
613 bscale
= bsize
>> DEV_BSHIFT
;
615 bn
= (uio
->uio_offset
>> DEV_BSHIFT
) &~ (bscale
- 1);
616 on
= uio
->uio_offset
% bsize
;
617 n
= min((unsigned)(bsize
- on
), uio
->uio_resid
);
618 error
= bread(vp
, bn
, bsize
, NOCRED
, 0, &bp
);
619 n
= min(n
, bsize
- bp
->b_resid
);
624 error
= uiomove((char *)bp
->b_data
+ on
, n
, uio
);
626 } while (error
== 0 && uio
->uio_resid
> 0 && n
!= 0);
630 panic("spec_read type");
642 struct vop_write_args
/* {
648 struct vnode
*vp
= ap
->a_vp
;
649 struct uio
*uio
= ap
->a_uio
;
650 struct lwp
*l
= curlwp
;
654 struct partinfo dpart
;
659 if (uio
->uio_rw
!= UIO_WRITE
)
660 panic("spec_write mode");
661 if (&uio
->uio_vmspace
->vm_map
!= kernel_map
&&
662 uio
->uio_vmspace
!= curproc
->p_vmspace
)
663 panic("spec_write proc");
666 switch (vp
->v_type
) {
670 error
= cdev_write(vp
->v_rdev
, uio
, ap
->a_ioflag
);
671 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
675 KASSERT(vp
== vp
->v_specnode
->sn_dev
->sd_bdevvp
);
676 if (uio
->uio_resid
== 0)
678 if (uio
->uio_offset
< 0)
680 bsize
= BLKDEV_IOSIZE
;
681 if (bdev_ioctl(vp
->v_rdev
, DIOCGPART
, &dpart
, FREAD
, l
) == 0) {
682 if (dpart
.part
->p_fstype
== FS_BSDFFS
&&
683 dpart
.part
->p_frag
!= 0 && dpart
.part
->p_fsize
!= 0)
684 bsize
= dpart
.part
->p_frag
*
687 bscale
= bsize
>> DEV_BSHIFT
;
689 bn
= (uio
->uio_offset
>> DEV_BSHIFT
) &~ (bscale
- 1);
690 on
= uio
->uio_offset
% bsize
;
691 n
= min((unsigned)(bsize
- on
), uio
->uio_resid
);
693 bp
= getblk(vp
, bn
, bsize
, 0, 0);
695 error
= bread(vp
, bn
, bsize
, NOCRED
,
701 n
= min(n
, bsize
- bp
->b_resid
);
702 error
= uiomove((char *)bp
->b_data
+ on
, n
, uio
);
712 } while (error
== 0 && uio
->uio_resid
> 0 && n
!= 0);
716 panic("spec_write type");
722 * Device ioctl operation.
728 struct vop_ioctl_args
/* {
739 * Extract all the info we need from the vnode, taking care to
740 * avoid a race with VOP_REVOKE().
745 mutex_enter(&vp
->v_interlock
);
746 if ((vp
->v_iflag
& VI_XLOCK
) == 0 && vp
->v_specnode
) {
749 mutex_exit(&vp
->v_interlock
);
754 switch (vp
->v_type
) {
757 return cdev_ioctl(dev
, ap
->a_command
, ap
->a_data
,
758 ap
->a_fflag
, curlwp
);
761 KASSERT(vp
== vp
->v_specnode
->sn_dev
->sd_bdevvp
);
762 return bdev_ioctl(dev
, ap
->a_command
, ap
->a_data
,
763 ap
->a_fflag
, curlwp
);
775 struct vop_poll_args
/* {
783 * Extract all the info we need from the vnode, taking care to
784 * avoid a race with VOP_REVOKE().
789 mutex_enter(&vp
->v_interlock
);
790 if ((vp
->v_iflag
& VI_XLOCK
) == 0 && vp
->v_specnode
) {
793 mutex_exit(&vp
->v_interlock
);
798 switch (vp
->v_type
) {
801 return cdev_poll(dev
, ap
->a_events
, curlwp
);
804 return (genfs_poll(v
));
810 spec_kqfilter(void *v
)
812 struct vop_kqfilter_args
/* {
818 switch (ap
->a_vp
->v_type
) {
821 dev
= ap
->a_vp
->v_rdev
;
822 return cdev_kqfilter(dev
, ap
->a_kn
);
825 * Block devices don't support kqfilter, and refuse it
826 * for any other files (like those vflush()ed) too.
833 * Allow mapping of only D_DISK. This is called only for VBLK.
838 struct vop_mmap_args
/* {
843 struct vnode
*vp
= ap
->a_vp
;
845 KASSERT(vp
->v_type
== VBLK
);
846 if (bdev_type(vp
->v_rdev
) != D_DISK
)
853 * Synch buffers associated with a block device
859 struct vop_fsync_args
/* {
866 struct vnode
*vp
= ap
->a_vp
;
870 if (vp
->v_type
== VBLK
) {
871 if ((mp
= vp
->v_specmountpoint
) != NULL
) {
872 error
= VFS_FSYNC(mp
, vp
, ap
->a_flags
| FSYNC_VFS
);
873 if (error
!= EOPNOTSUPP
)
876 vflushbuf(vp
, (ap
->a_flags
& FSYNC_WAIT
) != 0);
882 * Just call the device strategy routine
885 spec_strategy(void *v
)
887 struct vop_strategy_args
/* {
891 struct vnode
*vp
= ap
->a_vp
;
892 struct buf
*bp
= ap
->a_bp
;
895 KASSERT(vp
== vp
->v_specnode
->sn_dev
->sd_bdevvp
);
898 bp
->b_dev
= vp
->v_rdev
;
900 if (!(bp
->b_flags
& B_READ
))
901 error
= fscow_run(bp
, false);
915 spec_inactive(void *v
)
917 struct vop_inactive_args
/* {
922 VOP_UNLOCK(ap
->a_vp
, 0);
927 * This is a noop, simply returning what one has been given.
932 struct vop_bmap_args
/* {
935 struct vnode **a_vpp;
940 if (ap
->a_vpp
!= NULL
)
941 *ap
->a_vpp
= ap
->a_vp
;
942 if (ap
->a_bnp
!= NULL
)
943 *ap
->a_bnp
= ap
->a_bn
;
944 if (ap
->a_runp
!= NULL
)
945 *ap
->a_runp
= (MAXBSIZE
>> DEV_BSHIFT
) - 1;
950 * Device close routine
956 struct vop_close_args
/* {
961 struct vnode
*vp
= ap
->a_vp
;
962 struct session
*sess
;
963 dev_t dev
= vp
->v_rdev
;
964 int mode
, error
, flags
, flags1
, count
;
972 switch (vp
->v_type
) {
976 * Hack: a tty device that is a controlling terminal
977 * has a reference from the session structure. We
978 * cannot easily tell that a character device is a
979 * controlling terminal, unless it is the closing
980 * process' controlling terminal. In that case, if the
981 * open count is 1 release the reference from the
982 * session. Also, remove the link from the tty back to
983 * the session and pgrp.
987 mutex_enter(proc_lock
);
988 sess
= curlwp
->l_proc
->p_session
;
989 if (sn
->sn_opencnt
== 1 && vp
== sess
->s_ttyvp
) {
990 mutex_spin_enter(&tty_lock
);
991 sess
->s_ttyvp
= NULL
;
992 if (sess
->s_ttyp
->t_session
!= NULL
) {
993 sess
->s_ttyp
->t_pgrp
= NULL
;
994 sess
->s_ttyp
->t_session
= NULL
;
995 mutex_spin_exit(&tty_lock
);
996 /* Releases proc_lock. */
999 mutex_spin_exit(&tty_lock
);
1000 if (sess
->s_ttyp
->t_pgrp
!= NULL
)
1001 panic("spec_close: spurious pgrp ref");
1002 mutex_exit(proc_lock
);
1006 mutex_exit(proc_lock
);
1009 * If the vnode is locked, then we are in the midst
1010 * of forcably closing the device, otherwise we only
1011 * close on last reference.
1017 KASSERT(vp
== vp
->v_specnode
->sn_dev
->sd_bdevvp
);
1019 * On last close of a block device (that isn't mounted)
1020 * we must invalidate any in core blocks, so that
1021 * we can, for instance, change floppy disks.
1023 error
= vinvalbuf(vp
, V_SAVE
, ap
->a_cred
, curlwp
, 0, 0);
1027 * We do not want to really close the device if it
1028 * is still in use unless we are trying to close it
1029 * forcibly. Since every use (buffer, vnode, swap, cmap)
1030 * holds a reference to the vnode, and because we mark
1031 * any other vnodes that alias this device, when the
1032 * sum of the reference counts on all the aliased
1033 * vnodes descends to one, we are on last close.
1039 panic("spec_close: not special");
1042 mutex_enter(&device_lock
);
1044 count
= --sd
->sd_opencnt
;
1045 if (vp
->v_type
== VBLK
)
1046 sd
->sd_bdevvp
= NULL
;
1047 mutex_exit(&device_lock
);
1052 flags1
= ap
->a_fflag
;
1055 * if VI_XLOCK is set, then we're going away soon, so make this
1056 * non-blocking. Also ensures that we won't wedge in vn_lock below.
1058 if (flags
& VI_XLOCK
)
1059 flags1
|= FNONBLOCK
;
1062 * If we're able to block, release the vnode lock & reacquire. We
1063 * might end up sleeping for someone else who wants our queues. They
1064 * won't get them if we hold the vnode locked. Also, if VI_XLOCK is
1065 * set, don't release the lock as we won't be able to regain it.
1067 if (!(flags1
& FNONBLOCK
))
1070 if (vp
->v_type
== VBLK
)
1071 error
= bdev_close(dev
, flags1
, mode
, curlwp
);
1073 error
= cdev_close(dev
, flags1
, mode
, curlwp
);
1075 if (!(flags1
& FNONBLOCK
))
1076 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
1082 * Print out the contents of a special device vnode.
1087 struct vop_print_args
/* {
1091 printf("dev %llu, %llu\n", (unsigned long long)major(ap
->a_vp
->v_rdev
),
1092 (unsigned long long)minor(ap
->a_vp
->v_rdev
));
1097 * Return POSIX pathconf information applicable to special devices.
1100 spec_pathconf(void *v
)
1102 struct vop_pathconf_args
/* {
1105 register_t *a_retval;
1108 switch (ap
->a_name
) {
1110 *ap
->a_retval
= LINK_MAX
;
1113 *ap
->a_retval
= MAX_CANON
;
1116 *ap
->a_retval
= MAX_INPUT
;
1119 *ap
->a_retval
= PIPE_BUF
;
1121 case _PC_CHOWN_RESTRICTED
:
1125 *ap
->a_retval
= _POSIX_VDISABLE
;
1137 * Advisory record locking support.
1140 spec_advlock(void *v
)
1142 struct vop_advlock_args
/* {
1149 struct vnode
*vp
= ap
->a_vp
;
1151 return lf_advlock(ap
, &vp
->v_speclockf
, (off_t
)0);