svn commit: r278293 - in stable/8/sys: fs/devfs kern sys
Hans Petter Selasky
hselasky at FreeBSD.org
Thu Feb 5 21:53:43 UTC 2015
Author: hselasky
Date: Thu Feb 5 21:53:41 2015
New Revision: 278293
URL: https://svnweb.freebsd.org/changeset/base/278293
Log:
MFC r277179, r277199 and r277391:
Add a kernel function to delist our kernel character devices, so that
the device name can be re-used right away in case we are destroying
the character devices in the background.
Modified:
stable/8/sys/fs/devfs/devfs_int.h
stable/8/sys/kern/kern_conf.c
stable/8/sys/sys/conf.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/dev/ (props changed)
stable/8/sys/dev/usb/ (props changed)
stable/8/sys/fs/ (props changed)
stable/8/sys/kern/ (props changed)
stable/8/sys/sys/ (props changed)
Modified: stable/8/sys/fs/devfs/devfs_int.h
==============================================================================
--- stable/8/sys/fs/devfs/devfs_int.h Thu Feb 5 21:50:51 2015 (r278292)
+++ stable/8/sys/fs/devfs/devfs_int.h Thu Feb 5 21:53:41 2015 (r278293)
@@ -55,6 +55,7 @@ struct cdev_priv {
u_int cdp_flags;
#define CDP_ACTIVE (1 << 0)
#define CDP_SCHED_DTR (1 << 1)
+#define CDP_UNREF_DTR (1 << 2)
u_int cdp_inuse;
u_int cdp_maxdirent;
Modified: stable/8/sys/kern/kern_conf.c
==============================================================================
--- stable/8/sys/kern/kern_conf.c Thu Feb 5 21:50:51 2015 (r278292)
+++ stable/8/sys/kern/kern_conf.c Thu Feb 5 21:53:41 2015 (r278293)
@@ -115,6 +115,8 @@ dev_free_devlocked(struct cdev *cdev)
mtx_assert(&devmtx, MA_OWNED);
cdp = cdev2priv(cdev);
+ KASSERT((cdp->cdp_flags & CDP_UNREF_DTR) == 0,
+ ("destroy_dev() was not called after delist_dev(%p)", cdev));
TAILQ_INSERT_HEAD(&cdevp_free_list, cdp, cdp_list);
}
@@ -871,6 +873,7 @@ destroy_devl(struct cdev *dev)
{
struct cdevsw *csw;
struct cdev_privdata *p;
+ struct cdev_priv *cdp;
mtx_assert(&devmtx, MA_OWNED);
KASSERT(dev->si_flags & SI_NAMED,
@@ -879,13 +882,22 @@ destroy_devl(struct cdev *dev)
("WARNING: Driver mistake: destroy_dev on eternal %d\n",
dev2unit(dev)));
- devfs_destroy(dev);
+ cdp = cdev2priv(dev);
+ if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
+ /*
+ * Avoid race with dev_rel(), e.g. from the populate
+ * loop. If CDP_UNREF_DTR flag is set, the reference
+ * to be dropped at the end of destroy_devl() was
+ * already taken by delist_dev_locked().
+ */
+ dev_refl(dev);
+
+ devfs_destroy(dev);
+ }
/* Remove name marking */
dev->si_flags &= ~SI_NAMED;
- dev->si_refcount++; /* Avoid race with dev_rel() */
-
/* If we are a child, remove us from the parents list */
if (dev->si_flags & SI_CHILD) {
LIST_REMOVE(dev, si_siblings);
@@ -941,13 +953,39 @@ destroy_devl(struct cdev *dev)
}
}
dev->si_flags &= ~SI_ALIAS;
- dev->si_refcount--; /* Avoid race with dev_rel() */
+ cdp->cdp_flags &= ~CDP_UNREF_DTR;
+ dev->si_refcount--;
- if (dev->si_refcount > 0) {
+ if (dev->si_refcount > 0)
LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
- } else {
+ else
dev_free_devlocked(dev);
- }
+}
+
+static void
+delist_dev_locked(struct cdev *dev)
+{
+ struct cdev_priv *cdp;
+ struct cdev *child;
+
+ mtx_assert(&devmtx, MA_OWNED);
+ cdp = cdev2priv(dev);
+ if ((cdp->cdp_flags & CDP_UNREF_DTR) != 0)
+ return;
+ cdp->cdp_flags |= CDP_UNREF_DTR;
+ dev_refl(dev);
+ devfs_destroy(dev);
+ LIST_FOREACH(child, &dev->si_children, si_siblings)
+ delist_dev_locked(child);
+}
+
+void
+delist_dev(struct cdev *dev)
+{
+
+ dev_lock();
+ delist_dev_locked(dev);
+ dev_unlock();
}
void
Modified: stable/8/sys/sys/conf.h
==============================================================================
--- stable/8/sys/sys/conf.h Thu Feb 5 21:50:51 2015 (r278292)
+++ stable/8/sys/sys/conf.h Thu Feb 5 21:53:41 2015 (r278293)
@@ -254,6 +254,7 @@ void clone_cleanup(struct clonedevs **);
int clone_create(struct clonedevs **, struct cdevsw *, int *unit, struct cdev **dev, int extra);
int count_dev(struct cdev *_dev);
+void delist_dev(struct cdev *_dev);
void destroy_dev(struct cdev *_dev);
int destroy_dev_sched(struct cdev *dev);
int destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg);
More information about the svn-src-stable-8
mailing list