diff options
-rw-r--r-- | drivers/tty/vt/vt.c | 14 | ||||
-rw-r--r-- | drivers/tty/vt/vt_ioctl.c | 67 | ||||
-rw-r--r-- | include/linux/vt_kern.h | 2 |
3 files changed, 56 insertions, 27 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index fbd447b390f7..740202d8a5c4 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -779,7 +779,6 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
779 | con_set_default_unimap(vc); | 779 | con_set_default_unimap(vc); |
780 | vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); | 780 | vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); |
781 | if (!vc->vc_screenbuf) { | 781 | if (!vc->vc_screenbuf) { |
782 | tty_port_destroy(&vc->port); | ||
783 | kfree(vc); | 782 | kfree(vc); |
784 | vc_cons[currcons].d = NULL; | 783 | vc_cons[currcons].d = NULL; |
785 | return -ENOMEM; | 784 | return -ENOMEM; |
@@ -986,26 +985,25 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws) | |||
986 | return ret; | 985 | return ret; |
987 | } | 986 | } |
988 | 987 | ||
989 | void vc_deallocate(unsigned int currcons) | 988 | struct vc_data *vc_deallocate(unsigned int currcons) |
990 | { | 989 | { |
990 | struct vc_data *vc = NULL; | ||
991 | |||
991 | WARN_CONSOLE_UNLOCKED(); | 992 | WARN_CONSOLE_UNLOCKED(); |
992 | 993 | ||
993 | if (vc_cons_allocated(currcons)) { | 994 | if (vc_cons_allocated(currcons)) { |
994 | struct vc_data *vc = vc_cons[currcons].d; | 995 | struct vt_notifier_param param; |
995 | struct vt_notifier_param param = { .vc = vc }; | ||
996 | 996 | ||
997 | param.vc = vc = vc_cons[currcons].d; | ||
997 | atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); | 998 | atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); |
998 | vcs_remove_sysfs(currcons); | 999 | vcs_remove_sysfs(currcons); |
999 | vc->vc_sw->con_deinit(vc); | 1000 | vc->vc_sw->con_deinit(vc); |
1000 | put_pid(vc->vt_pid); | 1001 | put_pid(vc->vt_pid); |
1001 | module_put(vc->vc_sw->owner); | 1002 | module_put(vc->vc_sw->owner); |
1002 | kfree(vc->vc_screenbuf); | 1003 | kfree(vc->vc_screenbuf); |
1003 | if (currcons >= MIN_NR_CONSOLES) { | ||
1004 | tty_port_destroy(&vc->port); | ||
1005 | kfree(vc); | ||
1006 | } | ||
1007 | vc_cons[currcons].d = NULL; | 1004 | vc_cons[currcons].d = NULL; |
1008 | } | 1005 | } |
1006 | return vc; | ||
1009 | } | 1007 | } |
1010 | 1008 | ||
1011 | /* | 1009 | /* |
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 98ff1735eafc..fc2c06c66e89 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c | |||
@@ -283,6 +283,51 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_ | |||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | /* deallocate a single console, if possible (leave 0) */ | ||
287 | static int vt_disallocate(unsigned int vc_num) | ||
288 | { | ||
289 | struct vc_data *vc = NULL; | ||
290 | int ret = 0; | ||
291 | |||
292 | if (!vc_num) | ||
293 | return 0; | ||
294 | |||
295 | console_lock(); | ||
296 | if (VT_BUSY(vc_num)) | ||
297 | ret = -EBUSY; | ||
298 | else | ||
299 | vc = vc_deallocate(vc_num); | ||
300 | console_unlock(); | ||
301 | |||
302 | if (vc && vc_num >= MIN_NR_CONSOLES) { | ||
303 | tty_port_destroy(&vc->port); | ||
304 | kfree(vc); | ||
305 | } | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | /* deallocate all unused consoles, but leave 0 */ | ||
311 | static void vt_disallocate_all(void) | ||
312 | { | ||
313 | struct vc_data *vc[MAX_NR_CONSOLES]; | ||
314 | int i; | ||
315 | |||
316 | console_lock(); | ||
317 | for (i = 1; i < MAX_NR_CONSOLES; i++) | ||
318 | if (!VT_BUSY(i)) | ||
319 | vc[i] = vc_deallocate(i); | ||
320 | else | ||
321 | vc[i] = NULL; | ||
322 | console_unlock(); | ||
323 | |||
324 | for (i = 1; i < MAX_NR_CONSOLES; i++) { | ||
325 | if (vc[i] && i >= MIN_NR_CONSOLES) { | ||
326 | tty_port_destroy(&vc[i]->port); | ||
327 | kfree(vc[i]); | ||
328 | } | ||
329 | } | ||
330 | } | ||
286 | 331 | ||
287 | 332 | ||
288 | /* | 333 | /* |
@@ -769,24 +814,10 @@ int vt_ioctl(struct tty_struct *tty, | |||
769 | ret = -ENXIO; | 814 | ret = -ENXIO; |
770 | break; | 815 | break; |
771 | } | 816 | } |
772 | if (arg == 0) { | 817 | if (arg == 0) |
773 | /* deallocate all unused consoles, but leave 0 */ | 818 | vt_disallocate_all(); |
774 | console_lock(); | 819 | else |
775 | for (i=1; i<MAX_NR_CONSOLES; i++) | 820 | ret = vt_disallocate(--arg); |
776 | if (! VT_BUSY(i)) | ||
777 | vc_deallocate(i); | ||
778 | console_unlock(); | ||
779 | } else { | ||
780 | /* deallocate a single console, if possible */ | ||
781 | arg--; | ||
782 | if (VT_BUSY(arg)) | ||
783 | ret = -EBUSY; | ||
784 | else if (arg) { /* leave 0 */ | ||
785 | console_lock(); | ||
786 | vc_deallocate(arg); | ||
787 | console_unlock(); | ||
788 | } | ||
789 | } | ||
790 | break; | 821 | break; |
791 | 822 | ||
792 | case VT_RESIZE: | 823 | case VT_RESIZE: |
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index e8d65718560b..0d33fca48774 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
@@ -36,7 +36,7 @@ extern int fg_console, last_console, want_console; | |||
36 | int vc_allocate(unsigned int console); | 36 | int vc_allocate(unsigned int console); |
37 | int vc_cons_allocated(unsigned int console); | 37 | int vc_cons_allocated(unsigned int console); |
38 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); | 38 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); |
39 | void vc_deallocate(unsigned int console); | 39 | struct vc_data *vc_deallocate(unsigned int console); |
40 | void reset_palette(struct vc_data *vc); | 40 | void reset_palette(struct vc_data *vc); |
41 | void do_blank_screen(int entering_gfx); | 41 | void do_blank_screen(int entering_gfx); |
42 | void do_unblank_screen(int leaving_gfx); | 42 | void do_unblank_screen(int leaving_gfx); |