Author: mjg
Date: Sat Jul 25 00:37:34 2020
New Revision: 363506
URL: https://svnweb.freebsd.org/changeset/base/363506

Log:
  MFC r355228:
  
      devfs: introduce a per-dev lock to protect ->si_devsw

Modified:
  stable/12/sys/fs/devfs/devfs_devs.c
  stable/12/sys/fs/devfs/devfs_int.h
  stable/12/sys/kern/kern_conf.c
  stable/12/sys/kern/subr_witness.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/fs/devfs/devfs_devs.c
==============================================================================
--- stable/12/sys/fs/devfs/devfs_devs.c Sat Jul 25 00:24:11 2020        
(r363505)
+++ stable/12/sys/fs/devfs/devfs_devs.c Sat Jul 25 00:37:34 2020        
(r363506)
@@ -138,6 +138,8 @@ devfs_alloc(int flags)
        if (cdp == NULL)
                return (NULL);
 
+       mtx_init(&cdp->cdp_threadlock, "devthrd", NULL, MTX_DEF);
+
        cdp->cdp_dirents = &cdp->cdp_dirent0;
 
        cdev = &cdp->cdp_c;
@@ -180,6 +182,7 @@ devfs_free(struct cdev *cdev)
        devfs_free_cdp_inode(cdp->cdp_inode);
        if (cdp->cdp_maxdirent > 0) 
                free(cdp->cdp_dirents, M_DEVFS2);
+       mtx_destroy(&cdp->cdp_threadlock);
        free(cdp, M_CDEVP);
 }
 

Modified: stable/12/sys/fs/devfs/devfs_int.h
==============================================================================
--- stable/12/sys/fs/devfs/devfs_int.h  Sat Jul 25 00:24:11 2020        
(r363505)
+++ stable/12/sys/fs/devfs/devfs_int.h  Sat Jul 25 00:37:34 2020        
(r363506)
@@ -70,6 +70,8 @@ struct cdev_priv {
        void                    *cdp_dtr_cb_arg;
 
        LIST_HEAD(, cdev_privdata) cdp_fdpriv;
+
+       struct mtx              cdp_threadlock;
 };
 
 #define        cdev2priv(c)    __containerof(c, struct cdev_priv, cdp_c)

Modified: stable/12/sys/kern/kern_conf.c
==============================================================================
--- stable/12/sys/kern/kern_conf.c      Sat Jul 25 00:24:11 2020        
(r363505)
+++ stable/12/sys/kern/kern_conf.c      Sat Jul 25 00:37:34 2020        
(r363506)
@@ -186,16 +186,16 @@ dev_refthread(struct cdev *dev, int *ref)
                *ref = 0;
                return (dev->si_devsw);
        }
-       dev_lock();
+       cdp = cdev2priv(dev);
+       mtx_lock(&cdp->cdp_threadlock);
        csw = dev->si_devsw;
        if (csw != NULL) {
-               cdp = cdev2priv(dev);
                if ((cdp->cdp_flags & CDP_SCHED_DTR) == 0)
                        atomic_add_long(&dev->si_threadcount, 1);
                else
                        csw = NULL;
        }
-       dev_unlock();
+       mtx_unlock(&cdp->cdp_threadlock);
        *ref = 1;
        return (csw);
 }
@@ -222,19 +222,21 @@ devvn_refthread(struct vnode *vp, struct cdev **devp, 
        }
 
        csw = NULL;
-       dev_lock();
+       VI_LOCK(vp);
        dev = vp->v_rdev;
        if (dev == NULL) {
-               dev_unlock();
+               VI_UNLOCK(vp);
                return (NULL);
        }
        cdp = cdev2priv(dev);
+       mtx_lock(&cdp->cdp_threadlock);
        if ((cdp->cdp_flags & CDP_SCHED_DTR) == 0) {
                csw = dev->si_devsw;
                if (csw != NULL)
                        atomic_add_long(&dev->si_threadcount, 1);
        }
-       dev_unlock();
+       mtx_unlock(&cdp->cdp_threadlock);
+       VI_UNLOCK(vp);
        if (csw != NULL) {
                *devp = dev;
                *ref = 1;
@@ -1132,20 +1134,26 @@ destroy_devl(struct cdev *dev)
                dev->si_flags &= ~SI_CLONELIST;
        }
 
+       mtx_lock(&cdp->cdp_threadlock);
        csw = dev->si_devsw;
        dev->si_devsw = NULL;   /* already NULL for SI_ALIAS */
        while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) {
                csw->d_purge(dev);
+               mtx_unlock(&cdp->cdp_threadlock);
                msleep(csw, &devmtx, PRIBIO, "devprg", hz/10);
+               mtx_lock(&cdp->cdp_threadlock);
                if (dev->si_threadcount)
                        printf("Still %lu threads in %s\n",
                            dev->si_threadcount, devtoname(dev));
        }
        while (dev->si_threadcount != 0) {
                /* Use unique dummy wait ident */
+               mtx_unlock(&cdp->cdp_threadlock);
                msleep(&csw, &devmtx, PRIBIO, "devdrn", hz / 10);
+               mtx_lock(&cdp->cdp_threadlock);
        }
 
+       mtx_unlock(&cdp->cdp_threadlock);
        dev_unlock();
        if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
                /* avoid out of order notify events */

Modified: stable/12/sys/kern/subr_witness.c
==============================================================================
--- stable/12/sys/kern/subr_witness.c   Sat Jul 25 00:24:11 2020        
(r363505)
+++ stable/12/sys/kern/subr_witness.c   Sat Jul 25 00:37:34 2020        
(r363506)
@@ -602,6 +602,7 @@ static struct witness_order_list_entry order_lists[] =
        { "vm map (system)", &lock_class_mtx_sleep },
        { "vnode interlock", &lock_class_mtx_sleep },
        { "cdev", &lock_class_mtx_sleep },
+       { "devthrd", &lock_class_mtx_sleep },
        { NULL, NULL },
        /*
         * VM
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to