From 7cbab9dafa4f803b27a7ff3273e0ce988b0aa8be Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Wed, 5 Aug 2009 19:29:45 +0100 Subject: [PATCH] DEVFS - change the rdev allocator to consider minor Add a unique id to each dev ops in use and use this one and the minor to construct the rdev. --- sys/kern/kern_conf.c | 2 +- sys/sys/device.h | 7 ++++--- sys/vfs/devfs/devfs.h | 3 +++ sys/vfs/devfs/devfs_core.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index ebccb53b11..e776db7c48 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -249,7 +249,7 @@ makeudev(int x, int y) { if ((x & 0xffffff00) || (y & 0x0000ff00)) return NOUDEV; - return ((x << 8) | y); + return ((x << 8) | y); } /* diff --git a/sys/sys/device.h b/sys/sys/device.h index dbd794d6bc..c12a886bab 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -207,10 +207,11 @@ typedef int d_revoke_t (struct dev_revoke_args *ap); struct dev_ops { struct { const char *name; /* base name, e.g. 'da' */ - int maj; /* major device number */ + int maj; /* major device number */ u_int flags; /* D_XXX flags */ - void *data; /* custom driver data */ - int refs; /* ref count */ + void *data; /* custom driver data */ + int refs; /* ref count */ + int id; } head; #define dev_ops_first_field d_default diff --git a/sys/vfs/devfs/devfs.h b/sys/vfs/devfs/devfs.h index b4920e2989..760618f057 100644 --- a/sys/vfs/devfs/devfs.h +++ b/sys/vfs/devfs/devfs.h @@ -413,5 +413,8 @@ int devfs_clr_subnames_flag(char *, uint32_t); int devfs_destroy_subnames_without_flag(char *, uint32_t); int devfs_node_is_accessible(struct devfs_node *); +int devfs_reference_ops(struct dev_ops *); +void devfs_release_ops(struct dev_ops *); + void devfs_config(void *); #endif /* _VFS_DEVFS_H_ */ diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index e77f5266f2..2fd32a9159 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -45,11 +45,12 @@ #include #include #include +#include #include #include MALLOC_DEFINE(M_DEVFS, "devfs", "Device File System (devfs) allocations"); - +DEVFS_DECLARE_CLONE_BITMAP(ops_id); /* * SYSREF Integration - reference counting, allocation, * sysid and syslink integration. @@ -2159,7 +2160,7 @@ devfs_new_cdev(struct dev_ops *ops, int minor) dev->si_flags = 0; dev->si_umajor = 0; dev->si_uminor = minor; - dev->si_inode = devfs_fetch_ino(); + dev->si_inode = makeudev(devfs_reference_ops(ops), minor); return dev; } @@ -2184,6 +2185,8 @@ devfs_cdev_terminate(cdev_t dev) if (locked) lockmgr(&devfs_lock, LK_RELEASE); + devfs_release_ops(dev->si_ops); + /* Finally destroy the device */ sysref_put(&dev->si_sysref); } @@ -2227,6 +2230,34 @@ devfs_node_is_accessible(struct devfs_node *node) return 0; } +int +devfs_reference_ops(struct dev_ops *ops) +{ + int unit; + + if (ops->head.refs == 0) { + ops->head.id = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(ops_id), 255); + if (ops->head.id == -1) { + /* Ran out of unique ids */ + kprintf("devfs_reference_ops: WARNING: ran out of unique ids\n"); + } + } + unit = ops->head.id; + ++ops->head.refs; + + return unit; +} + +void +devfs_release_ops(struct dev_ops *ops) +{ + --ops->head.refs; + + if (ops->head.refs == 0) { + devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ops_id), ops->head.id); + } +} + void devfs_config(void *arg) { @@ -2267,6 +2298,11 @@ devfs_init(void) objcache_malloc_free, &devfs_dev_malloc_args ); + devfs_clone_bitmap_init(&DEVFS_CLONE_BITMAP(ops_id)); +#if 0 + devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(ops_id), 0); +#endif + /* Initialize the reply-only port which acts as a message drain */ lwkt_initport_replyonly(&devfs_dispose_port, devfs_msg_autofree_reply); @@ -2296,6 +2332,8 @@ devfs_uninit(void) tsleep(td_core/*devfs_id*/, 0, "devfsc", 0); tsleep(td_core/*devfs_id*/, 0, "devfsc", 10000); + devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(ops_id)); + /* Destroy the objcaches */ objcache_destroy(devfs_msg_cache); objcache_destroy(devfs_node_cache); -- 2.11.4.GIT