diff options
author | phk <phk@FreeBSD.org> | 1999-08-29 09:09:12 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1999-08-29 09:09:12 +0000 |
commit | 244faf2e1bea24c6fcd49a96a0891eccf5512347 (patch) | |
tree | 42212b7ace3a6c7f66fb134cfdb92513e47759fd /sys/kern | |
parent | b40f30707d14d710c90e70efe406d062ea6b9f7d (diff) | |
download | FreeBSD-src-244faf2e1bea24c6fcd49a96a0891eccf5512347.zip FreeBSD-src-244faf2e1bea24c6fcd49a96a0891eccf5512347.tar.gz |
Add dev_t freeing code. Controlled by sysctl debug.free_devt, default
is off.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_conf.c | 67 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 3 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 3 |
3 files changed, 62 insertions, 11 deletions
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index 3f49464..325c7ef 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -35,6 +35,7 @@ #include <sys/param.h> #include <sys/kernel.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <sys/module.h> #include <sys/malloc.h> @@ -63,9 +64,15 @@ MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); static struct specinfo devt_stash[DEVT_STASH]; -static SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH]; +static LIST_HEAD(, specinfo) dev_hash[DEVT_HASH]; + +static LIST_HEAD(, specinfo) dev_free; devfs_create_t *devfs_create_hook; +devfs_remove_t *devfs_remove_hook; + +static int free_devt; +SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, ""); /* * Routine to convert from character to block device number. @@ -230,26 +237,47 @@ makedev(int x, int y) udev = (x << 8) | y; hash = udev % DEVT_HASH; - SLIST_FOREACH(si, &dev_hash[hash], si_hash) { + LIST_FOREACH(si, &dev_hash[hash], si_hash) { if (si->si_udev == udev) return (si); } if (stashed >= DEVT_STASH) { MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, M_USE_RESERVE); + bzero(si, sizeof(*si)); + } else if (LIST_FIRST(&dev_free)) { + si = LIST_FIRST(&dev_free); + LIST_REMOVE(si, si_hash); } else { si = devt_stash + stashed++; + si->si_flags |= SI_STASHED; } - bzero(si, sizeof(*si)); si->si_udev = udev; - if (y > 256) - sprintf(si->si_name, "#%d/0x%x", x, y); - else - sprintf(si->si_name, "#%d/%d", x, y); - SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); + LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); return (si); } +void +freedev(dev_t dev) +{ + int hash; + + if (!free_devt) + return; + if (SLIST_FIRST(&dev->si_hlist)) + return; + if (dev->si_devsw || dev->si_drv1 || dev->si_drv2) + return; + hash = dev->si_udev % DEVT_HASH; + LIST_REMOVE(dev, si_hash); + if (dev->si_flags & SI_STASHED) { + bzero(dev, sizeof(*dev)); + LIST_INSERT_HEAD(&dev_free, dev, si_hash); + } else { + FREE(dev, M_DEVT); + } +} + udev_t dev2udev(dev_t x) { @@ -318,10 +346,31 @@ make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char return (dev); } +void +remove_dev(dev_t dev) +{ + if (devfs_remove_hook) + devfs_remove_hook(dev); + dev->si_drv1 = 0; + dev->si_drv2 = 0; + dev->si_devsw = 0; + freedev(dev); +} + char * devtoname(dev_t dev) { - + char *p; + + if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { + p = dev->si_name; + if (devsw(dev)) + sprintf(p, "#%s/", devsw(dev)->d_name); + else + sprintf(p, "#%d/", major(dev)); + p += strlen(p); + sprintf(p, minor(dev) > 255 ? "0x%x" : "%d", minor(dev)); + } return (dev->si_name); } diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index c6ce788..b452cc1 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -1692,7 +1692,7 @@ vclean(vp, flags, p) if (VSHOULDFREE(vp)) vfree(vp); - + /* * Done with purge, notify sleepers of the grim news. */ @@ -1821,6 +1821,7 @@ vgonel(vp, p) if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_rdev != NULL) { simple_lock(&spechash_slock); SLIST_REMOVE(&vp->v_hashchain, vp, vnode, v_specnext); + freedev(vp->v_rdev); simple_unlock(&spechash_slock); vp->v_rdev = NULL; } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index c6ce788..b452cc1 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1692,7 +1692,7 @@ vclean(vp, flags, p) if (VSHOULDFREE(vp)) vfree(vp); - + /* * Done with purge, notify sleepers of the grim news. */ @@ -1821,6 +1821,7 @@ vgonel(vp, p) if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_rdev != NULL) { simple_lock(&spechash_slock); SLIST_REMOVE(&vp->v_hashchain, vp, vnode, v_specnext); + freedev(vp->v_rdev); simple_unlock(&spechash_slock); vp->v_rdev = NULL; } |