aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/vt.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-10-13 05:41:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-13 12:51:42 -0400
commitfeebed6515a113eeb33919e9557a8b9710ea627c (patch)
tree0461178ee0c5e16ea90023e4b6386cb5c57d3391 /drivers/char/vt.c
parentbf7a06bcce205705ea5c7675cbb8ea9239ea30a0 (diff)
tty: shutdown method
Right now there are various drivers that try to use tty->count to know when they get the final close. Aristeau Rozanski showed while debugging the vt sysfs race that this isn't entirely safe. Instead of driver side tricks to work around this introduce a shutdown which is called when the tty is being destructed. This also means that the shutdown method is tied into the refcounting. Use this to rework the console close/sysfs logic. Remove lots of special case code from the tty core code. The pty code can now have a shutdown() method that replaces the special case hackery in the tree free up paths. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/vt.c')
-rw-r--r--drivers/char/vt.c34
1 files changed, 17 insertions, 17 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index ec94521c3118..37a45db5bae0 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2758,6 +2758,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2758 ret = vc_allocate(currcons); 2758 ret = vc_allocate(currcons);
2759 if (ret == 0) { 2759 if (ret == 0) {
2760 struct vc_data *vc = vc_cons[currcons].d; 2760 struct vc_data *vc = vc_cons[currcons].d;
2761
2762 /* Still being freed */
2763 if (vc->vc_tty) {
2764 release_console_sem();
2765 return -ERESTARTSYS;
2766 }
2761 tty->driver_data = vc; 2767 tty->driver_data = vc;
2762 vc->vc_tty = tty; 2768 vc->vc_tty = tty;
2763 2769
@@ -2787,25 +2793,18 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2787 */ 2793 */
2788static void con_close(struct tty_struct *tty, struct file *filp) 2794static void con_close(struct tty_struct *tty, struct file *filp)
2789{ 2795{
2790 mutex_lock(&tty_mutex); 2796 /* Nothing to do - we defer to shutdown */
2791 acquire_console_sem(); 2797}
2792 if (tty && tty->count == 1) {
2793 struct vc_data *vc = tty->driver_data;
2794 2798
2795 if (vc) 2799static void con_shutdown(struct tty_struct *tty)
2796 vc->vc_tty = NULL; 2800{
2797 tty->driver_data = NULL; 2801 struct vc_data *vc = tty->driver_data;
2798 vcs_remove_sysfs(tty); 2802 BUG_ON(vc == NULL);
2799 release_console_sem(); 2803 acquire_console_sem();
2800 mutex_unlock(&tty_mutex); 2804 vc->vc_tty = NULL;
2801 /* 2805 vcs_remove_sysfs(tty);
2802 * tty_mutex is released, but we still hold BKL, so there is
2803 * still exclusion against init_dev()
2804 */
2805 return;
2806 }
2807 release_console_sem(); 2806 release_console_sem();
2808 mutex_unlock(&tty_mutex); 2807 tty_shutdown(tty);
2809} 2808}
2810 2809
2811static int default_italic_color = 2; // green (ASCII) 2810static int default_italic_color = 2; // green (ASCII)
@@ -2930,6 +2929,7 @@ static const struct tty_operations con_ops = {
2930 .throttle = con_throttle, 2929 .throttle = con_throttle,
2931 .unthrottle = con_unthrottle, 2930 .unthrottle = con_unthrottle,
2932 .resize = vt_resize, 2931 .resize = vt_resize,
2932 .shutdown = con_shutdown
2933}; 2933};
2934 2934
2935int __init vty_init(void) 2935int __init vty_init(void)