3939#include <linux/kbd_diacr.h>
4040#include <linux/selection.h>
4141
42- char vt_dont_switch ;
43- extern struct tty_driver * console_driver ;
42+ bool vt_dont_switch ;
4443
45- #define VT_IS_IN_USE (i ) (console_driver->ttys[i] && console_driver->ttys[i]->count)
46- #define VT_BUSY (i ) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
44+ static inline bool vt_in_use (unsigned int i )
45+ {
46+ const struct vc_data * vc = vc_cons [i ].d ;
47+
48+ /*
49+ * console_lock must be held to prevent the vc from being deallocated
50+ * while we're checking whether it's in-use.
51+ */
52+ WARN_CONSOLE_UNLOCKED ();
53+
54+ return vc && kref_read (& vc -> port .kref ) > 1 ;
55+ }
56+
57+ static inline bool vt_busy (int i )
58+ {
59+ if (vt_in_use (i ))
60+ return true;
61+ if (i == fg_console )
62+ return true;
63+ if (vc_is_sel (vc_cons [i ].d ))
64+ return true;
65+
66+ return false;
67+ }
4768
4869/*
4970 * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
@@ -289,16 +310,14 @@ static int vt_disallocate(unsigned int vc_num)
289310 int ret = 0 ;
290311
291312 console_lock ();
292- if (VT_BUSY (vc_num ))
313+ if (vt_busy (vc_num ))
293314 ret = - EBUSY ;
294315 else if (vc_num )
295316 vc = vc_deallocate (vc_num );
296317 console_unlock ();
297318
298- if (vc && vc_num >= MIN_NR_CONSOLES ) {
299- tty_port_destroy (& vc -> port );
300- kfree (vc );
301- }
319+ if (vc && vc_num >= MIN_NR_CONSOLES )
320+ tty_port_put (& vc -> port );
302321
303322 return ret ;
304323}
@@ -311,17 +330,15 @@ static void vt_disallocate_all(void)
311330
312331 console_lock ();
313332 for (i = 1 ; i < MAX_NR_CONSOLES ; i ++ )
314- if (!VT_BUSY (i ))
333+ if (!vt_busy (i ))
315334 vc [i ] = vc_deallocate (i );
316335 else
317336 vc [i ] = NULL ;
318337 console_unlock ();
319338
320339 for (i = 1 ; i < MAX_NR_CONSOLES ; i ++ ) {
321- if (vc [i ] && i >= MIN_NR_CONSOLES ) {
322- tty_port_destroy (& vc [i ]-> port );
323- kfree (vc [i ]);
324- }
340+ if (vc [i ] && i >= MIN_NR_CONSOLES )
341+ tty_port_put (& vc [i ]-> port );
325342 }
326343}
327344
@@ -335,22 +352,13 @@ int vt_ioctl(struct tty_struct *tty,
335352{
336353 struct vc_data * vc = tty -> driver_data ;
337354 struct console_font_op op ; /* used in multiple places here */
338- unsigned int console ;
355+ unsigned int console = vc -> vc_num ;
339356 unsigned char ucval ;
340357 unsigned int uival ;
341358 void __user * up = (void __user * )arg ;
342359 int i , perm ;
343360 int ret = 0 ;
344361
345- console = vc -> vc_num ;
346-
347-
348- if (!vc_cons_allocated (console )) { /* impossible? */
349- ret = - ENOIOCTLCMD ;
350- goto out ;
351- }
352-
353-
354362 /*
355363 * To have permissions to do most of the vt ioctls, we either have
356364 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
@@ -641,15 +649,16 @@ int vt_ioctl(struct tty_struct *tty,
641649 struct vt_stat __user * vtstat = up ;
642650 unsigned short state , mask ;
643651
644- /* Review: FIXME: Console lock ? */
645652 if (put_user (fg_console + 1 , & vtstat -> v_active ))
646653 ret = - EFAULT ;
647654 else {
648655 state = 1 ; /* /dev/tty0 is always open */
656+ console_lock (); /* required by vt_in_use() */
649657 for (i = 0 , mask = 2 ; i < MAX_NR_CONSOLES && mask ;
650658 ++ i , mask <<= 1 )
651- if (VT_IS_IN_USE (i ))
659+ if (vt_in_use (i ))
652660 state |= mask ;
661+ console_unlock ();
653662 ret = put_user (state , & vtstat -> v_state );
654663 }
655664 break ;
@@ -659,10 +668,11 @@ int vt_ioctl(struct tty_struct *tty,
659668 * Returns the first available (non-opened) console.
660669 */
661670 case VT_OPENQRY :
662- /* FIXME: locking ? - but then this is a stupid API */
671+ console_lock (); /* required by vt_in_use() */
663672 for (i = 0 ; i < MAX_NR_CONSOLES ; ++ i )
664- if (! VT_IS_IN_USE (i ))
673+ if (!vt_in_use (i ))
665674 break ;
675+ console_unlock ();
666676 uival = i < MAX_NR_CONSOLES ? (i + 1 ) : -1 ;
667677 goto setint ;
668678
@@ -1011,12 +1021,12 @@ int vt_ioctl(struct tty_struct *tty,
10111021 case VT_LOCKSWITCH :
10121022 if (!capable (CAP_SYS_TTY_CONFIG ))
10131023 return - EPERM ;
1014- vt_dont_switch = 1 ;
1024+ vt_dont_switch = true ;
10151025 break ;
10161026 case VT_UNLOCKSWITCH :
10171027 if (!capable (CAP_SYS_TTY_CONFIG ))
10181028 return - EPERM ;
1019- vt_dont_switch = 0 ;
1029+ vt_dont_switch = false ;
10201030 break ;
10211031 case VT_GETHIFONTMASK :
10221032 ret = put_user (vc -> vc_hi_font_mask ,
@@ -1180,14 +1190,9 @@ long vt_compat_ioctl(struct tty_struct *tty,
11801190{
11811191 struct vc_data * vc = tty -> driver_data ;
11821192 struct console_font_op op ; /* used in multiple places here */
1183- unsigned int console = vc -> vc_num ;
11841193 void __user * up = compat_ptr (arg );
11851194 int perm ;
11861195
1187-
1188- if (!vc_cons_allocated (console )) /* impossible? */
1189- return - ENOIOCTLCMD ;
1190-
11911196 /*
11921197 * To have permissions to do most of the vt ioctls, we either have
11931198 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
0 commit comments