Commit c2e562b9 authored by Andrew Morton's avatar Andrew Morton Committed by David S. Miller

[PATCH] dev_t [1/3]: kill cdev

Patch from Andries.Brouwer@cwi.nl

Now that 2.5.65 is out, the next dev_t patch.  It was a bit large and
unreadable, so I split it into three clean pieces.  Afterwards, since many
people ask for this, a fourth patch that actually changes the type of dev_t
(not to be applied yet, that is just for playing).

The first patch is the cdev-kill patch that I sent out earlier.  It is no use
having two forms of chardev registration in the source, and my version of the
path of small modifications does not pass through this version, although the
final result will not be that different.  So, kill cdev_cachep,
cdev_cache_init, cdfind, cdget, cdput, inode->i_cdev, struct char_device.
All of this is dead code today.

The second patch removes MAX_CHRDEV.

The third patch polishes linux/major.h.
parent c290f965
...@@ -23,110 +23,10 @@ ...@@ -23,110 +23,10 @@
/* serial module kmod load support */ /* serial module kmod load support */
struct tty_driver *get_tty_driver(kdev_t device); struct tty_driver *get_tty_driver(kdev_t device);
#define isa_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR) #define is_a_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR)
#define need_serial(ma,mi) (get_tty_driver(mk_kdev(ma,mi)) == NULL) #define need_serial(ma,mi) (get_tty_driver(mk_kdev(ma,mi)) == NULL)
#endif #endif
#define HASH_BITS 6
#define HASH_SIZE (1UL << HASH_BITS)
#define HASH_MASK (HASH_SIZE-1)
static struct list_head cdev_hashtable[HASH_SIZE];
static spinlock_t cdev_lock = SPIN_LOCK_UNLOCKED;
static kmem_cache_t * cdev_cachep;
#define alloc_cdev() \
((struct char_device *) kmem_cache_alloc(cdev_cachep, SLAB_KERNEL))
#define destroy_cdev(cdev) kmem_cache_free(cdev_cachep, (cdev))
static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
{
struct char_device *cdev = (struct char_device *) foo;
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR)
memset(cdev, 0, sizeof(*cdev));
}
void __init cdev_cache_init(void)
{
int i;
struct list_head *head = cdev_hashtable;
i = HASH_SIZE;
do {
INIT_LIST_HEAD(head);
head++;
i--;
} while (i);
cdev_cachep = kmem_cache_create("cdev_cache",
sizeof(struct char_device),
0, SLAB_HWCACHE_ALIGN, init_once,
NULL);
if (!cdev_cachep)
panic("Cannot create cdev_cache SLAB cache");
}
/*
* Most likely _very_ bad one - but then it's hardly critical for small
* /dev and can be fixed when somebody will need really large one.
*/
static inline unsigned long hash(dev_t dev)
{
unsigned long tmp = dev;
tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2);
return tmp & HASH_MASK;
}
static struct char_device *cdfind(dev_t dev, struct list_head *head)
{
struct list_head *p;
struct char_device *cdev;
list_for_each(p, head) {
cdev = list_entry(p, struct char_device, hash);
if (cdev->dev != dev)
continue;
atomic_inc(&cdev->count);
return cdev;
}
return NULL;
}
struct char_device *cdget(dev_t dev)
{
struct list_head * head = cdev_hashtable + hash(dev);
struct char_device *cdev, *new_cdev;
spin_lock(&cdev_lock);
cdev = cdfind(dev, head);
spin_unlock(&cdev_lock);
if (cdev)
return cdev;
new_cdev = alloc_cdev();
if (!new_cdev)
return NULL;
atomic_set(&new_cdev->count,1);
new_cdev->dev = dev;
spin_lock(&cdev_lock);
cdev = cdfind(dev, head);
if (!cdev) {
list_add(&new_cdev->hash, head);
spin_unlock(&cdev_lock);
return new_cdev;
}
spin_unlock(&cdev_lock);
destroy_cdev(new_cdev);
return cdev;
}
void cdput(struct char_device *cdev)
{
if (atomic_dec_and_lock(&cdev->count, &cdev_lock)) {
list_del(&cdev->hash);
spin_unlock(&cdev_lock);
destroy_cdev(cdev);
}
}
struct device_struct { struct device_struct {
const char * name; const char * name;
struct file_operations * fops; struct file_operations * fops;
...@@ -144,7 +44,8 @@ int get_chrdev_list(char *page) ...@@ -144,7 +44,8 @@ int get_chrdev_list(char *page)
read_lock(&chrdevs_lock); read_lock(&chrdevs_lock);
for (i = 0; i < MAX_CHRDEV ; i++) { for (i = 0; i < MAX_CHRDEV ; i++) {
if (chrdevs[i].fops) { if (chrdevs[i].fops) {
len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name); len += sprintf(page+len, "%3d %s\n",
i, chrdevs[i].name);
} }
} }
read_unlock(&chrdevs_lock); read_unlock(&chrdevs_lock);
...@@ -152,13 +53,14 @@ int get_chrdev_list(char *page) ...@@ -152,13 +53,14 @@ int get_chrdev_list(char *page)
} }
/* /*
Return the function table of a device. * Return the function table of a device.
Load the driver if needed. * Load the driver if needed.
Increment the reference count of module in question. * Increment the reference count of module in question.
*/ */
static struct file_operations * get_chrfops(unsigned int major, unsigned int minor) static struct file_operations *
get_chrfops(unsigned int major, unsigned int minor)
{ {
struct file_operations *ret = NULL; struct file_operations *ret;
if (!major || major >= MAX_CHRDEV) if (!major || major >= MAX_CHRDEV)
return NULL; return NULL;
...@@ -167,10 +69,12 @@ static struct file_operations * get_chrfops(unsigned int major, unsigned int min ...@@ -167,10 +69,12 @@ static struct file_operations * get_chrfops(unsigned int major, unsigned int min
ret = fops_get(chrdevs[major].fops); ret = fops_get(chrdevs[major].fops);
read_unlock(&chrdevs_lock); read_unlock(&chrdevs_lock);
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
if (ret && isa_tty_dev(major)) { if (ret && is_a_tty_dev(major)) {
lock_kernel(); lock_kernel();
if (need_serial(major,minor)) { if (need_serial(major,minor)) {
/* Force request_module anyway, but what for? */ /* Force request_module anyway, but what for? */
/* The reason is that we may have a driver for
/dev/tty1 already, but need one for /dev/ttyS1. */
fops_put(ret); fops_put(ret);
ret = NULL; ret = NULL;
} }
...@@ -189,7 +93,8 @@ static struct file_operations * get_chrfops(unsigned int major, unsigned int min ...@@ -189,7 +93,8 @@ static struct file_operations * get_chrfops(unsigned int major, unsigned int min
return ret; return ret;
} }
int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) int register_chrdev(unsigned int major, const char *name,
struct file_operations *fops)
{ {
if (major == 0) { if (major == 0) {
write_lock(&chrdevs_lock); write_lock(&chrdevs_lock);
......
...@@ -1563,7 +1563,6 @@ kmem_cache_t *filp_cachep; ...@@ -1563,7 +1563,6 @@ kmem_cache_t *filp_cachep;
EXPORT_SYMBOL(d_genocide); EXPORT_SYMBOL(d_genocide);
extern void bdev_cache_init(void); extern void bdev_cache_init(void);
extern void cdev_cache_init(void);
void __init vfs_caches_init(unsigned long mempages) void __init vfs_caches_init(unsigned long mempages)
{ {
...@@ -1584,5 +1583,4 @@ void __init vfs_caches_init(unsigned long mempages) ...@@ -1584,5 +1583,4 @@ void __init vfs_caches_init(unsigned long mempages)
files_init(mempages); files_init(mempages);
mnt_init(mempages); mnt_init(mempages);
bdev_cache_init(); bdev_cache_init();
cdev_cache_init();
} }
...@@ -2016,7 +2016,6 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb, ...@@ -2016,7 +2016,6 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb,
if ( S_ISCHR (de->mode) ) if ( S_ISCHR (de->mode) )
{ {
inode->i_rdev = to_kdev_t(de->u.cdev.dev); inode->i_rdev = to_kdev_t(de->u.cdev.dev);
inode->i_cdev = cdget(de->u.cdev.dev);
} }
else if ( S_ISBLK (de->mode) ) else if ( S_ISBLK (de->mode) )
{ {
......
...@@ -128,7 +128,6 @@ static struct inode *alloc_inode(struct super_block *sb) ...@@ -128,7 +128,6 @@ static struct inode *alloc_inode(struct super_block *sb)
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
inode->i_pipe = NULL; inode->i_pipe = NULL;
inode->i_bdev = NULL; inode->i_bdev = NULL;
inode->i_cdev = NULL;
inode->i_rdev = to_kdev_t(0); inode->i_rdev = to_kdev_t(0);
inode->i_security = NULL; inode->i_security = NULL;
if (security_inode_alloc(inode)) { if (security_inode_alloc(inode)) {
...@@ -242,10 +241,6 @@ void clear_inode(struct inode *inode) ...@@ -242,10 +241,6 @@ void clear_inode(struct inode *inode)
inode->i_sb->s_op->clear_inode(inode); inode->i_sb->s_op->clear_inode(inode);
if (inode->i_bdev) if (inode->i_bdev)
bd_forget(inode); bd_forget(inode);
else if (inode->i_cdev) {
cdput(inode->i_cdev);
inode->i_cdev = NULL;
}
inode->i_state = I_CLEAR; inode->i_state = I_CLEAR;
} }
...@@ -1315,7 +1310,6 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) ...@@ -1315,7 +1310,6 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
if (S_ISCHR(mode)) { if (S_ISCHR(mode)) {
inode->i_fop = &def_chr_fops; inode->i_fop = &def_chr_fops;
inode->i_rdev = to_kdev_t(rdev); inode->i_rdev = to_kdev_t(rdev);
inode->i_cdev = cdget(rdev);
} else if (S_ISBLK(mode)) { } else if (S_ISBLK(mode)) {
inode->i_fop = &def_blk_fops; inode->i_fop = &def_blk_fops;
inode->i_rdev = to_kdev_t(rdev); inode->i_rdev = to_kdev_t(rdev);
...@@ -1324,5 +1318,6 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) ...@@ -1324,5 +1318,6 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
else if (S_ISSOCK(mode)) else if (S_ISSOCK(mode))
inode->i_fop = &bad_sock_fops; inode->i_fop = &bad_sock_fops;
else else
printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n", mode); printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n",
mode);
} }
...@@ -331,12 +331,6 @@ struct address_space { ...@@ -331,12 +331,6 @@ struct address_space {
struct address_space *assoc_mapping; /* ditto */ struct address_space *assoc_mapping; /* ditto */
}; };
struct char_device {
struct list_head hash;
atomic_t count;
dev_t dev;
};
struct block_device { struct block_device {
struct list_head bd_hash; struct list_head bd_hash;
atomic_t bd_count; atomic_t bd_count;
...@@ -388,7 +382,6 @@ struct inode { ...@@ -388,7 +382,6 @@ struct inode {
struct list_head i_devices; struct list_head i_devices;
struct pipe_inode_info *i_pipe; struct pipe_inode_info *i_pipe;
struct block_device *i_bdev; struct block_device *i_bdev;
struct char_device *i_cdev;
unsigned long i_dnotify_mask; /* Directory notify events */ unsigned long i_dnotify_mask; /* Directory notify events */
struct dnotify_struct *i_dnotify; /* for directory notifications */ struct dnotify_struct *i_dnotify; /* for directory notifications */
...@@ -1046,8 +1039,6 @@ extern struct block_device *bdget(dev_t); ...@@ -1046,8 +1039,6 @@ extern struct block_device *bdget(dev_t);
extern int bd_acquire(struct inode *inode); extern int bd_acquire(struct inode *inode);
extern void bd_forget(struct inode *inode); extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *); extern void bdput(struct block_device *);
extern struct char_device *cdget(dev_t);
extern void cdput(struct char_device *);
extern int blkdev_open(struct inode *, struct file *); extern int blkdev_open(struct inode *, struct file *);
extern int blkdev_close(struct inode *, struct file *); extern int blkdev_close(struct inode *, struct file *);
extern struct file_operations def_blk_fops; extern struct file_operations def_blk_fops;
......
...@@ -203,8 +203,6 @@ EXPORT_SYMBOL(notify_change); ...@@ -203,8 +203,6 @@ EXPORT_SYMBOL(notify_change);
EXPORT_SYMBOL(set_blocksize); EXPORT_SYMBOL(set_blocksize);
EXPORT_SYMBOL(sb_set_blocksize); EXPORT_SYMBOL(sb_set_blocksize);
EXPORT_SYMBOL(sb_min_blocksize); EXPORT_SYMBOL(sb_min_blocksize);
EXPORT_SYMBOL(cdget);
EXPORT_SYMBOL(cdput);
EXPORT_SYMBOL(bdget); EXPORT_SYMBOL(bdget);
EXPORT_SYMBOL(bdput); EXPORT_SYMBOL(bdput);
EXPORT_SYMBOL(bd_claim); EXPORT_SYMBOL(bd_claim);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment