On Thu, Mar 31, 2016 at 06:02:07AM -0600, Todd C. Miller wrote:
> On Thu, 31 Mar 2016 09:34:32 +0200, Martin Natano wrote:
> 
> > Thank you all for the input. Allocatig the bitmap via malloc() really
> > seems like the way to go, so we don't waste space for non-cloning
> > devices. See updated patch below.
> > 
> > Would it make sense to move the (rdev == VCHR && ...) condition to a
> > macro in <sys/specdev.h>? I figured it's only used twice, so I inlined
> > it.
> 
> I think it is fine to inline that but please put a set of parens
> around the bitwise and part for readability.

Sure; see the updated patch below. Ok?

natano


Index: sys/specdev.h
===================================================================
RCS file: /cvs/src/sys/sys/specdev.h,v
retrieving revision 1.34
diff -u -p -r1.34 specdev.h
--- sys/specdev.h       2 Nov 2013 00:16:31 -0000       1.34
+++ sys/specdev.h       31 Mar 2016 12:32:53 -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_MAP_SZ   128
 
 /*
  * Special device management
Index: kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.240
diff -u -p -r1.240 vfs_subr.c
--- kern/vfs_subr.c     19 Mar 2016 12:04:15 -0000      1.240
+++ kern/vfs_subr.c     31 Mar 2016 12:32:54 -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_rdev == VCHR &&
+                   (cdevsw[major(nvp_rdev)].d_flags & D_CLONE) &&
+                   minor(nvp_rdev) >> CLONE_SHIFT == 0) {
+                       nvp->v_specbitmap = malloc(CLONE_MAP_SZ, 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_rdev == VCHR &&
+                   (cdevsw[major(vp->v_rdev)].d_flags & D_CLONE) &&
+                   minor(vp->v_rdev) >> CLONE_SHIFT == 0) {
+                       free(vp->v_specbitmap, M_VNODE, CLONE_MAP_SZ);
                }
                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.86
diff -u -p -r1.86 spec_vnops.c
--- kern/spec_vnops.c   19 Mar 2016 12:04:15 -0000      1.86
+++ kern/spec_vnops.c   31 Mar 2016 12:32:54 -0000
@@ -707,13 +707,14 @@ 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_MAP_SZ * NBBY; i++) {
                if (isclr(vp->v_specbitmap, i)) {
                        setbit(vp->v_specbitmap, i);
                        break;
                }
+       }
 
-       if (i == sizeof(vp->v_specbitmap) * NBBY)
+       if (i == CLONE_MAP_SZ * NBBY)
                return (EBUSY); /* too many open instances */
 
        error = cdevvp(makedev(major(vp->v_rdev),

Reply via email to