Add dev_t freeing code. Controlled by sysctl debug.free_devt, default

is off.
This commit is contained in:
Poul-Henning Kamp 1999-08-29 09:09:12 +00:00
parent 3de9d6fbe4
commit d137accc89
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=50549
5 changed files with 73 additions and 14 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -50,9 +50,10 @@ struct tty;
struct vnode;
struct specinfo {
u_int si_flags;
#define SI_STASHED 0x0001 /* created in stashed storage */
udev_t si_udev;
SLIST_ENTRY(specinfo) si_hash;
LIST_ENTRY(specinfo) si_hash;
SLIST_HEAD(, vnode) si_hlist;
char si_name[SPECNAMELEN + 1];
void *si_drv1, *si_drv2;
@ -127,6 +128,7 @@ typedef int l_modem_t __P((struct tty *tp, int flag));
/* This is type of the function DEVFS uses to hook into the kernel with */
typedef void devfs_create_t __P((dev_t dev, uid_t uid, gid_t gid, int perms));
typedef void devfs_remove_t __P((dev_t dev));
/*
* XXX: The dummy argument can be used to do what strategy1() never
@ -275,11 +277,13 @@ dev_t chrtoblk __P((dev_t dev));
struct cdevsw *devsw __P((dev_t dev));
int devsw_module_handler __P((struct module *mod, int what, void *arg));
char *devtoname __P((dev_t dev));
void freedev __P((dev_t dev));
int iskmemdev __P((dev_t dev));
int iszerodev __P((dev_t dev));
dev_t makebdev __P((int maj, int min));
dev_t make_dev __P((struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...)) __printflike(6, 7);
int lminor __P((dev_t dev));
void remove_dev __P((dev_t dev));
void setconf __P((void));
extern devfs_create_t *devfs_create_hook;

View File

@ -50,9 +50,10 @@ struct tty;
struct vnode;
struct specinfo {
u_int si_flags;
#define SI_STASHED 0x0001 /* created in stashed storage */
udev_t si_udev;
SLIST_ENTRY(specinfo) si_hash;
LIST_ENTRY(specinfo) si_hash;
SLIST_HEAD(, vnode) si_hlist;
char si_name[SPECNAMELEN + 1];
void *si_drv1, *si_drv2;
@ -127,6 +128,7 @@ typedef int l_modem_t __P((struct tty *tp, int flag));
/* This is type of the function DEVFS uses to hook into the kernel with */
typedef void devfs_create_t __P((dev_t dev, uid_t uid, gid_t gid, int perms));
typedef void devfs_remove_t __P((dev_t dev));
/*
* XXX: The dummy argument can be used to do what strategy1() never
@ -275,11 +277,13 @@ dev_t chrtoblk __P((dev_t dev));
struct cdevsw *devsw __P((dev_t dev));
int devsw_module_handler __P((struct module *mod, int what, void *arg));
char *devtoname __P((dev_t dev));
void freedev __P((dev_t dev));
int iskmemdev __P((dev_t dev));
int iszerodev __P((dev_t dev));
dev_t makebdev __P((int maj, int min));
dev_t make_dev __P((struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...)) __printflike(6, 7);
int lminor __P((dev_t dev));
void remove_dev __P((dev_t dev));
void setconf __P((void));
extern devfs_create_t *devfs_create_hook;