diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:42:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:42 -0400 |
commit | 7d7b93c1452f381350dbaf276a63357fa6559e6d (patch) | |
tree | 02ce0c37e7fea66d1e8af20111d92171bfc0ff1d /drivers/char/tty_io.c | |
parent | 99f1fe189daf8e99a847e420567e49dd7ee2aae7 (diff) |
tty: kref the tty driver object
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 110 |
1 files changed, 61 insertions, 49 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index ac41af8763d1..47aa437effe2 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -276,7 +276,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index) | |||
276 | if (device < base || device >= base + p->num) | 276 | if (device < base || device >= base + p->num) |
277 | continue; | 277 | continue; |
278 | *index = device - base; | 278 | *index = device - base; |
279 | return p; | 279 | return tty_driver_kref_get(p); |
280 | } | 280 | } |
281 | return NULL; | 281 | return NULL; |
282 | } | 282 | } |
@@ -320,7 +320,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
320 | 320 | ||
321 | if (tty_line >= 0 && tty_line <= p->num && p->ops && | 321 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
322 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { | 322 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { |
323 | res = p; | 323 | res = tty_driver_kref_get(p); |
324 | *line = tty_line; | 324 | *line = tty_line; |
325 | break; | 325 | break; |
326 | } | 326 | } |
@@ -1410,7 +1410,7 @@ int tty_init_dev(struct tty_driver *driver, int idx, | |||
1410 | *o_ltp_loc = o_ltp; | 1410 | *o_ltp_loc = o_ltp; |
1411 | o_tty->termios = *o_tp_loc; | 1411 | o_tty->termios = *o_tp_loc; |
1412 | o_tty->termios_locked = *o_ltp_loc; | 1412 | o_tty->termios_locked = *o_ltp_loc; |
1413 | driver->other->refcount++; | 1413 | tty_driver_kref_get(driver->other); |
1414 | if (driver->subtype == PTY_TYPE_MASTER) | 1414 | if (driver->subtype == PTY_TYPE_MASTER) |
1415 | o_tty->count++; | 1415 | o_tty->count++; |
1416 | 1416 | ||
@@ -1438,7 +1438,7 @@ int tty_init_dev(struct tty_driver *driver, int idx, | |||
1438 | /* Compatibility until drivers always set this */ | 1438 | /* Compatibility until drivers always set this */ |
1439 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | 1439 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); |
1440 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | 1440 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); |
1441 | driver->refcount++; | 1441 | tty_driver_kref_get(driver); |
1442 | tty->count++; | 1442 | tty->count++; |
1443 | 1443 | ||
1444 | /* | 1444 | /* |
@@ -1530,8 +1530,7 @@ static void release_one_tty(struct kref *kref) | |||
1530 | else | 1530 | else |
1531 | tty_shutdown(tty); | 1531 | tty_shutdown(tty); |
1532 | tty->magic = 0; | 1532 | tty->magic = 0; |
1533 | /* FIXME: locking on tty->driver->refcount */ | 1533 | tty_driver_kref_put(driver); |
1534 | tty->driver->refcount--; | ||
1535 | module_put(driver->owner); | 1534 | module_put(driver->owner); |
1536 | 1535 | ||
1537 | file_list_lock(); | 1536 | file_list_lock(); |
@@ -1854,7 +1853,7 @@ retry_open: | |||
1854 | mutex_unlock(&tty_mutex); | 1853 | mutex_unlock(&tty_mutex); |
1855 | return -ENXIO; | 1854 | return -ENXIO; |
1856 | } | 1855 | } |
1857 | driver = tty->driver; | 1856 | driver = tty_driver_kref_get(tty->driver); |
1858 | index = tty->index; | 1857 | index = tty->index; |
1859 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ | 1858 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
1860 | /* noctty = 1; */ | 1859 | /* noctty = 1; */ |
@@ -1865,14 +1864,14 @@ retry_open: | |||
1865 | #ifdef CONFIG_VT | 1864 | #ifdef CONFIG_VT |
1866 | if (device == MKDEV(TTY_MAJOR, 0)) { | 1865 | if (device == MKDEV(TTY_MAJOR, 0)) { |
1867 | extern struct tty_driver *console_driver; | 1866 | extern struct tty_driver *console_driver; |
1868 | driver = console_driver; | 1867 | driver = tty_driver_kref_get(console_driver); |
1869 | index = fg_console; | 1868 | index = fg_console; |
1870 | noctty = 1; | 1869 | noctty = 1; |
1871 | goto got_driver; | 1870 | goto got_driver; |
1872 | } | 1871 | } |
1873 | #endif | 1872 | #endif |
1874 | if (device == MKDEV(TTYAUX_MAJOR, 1)) { | 1873 | if (device == MKDEV(TTYAUX_MAJOR, 1)) { |
1875 | driver = console_device(&index); | 1874 | driver = tty_driver_kref_get(console_device(&index)); |
1876 | if (driver) { | 1875 | if (driver) { |
1877 | /* Don't let /dev/console block */ | 1876 | /* Don't let /dev/console block */ |
1878 | filp->f_flags |= O_NONBLOCK; | 1877 | filp->f_flags |= O_NONBLOCK; |
@@ -1891,6 +1890,7 @@ retry_open: | |||
1891 | got_driver: | 1890 | got_driver: |
1892 | retval = tty_init_dev(driver, index, &tty, 0); | 1891 | retval = tty_init_dev(driver, index, &tty, 0); |
1893 | mutex_unlock(&tty_mutex); | 1892 | mutex_unlock(&tty_mutex); |
1893 | tty_driver_kref_put(driver); | ||
1894 | if (retval) | 1894 | if (retval) |
1895 | return retval; | 1895 | return retval; |
1896 | 1896 | ||
@@ -2866,7 +2866,6 @@ int tty_put_char(struct tty_struct *tty, unsigned char ch) | |||
2866 | return tty->ops->put_char(tty, ch); | 2866 | return tty->ops->put_char(tty, ch); |
2867 | return tty->ops->write(tty, &ch, 1); | 2867 | return tty->ops->write(tty, &ch, 1); |
2868 | } | 2868 | } |
2869 | |||
2870 | EXPORT_SYMBOL_GPL(tty_put_char); | 2869 | EXPORT_SYMBOL_GPL(tty_put_char); |
2871 | 2870 | ||
2872 | struct class *tty_class; | 2871 | struct class *tty_class; |
@@ -2909,6 +2908,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, | |||
2909 | 2908 | ||
2910 | return device_create_drvdata(tty_class, device, dev, NULL, name); | 2909 | return device_create_drvdata(tty_class, device, dev, NULL, name); |
2911 | } | 2910 | } |
2911 | EXPORT_SYMBOL(tty_register_device); | ||
2912 | 2912 | ||
2913 | /** | 2913 | /** |
2914 | * tty_unregister_device - unregister a tty device | 2914 | * tty_unregister_device - unregister a tty device |
@@ -2926,8 +2926,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index) | |||
2926 | device_destroy(tty_class, | 2926 | device_destroy(tty_class, |
2927 | MKDEV(driver->major, driver->minor_start) + index); | 2927 | MKDEV(driver->major, driver->minor_start) + index); |
2928 | } | 2928 | } |
2929 | |||
2930 | EXPORT_SYMBOL(tty_register_device); | ||
2931 | EXPORT_SYMBOL(tty_unregister_device); | 2929 | EXPORT_SYMBOL(tty_unregister_device); |
2932 | 2930 | ||
2933 | struct tty_driver *alloc_tty_driver(int lines) | 2931 | struct tty_driver *alloc_tty_driver(int lines) |
@@ -2936,27 +2934,70 @@ struct tty_driver *alloc_tty_driver(int lines) | |||
2936 | 2934 | ||
2937 | driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); | 2935 | driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); |
2938 | if (driver) { | 2936 | if (driver) { |
2937 | kref_init(&driver->kref); | ||
2939 | driver->magic = TTY_DRIVER_MAGIC; | 2938 | driver->magic = TTY_DRIVER_MAGIC; |
2940 | driver->num = lines; | 2939 | driver->num = lines; |
2941 | /* later we'll move allocation of tables here */ | 2940 | /* later we'll move allocation of tables here */ |
2942 | } | 2941 | } |
2943 | return driver; | 2942 | return driver; |
2944 | } | 2943 | } |
2944 | EXPORT_SYMBOL(alloc_tty_driver); | ||
2945 | 2945 | ||
2946 | void put_tty_driver(struct tty_driver *driver) | 2946 | static void destruct_tty_driver(struct kref *kref) |
2947 | { | 2947 | { |
2948 | struct tty_driver *driver = container_of(kref, struct tty_driver, kref); | ||
2949 | int i; | ||
2950 | struct ktermios *tp; | ||
2951 | void *p; | ||
2952 | |||
2953 | if (driver->flags & TTY_DRIVER_INSTALLED) { | ||
2954 | /* | ||
2955 | * Free the termios and termios_locked structures because | ||
2956 | * we don't want to get memory leaks when modular tty | ||
2957 | * drivers are removed from the kernel. | ||
2958 | */ | ||
2959 | for (i = 0; i < driver->num; i++) { | ||
2960 | tp = driver->termios[i]; | ||
2961 | if (tp) { | ||
2962 | driver->termios[i] = NULL; | ||
2963 | kfree(tp); | ||
2964 | } | ||
2965 | tp = driver->termios_locked[i]; | ||
2966 | if (tp) { | ||
2967 | driver->termios_locked[i] = NULL; | ||
2968 | kfree(tp); | ||
2969 | } | ||
2970 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) | ||
2971 | tty_unregister_device(driver, i); | ||
2972 | } | ||
2973 | p = driver->ttys; | ||
2974 | proc_tty_unregister_driver(driver); | ||
2975 | driver->ttys = NULL; | ||
2976 | driver->termios = driver->termios_locked = NULL; | ||
2977 | kfree(p); | ||
2978 | cdev_del(&driver->cdev); | ||
2979 | } | ||
2948 | kfree(driver); | 2980 | kfree(driver); |
2949 | } | 2981 | } |
2950 | 2982 | ||
2983 | void tty_driver_kref_put(struct tty_driver *driver) | ||
2984 | { | ||
2985 | kref_put(&driver->kref, destruct_tty_driver); | ||
2986 | } | ||
2987 | EXPORT_SYMBOL(tty_driver_kref_put); | ||
2988 | |||
2951 | void tty_set_operations(struct tty_driver *driver, | 2989 | void tty_set_operations(struct tty_driver *driver, |
2952 | const struct tty_operations *op) | 2990 | const struct tty_operations *op) |
2953 | { | 2991 | { |
2954 | driver->ops = op; | 2992 | driver->ops = op; |
2955 | }; | 2993 | }; |
2994 | EXPORT_SYMBOL(tty_set_operations); | ||
2956 | 2995 | ||
2957 | EXPORT_SYMBOL(alloc_tty_driver); | 2996 | void put_tty_driver(struct tty_driver *d) |
2997 | { | ||
2998 | tty_driver_kref_put(d); | ||
2999 | } | ||
2958 | EXPORT_SYMBOL(put_tty_driver); | 3000 | EXPORT_SYMBOL(put_tty_driver); |
2959 | EXPORT_SYMBOL(tty_set_operations); | ||
2960 | 3001 | ||
2961 | /* | 3002 | /* |
2962 | * Called by a tty driver to register itself. | 3003 | * Called by a tty driver to register itself. |
@@ -2968,9 +3009,6 @@ int tty_register_driver(struct tty_driver *driver) | |||
2968 | dev_t dev; | 3009 | dev_t dev; |
2969 | void **p = NULL; | 3010 | void **p = NULL; |
2970 | 3011 | ||
2971 | if (driver->flags & TTY_DRIVER_INSTALLED) | ||
2972 | return 0; | ||
2973 | |||
2974 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { | 3012 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { |
2975 | p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); | 3013 | p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); |
2976 | if (!p) | 3014 | if (!p) |
@@ -3024,6 +3062,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
3024 | tty_register_device(driver, i, NULL); | 3062 | tty_register_device(driver, i, NULL); |
3025 | } | 3063 | } |
3026 | proc_tty_register_driver(driver); | 3064 | proc_tty_register_driver(driver); |
3065 | driver->flags |= TTY_DRIVER_INSTALLED; | ||
3027 | return 0; | 3066 | return 0; |
3028 | } | 3067 | } |
3029 | 3068 | ||
@@ -3034,46 +3073,19 @@ EXPORT_SYMBOL(tty_register_driver); | |||
3034 | */ | 3073 | */ |
3035 | int tty_unregister_driver(struct tty_driver *driver) | 3074 | int tty_unregister_driver(struct tty_driver *driver) |
3036 | { | 3075 | { |
3037 | int i; | 3076 | #if 0 |
3038 | struct ktermios *tp; | 3077 | /* FIXME */ |
3039 | void *p; | ||
3040 | |||
3041 | if (driver->refcount) | 3078 | if (driver->refcount) |
3042 | return -EBUSY; | 3079 | return -EBUSY; |
3043 | 3080 | #endif | |
3044 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), | 3081 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), |
3045 | driver->num); | 3082 | driver->num); |
3046 | mutex_lock(&tty_mutex); | 3083 | mutex_lock(&tty_mutex); |
3047 | list_del(&driver->tty_drivers); | 3084 | list_del(&driver->tty_drivers); |
3048 | mutex_unlock(&tty_mutex); | 3085 | mutex_unlock(&tty_mutex); |
3049 | |||
3050 | /* | ||
3051 | * Free the termios and termios_locked structures because | ||
3052 | * we don't want to get memory leaks when modular tty | ||
3053 | * drivers are removed from the kernel. | ||
3054 | */ | ||
3055 | for (i = 0; i < driver->num; i++) { | ||
3056 | tp = driver->termios[i]; | ||
3057 | if (tp) { | ||
3058 | driver->termios[i] = NULL; | ||
3059 | kfree(tp); | ||
3060 | } | ||
3061 | tp = driver->termios_locked[i]; | ||
3062 | if (tp) { | ||
3063 | driver->termios_locked[i] = NULL; | ||
3064 | kfree(tp); | ||
3065 | } | ||
3066 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) | ||
3067 | tty_unregister_device(driver, i); | ||
3068 | } | ||
3069 | p = driver->ttys; | ||
3070 | proc_tty_unregister_driver(driver); | ||
3071 | driver->ttys = NULL; | ||
3072 | driver->termios = driver->termios_locked = NULL; | ||
3073 | kfree(p); | ||
3074 | cdev_del(&driver->cdev); | ||
3075 | return 0; | 3086 | return 0; |
3076 | } | 3087 | } |
3088 | |||
3077 | EXPORT_SYMBOL(tty_unregister_driver); | 3089 | EXPORT_SYMBOL(tty_unregister_driver); |
3078 | 3090 | ||
3079 | dev_t tty_devnum(struct tty_struct *tty) | 3091 | dev_t tty_devnum(struct tty_struct *tty) |