summaryrefslogtreecommitdiffstats
path: root/sys/kern/spec_vnops.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2013-08-06 08:22:37 +0000
committerkettenis <kettenis@openbsd.org>2013-08-06 08:22:37 +0000
commit8ee7e372d768100fd5261a28f21d57ad9fa08738 (patch)
tree2c180963e051d8b73c5977a6d103e71c5553d2b9 /sys/kern/spec_vnops.c
parentThe atomic_setbits_int() and atomic_clearbits_int() functions touch the (diff)
downloadwireguard-openbsd-8ee7e372d768100fd5261a28f21d57ad9fa08738.tar.xz
wireguard-openbsd-8ee7e372d768100fd5261a28f21d57ad9fa08738.zip
Make it possible to have multiple clonable devices per major.
Diffstat (limited to 'sys/kern/spec_vnops.c')
-rw-r--r--sys/kern/spec_vnops.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c
index 49d301de241..20ce5f2da03 100644
--- a/sys/kern/spec_vnops.c
+++ b/sys/kern/spec_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spec_vnops.c,v 1.75 2013/07/29 18:51:42 kettenis Exp $ */
+/* $OpenBSD: spec_vnops.c,v 1.76 2013/08/06 08:22:37 kettenis Exp $ */
/* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */
/*
@@ -691,6 +691,9 @@ spec_open_clone(struct vop_open_args *ap)
DNPRINTF("cloning vnode\n");
+ if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT))
+ return (ENXIO);
+
for (i = 1; i < sizeof(vp->v_specbitmap) * NBBY; i++)
if (isclr(vp->v_specbitmap, i)) {
setbit(vp->v_specbitmap, i);
@@ -700,7 +703,8 @@ spec_open_clone(struct vop_open_args *ap)
if (i == sizeof(vp->v_specbitmap) * NBBY)
return (EBUSY); /* too many open instances */
- error = cdevvp(makedev(major(vp->v_rdev), i), &cvp);
+ error = cdevvp(makedev(major(vp->v_rdev),
+ (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp);
if (error) {
clrbit(vp->v_specbitmap, i);
return (error); /* out of vnodes */
@@ -746,7 +750,7 @@ spec_close_clone(struct vop_close_args *ap)
return (error); /* device close failed */
pvp = vp->v_specparent; /* get parent device */
- clrbit(pvp->v_specbitmap, minor(vp->v_rdev));
+ clrbit(pvp->v_specbitmap, minor(vp->v_rdev) >> CLONE_SHIFT);
vrele(pvp);
return (0); /* clone closed */