Commit 4460bbfd authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] register_chrdev_region() cleanup

register_chrdev_region() sanitized, code in tty_io.c that dealt with it
cleaned up.
parent 106a92d1
...@@ -2242,53 +2242,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index) ...@@ -2242,53 +2242,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
EXPORT_SYMBOL(tty_register_device); EXPORT_SYMBOL(tty_register_device);
EXPORT_SYMBOL(tty_unregister_device); EXPORT_SYMBOL(tty_unregister_device);
/* that should be handled by register_chrdev_region() */
static int get_range(struct tty_driver *driver)
{
dev_t from = MKDEV(driver->major, driver->minor_start);
dev_t to = from + driver->num;
dev_t n, next;
int error = 0;
for (n = from; MAJOR(n) < MAJOR(to); n = next) {
next = MKDEV(MAJOR(n)+1, 0);
error = register_chrdev_region(MAJOR(n), MINOR(n),
next - n, driver->name, &tty_fops);
if (error)
goto fail;
}
if (n != to)
error = register_chrdev_region(MAJOR(n), MINOR(n),
to - n, driver->name, &tty_fops);
if (!error)
return 0;
fail:
to = n;
for (n = from; MAJOR(n) < MAJOR(to); n = next) {
next = MKDEV(MAJOR(n)+1, 0);
unregister_chrdev_region(MAJOR(n), MINOR(n),
next - n, driver->name);
}
return error;
}
/* that should be handled by unregister_chrdev_region() */
static void put_range(struct tty_driver *driver)
{
dev_t from = MKDEV(driver->major, driver->minor_start);
dev_t to = from + driver->num;
dev_t n, next;
for (n = from; MAJOR(n) < MAJOR(to); n = next) {
next = MKDEV(MAJOR(n)+1, 0);
unregister_chrdev_region(MAJOR(n), MINOR(n),
next - n, driver->name);
}
if (n != to)
unregister_chrdev_region(MAJOR(n), MINOR(n),
to - n, driver->name);
}
/* /*
* Called by a tty driver to register itself. * Called by a tty driver to register itself.
*/ */
...@@ -2296,17 +2249,22 @@ int tty_register_driver(struct tty_driver *driver) ...@@ -2296,17 +2249,22 @@ int tty_register_driver(struct tty_driver *driver)
{ {
int error; int error;
int i; int i;
dev_t dev;
if (driver->flags & TTY_DRIVER_INSTALLED) if (driver->flags & TTY_DRIVER_INSTALLED)
return 0; return 0;
if (!driver->major) { if (!driver->major) {
error = register_chrdev_region(0, driver->minor_start, error = alloc_chrdev_region(&dev, driver->num,
driver->num, driver->name, &tty_fops); (char*)driver->name, &tty_fops);
if (error > 0) if (!error) {
driver->major = error; driver->major = MAJOR(dev);
driver->minor_start = MINOR(dev);
}
} else { } else {
error = get_range(driver); dev = MKDEV(driver->major, driver->minor_start);
error = register_chrdev_region(dev, driver->num,
(char*)driver->name, &tty_fops);
} }
if (error < 0) if (error < 0)
return error; return error;
...@@ -2335,7 +2293,8 @@ int tty_unregister_driver(struct tty_driver *driver) ...@@ -2335,7 +2293,8 @@ int tty_unregister_driver(struct tty_driver *driver)
if (*driver->refcount) if (*driver->refcount)
return -EBUSY; return -EBUSY;
put_range(driver); unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
driver->num);
list_del(&driver->tty_drivers); list_del(&driver->tty_drivers);
...@@ -2412,20 +2371,20 @@ postcore_initcall(tty_class_init); ...@@ -2412,20 +2371,20 @@ postcore_initcall(tty_class_init);
*/ */
void __init tty_init(void) void __init tty_init(void)
{ {
if (register_chrdev_region(TTYAUX_MAJOR, 0, 1, if (register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1,
"/dev/tty", &tty_fops) < 0) "/dev/tty", &tty_fops) < 0)
panic("Couldn't register /dev/tty driver\n"); panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL); tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
if (register_chrdev_region(TTYAUX_MAJOR, 1, 1, if (register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1,
"/dev/console", &tty_fops) < 0) "/dev/console", &tty_fops) < 0)
panic("Couldn't register /dev/console driver\n"); panic("Couldn't register /dev/console driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL); tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL);
#ifdef CONFIG_UNIX98_PTYS #ifdef CONFIG_UNIX98_PTYS
if (register_chrdev_region(TTYAUX_MAJOR, 2, 1, if (register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1,
"/dev/ptmx", &tty_fops) < 0) "/dev/ptmx", &tty_fops) < 0)
panic("Couldn't register /dev/ptmx driver\n"); panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
...@@ -2433,7 +2392,7 @@ void __init tty_init(void) ...@@ -2433,7 +2392,7 @@ void __init tty_init(void)
#endif #endif
#ifdef CONFIG_VT #ifdef CONFIG_VT
if (register_chrdev_region(TTY_MAJOR, 0, 1, if (register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1,
"/dev/vc/0", &tty_fops) < 0) "/dev/vc/0", &tty_fops) < 0)
panic("Couldn't register /dev/tty0 driver\n"); panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
......
...@@ -123,7 +123,8 @@ get_chrfops(unsigned int major, unsigned int minor) ...@@ -123,7 +123,8 @@ get_chrfops(unsigned int major, unsigned int minor)
* *
* Returns a -ve errno on failure. * Returns a -ve errno on failure.
*/ */
int register_chrdev_region(unsigned int major, unsigned int baseminor, static struct char_device_struct *
__register_chrdev_region(unsigned int major, unsigned int baseminor,
int minorct, const char *name, int minorct, const char *name,
struct file_operations *fops) struct file_operations *fops)
{ {
...@@ -133,7 +134,7 @@ int register_chrdev_region(unsigned int major, unsigned int baseminor, ...@@ -133,7 +134,7 @@ int register_chrdev_region(unsigned int major, unsigned int baseminor,
cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL); cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL);
if (cd == NULL) if (cd == NULL)
return -ENOMEM; return ERR_PTR(-ENOMEM);
write_lock_irq(&chrdevs_lock); write_lock_irq(&chrdevs_lock);
...@@ -167,32 +168,23 @@ int register_chrdev_region(unsigned int major, unsigned int baseminor, ...@@ -167,32 +168,23 @@ int register_chrdev_region(unsigned int major, unsigned int baseminor,
if (*cp && (*cp)->major == major && if (*cp && (*cp)->major == major &&
(*cp)->baseminor < baseminor + minorct) { (*cp)->baseminor < baseminor + minorct) {
ret = -EBUSY; ret = -EBUSY;
} else { goto out;
}
cd->next = *cp; cd->next = *cp;
*cp = cd; *cp = cd;
} write_unlock_irq(&chrdevs_lock);
return cd;
out: out:
write_unlock_irq(&chrdevs_lock); write_unlock_irq(&chrdevs_lock);
if (ret < 0)
kfree(cd); kfree(cd);
return ret; return ERR_PTR(ret);
}
int register_chrdev(unsigned int major, const char *name,
struct file_operations *fops)
{
return register_chrdev_region(major, 0, 256, name, fops);
} }
/* todo: make void - error printk here */ static struct char_device_struct *
int unregister_chrdev_region(unsigned int major, unsigned int baseminor, __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
int minorct, const char *name)
{ {
struct char_device_struct *cd, **cp; struct char_device_struct *cd = NULL, **cp;
int ret = 0; int i = major_to_index(major);
int i;
i = major_to_index(major);
write_lock_irq(&chrdevs_lock); write_lock_irq(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
...@@ -200,21 +192,79 @@ int unregister_chrdev_region(unsigned int major, unsigned int baseminor, ...@@ -200,21 +192,79 @@ int unregister_chrdev_region(unsigned int major, unsigned int baseminor,
(*cp)->baseminor == baseminor && (*cp)->baseminor == baseminor &&
(*cp)->minorct == minorct) (*cp)->minorct == minorct)
break; break;
if (!*cp || strcmp((*cp)->name, name)) if (*cp) {
ret = -EINVAL;
else {
cd = *cp; cd = *cp;
*cp = cd->next; *cp = cd->next;
kfree(cd);
} }
write_unlock_irq(&chrdevs_lock); write_unlock_irq(&chrdevs_lock);
return cd;
}
return ret; int register_chrdev_region(dev_t from, unsigned count, char *name,
struct file_operations *fops)
{
struct char_device_struct *cd;
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
cd = __register_chrdev_region(MAJOR(n), MINOR(n),
next - n, name, fops);
if (IS_ERR(cd))
goto fail;
}
return 0;
fail:
to = n;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
return PTR_ERR(cd);
}
int alloc_chrdev_region(dev_t *dev, unsigned count, char *name,
struct file_operations *fops)
{
struct char_device_struct *cd;
cd = __register_chrdev_region(0, 0, count, name, fops);
if (IS_ERR(cd))
return PTR_ERR(cd);
*dev = MKDEV(cd->major, cd->baseminor);
return 0;
}
int register_chrdev(unsigned int major, const char *name,
struct file_operations *fops)
{
struct char_device_struct *cd;
cd = __register_chrdev_region(major, 0, 256, name, fops);
if (IS_ERR(cd))
return PTR_ERR(cd);
return cd->major;
}
void unregister_chrdev_region(dev_t from, unsigned count)
{
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
} }
int unregister_chrdev(unsigned int major, const char *name) int unregister_chrdev(unsigned int major, const char *name)
{ {
return unregister_chrdev_region(major, 0, 256, name); kfree(__unregister_chrdev_region(major, 0, 256));
return 0;
} }
/* /*
......
...@@ -1056,13 +1056,14 @@ extern void bd_release(struct block_device *); ...@@ -1056,13 +1056,14 @@ extern void bd_release(struct block_device *);
extern void blk_run_queues(void); extern void blk_run_queues(void);
/* fs/char_dev.c */ /* fs/char_dev.c */
extern int register_chrdev_region(unsigned int, unsigned int, int, extern int alloc_chrdev_region(dev_t *, unsigned, char *,
const char *, struct file_operations *); struct file_operations *);
extern int register_chrdev_region(dev_t, unsigned, char *,
struct file_operations *);
extern int register_chrdev(unsigned int, const char *, extern int register_chrdev(unsigned int, const char *,
struct file_operations *); struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *); extern int unregister_chrdev(unsigned int, const char *);
extern int unregister_chrdev_region(unsigned int, unsigned int, int, extern void unregister_chrdev_region(dev_t, unsigned);
const char *);
extern int chrdev_open(struct inode *, struct file *); extern int chrdev_open(struct inode *, struct file *);
/* fs/block_dev.c */ /* fs/block_dev.c */
......
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