Commit 7d7b93c1452f381350dbaf276a63357fa6559e6d
Committed by
Linus Torvalds
1 parent
99f1fe189d
Exists in
master
and in
7 other branches
tty: kref the tty driver object
Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 5 changed files with 80 additions and 58 deletions Side-by-side Diff
drivers/char/ip2/ip2main.c
... | ... | @@ -264,8 +264,8 @@ |
264 | 264 | /**********/ |
265 | 265 | |
266 | 266 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) |
267 | -#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ | |
268 | - tty->name,(pCh->flags),ip2_tty_driver->refcount, \ | |
267 | +#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ | |
268 | + tty->name,(pCh->flags), \ | |
269 | 269 | tty->count,/*GET_USE_COUNT(module)*/0,s) |
270 | 270 | #else |
271 | 271 | #define DBG_CNT(s) |
... | ... | @@ -2893,7 +2893,7 @@ |
2893 | 2893 | case 13: |
2894 | 2894 | switch ( cmd ) { |
2895 | 2895 | case 64: /* Driver - ip2stat */ |
2896 | - rc = put_user(ip2_tty_driver->refcount, pIndex++ ); | |
2896 | + rc = put_user(-1, pIndex++ ); | |
2897 | 2897 | rc = put_user(irq_counter, pIndex++ ); |
2898 | 2898 | rc = put_user(bh_counter, pIndex++ ); |
2899 | 2899 | break; |
drivers/char/pty.c
... | ... | @@ -571,8 +571,11 @@ |
571 | 571 | if (tty_register_driver(pts_driver)) |
572 | 572 | panic("Couldn't register Unix98 pts driver"); |
573 | 573 | |
574 | + /* FIXME: WTF */ | |
575 | +#if 0 | |
574 | 576 | pty_table[1].data = &ptm_driver->refcount; |
575 | - register_sysctl_table(pty_root_table); | |
577 | +#endif | |
578 | + register_sysctl_table(pty_root_table); | |
576 | 579 | |
577 | 580 | /* Now create the /dev/ptmx special device */ |
578 | 581 | tty_default_fops(&ptmx_fops); |
drivers/char/tty_io.c
... | ... | @@ -276,7 +276,7 @@ |
276 | 276 | if (device < base || device >= base + p->num) |
277 | 277 | continue; |
278 | 278 | *index = device - base; |
279 | - return p; | |
279 | + return tty_driver_kref_get(p); | |
280 | 280 | } |
281 | 281 | return NULL; |
282 | 282 | } |
... | ... | @@ -320,7 +320,7 @@ |
320 | 320 | |
321 | 321 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
322 | 322 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { |
323 | - res = p; | |
323 | + res = tty_driver_kref_get(p); | |
324 | 324 | *line = tty_line; |
325 | 325 | break; |
326 | 326 | } |
... | ... | @@ -1410,7 +1410,7 @@ |
1410 | 1410 | *o_ltp_loc = o_ltp; |
1411 | 1411 | o_tty->termios = *o_tp_loc; |
1412 | 1412 | o_tty->termios_locked = *o_ltp_loc; |
1413 | - driver->other->refcount++; | |
1413 | + tty_driver_kref_get(driver->other); | |
1414 | 1414 | if (driver->subtype == PTY_TYPE_MASTER) |
1415 | 1415 | o_tty->count++; |
1416 | 1416 | |
... | ... | @@ -1438,7 +1438,7 @@ |
1438 | 1438 | /* Compatibility until drivers always set this */ |
1439 | 1439 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); |
1440 | 1440 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); |
1441 | - driver->refcount++; | |
1441 | + tty_driver_kref_get(driver); | |
1442 | 1442 | tty->count++; |
1443 | 1443 | |
1444 | 1444 | /* |
... | ... | @@ -1530,8 +1530,7 @@ |
1530 | 1530 | else |
1531 | 1531 | tty_shutdown(tty); |
1532 | 1532 | tty->magic = 0; |
1533 | - /* FIXME: locking on tty->driver->refcount */ | |
1534 | - tty->driver->refcount--; | |
1533 | + tty_driver_kref_put(driver); | |
1535 | 1534 | module_put(driver->owner); |
1536 | 1535 | |
1537 | 1536 | file_list_lock(); |
... | ... | @@ -1854,7 +1853,7 @@ |
1854 | 1853 | mutex_unlock(&tty_mutex); |
1855 | 1854 | return -ENXIO; |
1856 | 1855 | } |
1857 | - driver = tty->driver; | |
1856 | + driver = tty_driver_kref_get(tty->driver); | |
1858 | 1857 | index = tty->index; |
1859 | 1858 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
1860 | 1859 | /* noctty = 1; */ |
1861 | 1860 | |
... | ... | @@ -1865,14 +1864,14 @@ |
1865 | 1864 | #ifdef CONFIG_VT |
1866 | 1865 | if (device == MKDEV(TTY_MAJOR, 0)) { |
1867 | 1866 | extern struct tty_driver *console_driver; |
1868 | - driver = console_driver; | |
1867 | + driver = tty_driver_kref_get(console_driver); | |
1869 | 1868 | index = fg_console; |
1870 | 1869 | noctty = 1; |
1871 | 1870 | goto got_driver; |
1872 | 1871 | } |
1873 | 1872 | #endif |
1874 | 1873 | if (device == MKDEV(TTYAUX_MAJOR, 1)) { |
1875 | - driver = console_device(&index); | |
1874 | + driver = tty_driver_kref_get(console_device(&index)); | |
1876 | 1875 | if (driver) { |
1877 | 1876 | /* Don't let /dev/console block */ |
1878 | 1877 | filp->f_flags |= O_NONBLOCK; |
... | ... | @@ -1891,6 +1890,7 @@ |
1891 | 1890 | got_driver: |
1892 | 1891 | retval = tty_init_dev(driver, index, &tty, 0); |
1893 | 1892 | mutex_unlock(&tty_mutex); |
1893 | + tty_driver_kref_put(driver); | |
1894 | 1894 | if (retval) |
1895 | 1895 | return retval; |
1896 | 1896 | |
... | ... | @@ -2866,7 +2866,6 @@ |
2866 | 2866 | return tty->ops->put_char(tty, ch); |
2867 | 2867 | return tty->ops->write(tty, &ch, 1); |
2868 | 2868 | } |
2869 | - | |
2870 | 2869 | EXPORT_SYMBOL_GPL(tty_put_char); |
2871 | 2870 | |
2872 | 2871 | struct class *tty_class; |
... | ... | @@ -2909,6 +2908,7 @@ |
2909 | 2908 | |
2910 | 2909 | return device_create_drvdata(tty_class, device, dev, NULL, name); |
2911 | 2910 | } |
2911 | +EXPORT_SYMBOL(tty_register_device); | |
2912 | 2912 | |
2913 | 2913 | /** |
2914 | 2914 | * tty_unregister_device - unregister a tty device |
... | ... | @@ -2926,8 +2926,6 @@ |
2926 | 2926 | device_destroy(tty_class, |
2927 | 2927 | MKDEV(driver->major, driver->minor_start) + index); |
2928 | 2928 | } |
2929 | - | |
2930 | -EXPORT_SYMBOL(tty_register_device); | |
2931 | 2929 | EXPORT_SYMBOL(tty_unregister_device); |
2932 | 2930 | |
2933 | 2931 | struct tty_driver *alloc_tty_driver(int lines) |
2934 | 2932 | |
2935 | 2933 | |
2936 | 2934 | |
2937 | 2935 | |
2938 | 2936 | |
2939 | 2937 | |
2940 | 2938 | |
... | ... | @@ -2936,27 +2934,70 @@ |
2936 | 2934 | |
2937 | 2935 | driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); |
2938 | 2936 | if (driver) { |
2937 | + kref_init(&driver->kref); | |
2939 | 2938 | driver->magic = TTY_DRIVER_MAGIC; |
2940 | 2939 | driver->num = lines; |
2941 | 2940 | /* later we'll move allocation of tables here */ |
2942 | 2941 | } |
2943 | 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 | 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 | 2989 | void tty_set_operations(struct tty_driver *driver, |
2952 | 2990 | const struct tty_operations *op) |
2953 | 2991 | { |
2954 | 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 | 3000 | EXPORT_SYMBOL(put_tty_driver); |
2959 | -EXPORT_SYMBOL(tty_set_operations); | |
2960 | 3001 | |
2961 | 3002 | /* |
2962 | 3003 | * Called by a tty driver to register itself. |
... | ... | @@ -2968,9 +3009,6 @@ |
2968 | 3009 | dev_t dev; |
2969 | 3010 | void **p = NULL; |
2970 | 3011 | |
2971 | - if (driver->flags & TTY_DRIVER_INSTALLED) | |
2972 | - return 0; | |
2973 | - | |
2974 | 3012 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { |
2975 | 3013 | p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); |
2976 | 3014 | if (!p) |
... | ... | @@ -3024,6 +3062,7 @@ |
3024 | 3062 | tty_register_device(driver, i, NULL); |
3025 | 3063 | } |
3026 | 3064 | proc_tty_register_driver(driver); |
3065 | + driver->flags |= TTY_DRIVER_INSTALLED; | |
3027 | 3066 | return 0; |
3028 | 3067 | } |
3029 | 3068 | |
3030 | 3069 | |
3031 | 3070 | |
3032 | 3071 | |
... | ... | @@ -3034,46 +3073,19 @@ |
3034 | 3073 | */ |
3035 | 3074 | int tty_unregister_driver(struct tty_driver *driver) |
3036 | 3075 | { |
3037 | - int i; | |
3038 | - struct ktermios *tp; | |
3039 | - void *p; | |
3040 | - | |
3076 | +#if 0 | |
3077 | + /* FIXME */ | |
3041 | 3078 | if (driver->refcount) |
3042 | 3079 | return -EBUSY; |
3043 | - | |
3080 | +#endif | |
3044 | 3081 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), |
3045 | 3082 | driver->num); |
3046 | 3083 | mutex_lock(&tty_mutex); |
3047 | 3084 | list_del(&driver->tty_drivers); |
3048 | 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 | 3086 | return 0; |
3076 | 3087 | } |
3088 | + | |
3077 | 3089 | EXPORT_SYMBOL(tty_unregister_driver); |
3078 | 3090 | |
3079 | 3091 | dev_t tty_devnum(struct tty_struct *tty) |
drivers/net/wan/Kconfig
include/linux/tty_driver.h
... | ... | @@ -253,6 +253,7 @@ |
253 | 253 | |
254 | 254 | struct tty_driver { |
255 | 255 | int magic; /* magic number for this structure */ |
256 | + struct kref kref; /* Reference management */ | |
256 | 257 | struct cdev cdev; |
257 | 258 | struct module *owner; |
258 | 259 | const char *driver_name; |
... | ... | @@ -266,7 +267,6 @@ |
266 | 267 | short subtype; /* subtype of tty driver */ |
267 | 268 | struct ktermios init_termios; /* Initial termios */ |
268 | 269 | int flags; /* tty driver flags */ |
269 | - int refcount; /* for loadable tty drivers */ | |
270 | 270 | struct proc_dir_entry *proc_entry; /* /proc fs entry */ |
271 | 271 | struct tty_driver *other; /* only used for the PTY driver */ |
272 | 272 | |
273 | 273 | |
... | ... | @@ -288,11 +288,18 @@ |
288 | 288 | |
289 | 289 | extern struct list_head tty_drivers; |
290 | 290 | |
291 | -struct tty_driver *alloc_tty_driver(int lines); | |
292 | -void put_tty_driver(struct tty_driver *driver); | |
293 | -void tty_set_operations(struct tty_driver *driver, | |
291 | +extern struct tty_driver *alloc_tty_driver(int lines); | |
292 | +extern void put_tty_driver(struct tty_driver *driver); | |
293 | +extern void tty_set_operations(struct tty_driver *driver, | |
294 | 294 | const struct tty_operations *op); |
295 | 295 | extern struct tty_driver *tty_find_polling_driver(char *name, int *line); |
296 | + | |
297 | +extern void tty_driver_kref_put(struct tty_driver *driver); | |
298 | +extern inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d) | |
299 | +{ | |
300 | + kref_get(&d->kref); | |
301 | + return d; | |
302 | +} | |
296 | 303 | |
297 | 304 | /* tty driver magic number */ |
298 | 305 | #define TTY_DRIVER_MAGIC 0x5402 |