Below is the fixed v_specbitmap enlargements diff, including some tweaks
by mikeb@. I have tested this with fuse _and_ drm on amd64 and macppc. I
also tested on macppc with cloning bpf (not in the tree). Can anyone
come up with another interesting test case?
Comments? Ok?
natano
Index: sys/specdev.h
===================================================================
RCS file: /cvs/src/sys/sys/specdev.h,v
retrieving revision 1.36
diff -u -p -r1.36 specdev.h
--- sys/specdev.h 1 Apr 2016 11:51:55 -0000 1.36
+++ sys/specdev.h 1 Apr 2016 20:35:50 -0000
@@ -46,7 +46,7 @@ struct specinfo {
daddr_t si_lastr;
union {
struct vnode *ci_parent; /* pointer back to parent device */
- u_int8_t ci_bitmap[8]; /* bitmap of devices cloned off us */
+ u_int8_t *ci_bitmap; /* bitmap of devices cloned off us */
} si_ci;
};
@@ -71,6 +71,7 @@ struct cloneinfo {
* This gives us 8 bits for encoding the real minor number.
*/
#define CLONE_SHIFT 8
+#define CLONE_MAPSZ 128
/*
* Special device management
Index: kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.242
diff -u -p -r1.242 vfs_subr.c
--- kern/vfs_subr.c 1 Apr 2016 11:51:55 -0000 1.242
+++ kern/vfs_subr.c 1 Apr 2016 20:35:50 -0000
@@ -555,7 +555,13 @@ loop:
nvp->v_specnext = *vpp;
nvp->v_specmountpoint = NULL;
nvp->v_speclockf = NULL;
- memset(nvp->v_specbitmap, 0, sizeof(nvp->v_specbitmap));
+ nvp->v_specbitmap = NULL;
+ if (nvp->v_type == VCHR &&
+ (cdevsw[major(nvp_rdev)].d_flags & D_CLONE) &&
+ (minor(nvp_rdev) >> CLONE_SHIFT == 0)) {
+ nvp->v_specbitmap = malloc(CLONE_MAPSZ, M_VNODE,
+ M_WAITOK | M_ZERO);
+ }
*vpp = nvp;
if (vp != NULLVP) {
nvp->v_flag |= VALIASED;
@@ -1092,6 +1098,11 @@ vgonel(struct vnode *vp, struct proc *p)
if (vq == NULL)
vx->v_flag &= ~VALIASED;
vp->v_flag &= ~VALIASED;
+ }
+ if (vp->v_type == VCHR &&
+ (cdevsw[major(vp->v_rdev)].d_flags & D_CLONE) &&
+ (minor(vp->v_rdev) >> CLONE_SHIFT == 0)) {
+ free(vp->v_specbitmap, M_VNODE, CLONE_MAPSZ);
}
free(vp->v_specinfo, M_VNODE, sizeof(struct specinfo));
vp->v_specinfo = NULL;
Index: kern/spec_vnops.c
===================================================================
RCS file: /cvs/src/sys/kern/spec_vnops.c,v
retrieving revision 1.88
diff -u -p -r1.88 spec_vnops.c
--- kern/spec_vnops.c 1 Apr 2016 11:51:55 -0000 1.88
+++ kern/spec_vnops.c 1 Apr 2016 20:35:50 -0000
@@ -707,13 +707,13 @@ spec_open_clone(struct vop_open_args *ap
if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT))
return (ENXIO);
- for (i = 1; i < sizeof(vp->v_specbitmap) * NBBY; i++)
+ for (i = 1; i < CLONE_MAPSZ * NBBY; i++)
if (isclr(vp->v_specbitmap, i)) {
setbit(vp->v_specbitmap, i);
break;
}
- if (i == sizeof(vp->v_specbitmap) * NBBY)
+ if (i == CLONE_MAPSZ * NBBY)
return (EBUSY); /* too many open instances */
error = cdevvp(makedev(major(vp->v_rdev),