summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/devfs/devfs.h1
-rw-r--r--sys/fs/devfs/devfs_vnops.c33
-rw-r--r--sys/kern/kern_conf.c24
-rw-r--r--sys/kern/vfs_subr.c2
-rw-r--r--sys/sys/conf.h5
-rw-r--r--sys/sys/vnode.h8
6 files changed, 34 insertions, 39 deletions
diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h
index ba8bbf0..5a484c9 100644
--- a/sys/fs/devfs/devfs.h
+++ b/sys/fs/devfs/devfs.h
@@ -154,6 +154,7 @@ struct devfs_dirent {
struct dirent *de_dirent;
TAILQ_ENTRY(devfs_dirent) de_list;
TAILQ_HEAD(, devfs_dirent) de_dlist;
+ LIST_ENTRY(devfs_dirent) de_alias;
struct devfs_dirent *de_dir;
int de_links;
mode_t de_mode;
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index e51ca4f..4adacb4 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -199,7 +199,7 @@ loop:
dev_lock();
dev_ref(dev);
vp->v_rdev = dev;
- SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_specnext);
+ LIST_INSERT_HEAD(&dev->si_alist, de, de_alias);
dev->si_usecount += vp->v_usecount;
dev_unlock();
VI_UNLOCK(vp);
@@ -1041,19 +1041,23 @@ devfs_reclaim(ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *de;
- int i;
+ struct cdev *dev;
de = vp->v_data;
if (de != NULL)
de->de_vnode = NULL;
vp->v_data = NULL;
- if (vp->v_rdev != NULL) {
- i = vcount(vp);
- if ((vp->v_rdev->si_flags & SI_CHEAPCLONE) && i == 0 &&
- (vp->v_rdev->si_flags & SI_NAMED))
- destroy_dev(vp->v_rdev);
- }
vnode_destroy_vobject(vp);
+
+ dev = vp->v_rdev;
+ vp->v_rdev = NULL;
+
+ dev_lock();
+ if (de != NULL)
+ LIST_REMOVE(de, de_alias);
+ dev->si_usecount -= vp->v_usecount;
+ dev_unlock();
+ dev_rel(dev);
return (0);
}
@@ -1101,13 +1105,10 @@ devfs_revoke(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
- struct vnode *vq;
- struct devfs_dirent *de;
struct cdev *dev;
+ struct devfs_dirent *de;
KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL"));
- de = vp->v_data;
- de->de_vnode = NULL;
/*
* If a vgone (or vclean) is already in progress,
@@ -1115,15 +1116,15 @@ devfs_revoke(ap)
*/
if (vx_wait(vp))
return (0);
-
+
dev = vp->v_rdev;
for (;;) {
dev_lock();
- vq = SLIST_FIRST(&dev->si_hlist);
+ de = LIST_FIRST(&dev->si_alist);
dev_unlock();
- if (vq == NULL)
+ if (de == NULL)
break;
- vgone(vq);
+ vgone(de->de_vnode);
}
return (0);
}
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index 12402cb..fe9339d 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -61,6 +61,7 @@ static LIST_HEAD(, cdev) dev_hash[DEVT_HASH];
static struct mtx devmtx;
static void freedev(struct cdev *dev);
static struct cdev *newdev(int x, int y, struct cdev *);
+static void destroy_devl(struct cdev *dev);
void
dev_lock(void)
@@ -86,21 +87,17 @@ dev_ref(struct cdev *dev)
}
void
-dev_rel(struct vnode *vp)
+dev_rel(struct cdev *dev)
{
- struct cdev *dev;
- int flag;
+ int flag = 0;
- dev = vp->v_rdev;
mtx_assert(&devmtx, MA_NOTOWNED);
dev_lock();
- SLIST_REMOVE(&dev->si_hlist, vp, vnode, v_specnext);
- dev->si_usecount -= vp->v_usecount;
- vp->v_rdev = NULL;
dev->si_refcount--;
KASSERT(dev->si_refcount >= 0,
("dev_rel(%s) gave negative count", devtoname(dev)));
- flag = 0;
+ if (dev->si_usecount == 0 &&
+ (dev->si_flags & SI_CHEAPCLONE) && (dev->si_flags & SI_NAMED))
if (dev->si_devsw == NULL && dev->si_refcount == 0) {
LIST_REMOVE(dev, si_list);
flag = 1;
@@ -108,7 +105,6 @@ dev_rel(struct vnode *vp)
dev_unlock();
if (flag)
freedev(dev);
- return;
}
struct cdevsw *
@@ -287,6 +283,7 @@ allocdev(void)
si = malloc(sizeof *si, M_DEVT, M_USE_RESERVE | M_ZERO | M_WAITOK);
si->si_name = si->__si_namebuf;
LIST_INIT(&si->si_children);
+ LIST_INIT(&si->si_alist);
return (si);
}
@@ -547,10 +544,11 @@ make_dev_alias(struct cdev *pdev, const char *fmt, ...)
}
static void
-idestroy_dev(struct cdev *dev)
+destroy_devl(struct cdev *dev)
{
struct cdevsw *csw;
+ mtx_assert(&devmtx, MA_OWNED);
KASSERT(dev->si_flags & SI_NAMED,
("WARNING: Driver mistake: destroy_dev on %d/%d\n",
major(dev), minor(dev)));
@@ -568,7 +566,7 @@ idestroy_dev(struct cdev *dev)
/* Kill our children */
while (!LIST_EMPTY(&dev->si_children))
- idestroy_dev(LIST_FIRST(&dev->si_children));
+ destroy_devl(LIST_FIRST(&dev->si_children));
/* Remove from clone list */
if (dev->si_flags & SI_CLONELIST) {
@@ -615,7 +613,7 @@ destroy_dev(struct cdev *dev)
{
dev_lock();
- idestroy_dev(dev);
+ destroy_devl(dev);
dev_unlock();
}
@@ -796,7 +794,7 @@ clone_cleanup(struct clonedevs **cdp)
("Dev %p(%s) should be on clonelist", dev, dev->si_name));
KASSERT(dev->si_flags & SI_NAMED,
("Driver has goofed in cloning underways udev %x", dev->si_udev));
- idestroy_dev(dev);
+ destroy_devl(dev);
}
dev_unlock();
free(cd, M_DEVBUF);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 97fa19dd..e36f937 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2394,8 +2394,6 @@ vgonel(struct vnode *vp, struct thread *td)
* if it is on one.
*/
VI_LOCK(vp);
- if (vp->v_type == VCHR && vp->v_rdev != NULL)
- dev_rel(vp);
/*
* If it is on the freelist and not already at the head,
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 143faf5..16a132c 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -51,6 +51,7 @@ struct disk;
struct vnode;
struct buf;
struct snapdata;
+struct devfs_dirent;
struct cdev {
u_int si_flags;
@@ -71,7 +72,7 @@ struct cdev {
LIST_ENTRY(cdev) si_list;
LIST_ENTRY(cdev) si_clone;
LIST_ENTRY(cdev) si_hash;
- SLIST_HEAD(, vnode) si_hlist;
+ LIST_HEAD(,devfs_dirent)si_alist;
LIST_HEAD(, cdev) si_children;
LIST_ENTRY(cdev) si_siblings;
struct cdev *si_parent;
@@ -258,7 +259,7 @@ const char *devtoname(struct cdev *_dev);
int dev_named(struct cdev *_pdev, const char *_name);
void dev_depends(struct cdev *_pdev, struct cdev *_cdev);
void dev_ref(struct cdev *dev);
-void dev_rel(struct vnode *vp);
+void dev_rel(struct cdev *dev);
void dev_strategy(struct cdev *dev, struct buf *bp);
struct cdev *makebdev(int _maj, int _min);
struct cdev *make_dev(struct cdevsw *_devsw, int _minor, uid_t _uid, gid_t _gid,
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 0671248..2139919 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -121,10 +121,7 @@ struct vnode {
union {
struct mount *vu_mountedhere;/* v ptr to mounted vfs (VDIR) */
struct socket *vu_socket; /* v unix ipc (VSOCK) */
- struct {
- struct cdev *vu_cdev; /* v device (VCHR, VBLK) */
- SLIST_ENTRY(vnode) vu_specnext; /* s device aliases */
- } vu_spec;
+ struct cdev *vu_cdev; /* v device (VCHR, VBLK) */
struct fifoinfo *vu_fifoinfo; /* v fifo (VFIFO) */
} v_un;
TAILQ_ENTRY(vnode) v_freelist; /* f vnode freelist */
@@ -153,8 +150,7 @@ struct vnode {
#define v_mountedhere v_un.vu_mountedhere
#define v_socket v_un.vu_socket
-#define v_rdev v_un.vu_spec.vu_cdev
-#define v_specnext v_un.vu_spec.vu_specnext
+#define v_rdev v_un.vu_cdev
#define v_fifoinfo v_un.vu_fifoinfo
/* XXX: These are temporary to avoid a source sweep at this time */
OpenPOWER on IntegriCloud