Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Jul 2020 00:37:35 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r363506 - in stable/12/sys: fs/devfs kern
Message-ID:  <202007250037.06P0bZU0060284@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007250037.06P0bZU0060284>