ALPHA: srmcons, fix racy singleton structure
authorJiri Slaby <jslaby@suse.cz>
Mon, 5 Mar 2012 13:51:58 +0000 (14:51 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Mar 2012 19:42:21 +0000 (11:42 -0800)
The test and the assignment were racy. Make it really a singleton.
This is achieved by one global variable initialized at the module
init.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/alpha/kernel/srmcons.c

index f1fdf178bcb4cc0658376f3b5668b66ce1b520f3..2c89ce5c9ab6c555ee0cf0710429fe5026d90fc1 100644 (file)
@@ -33,7 +33,7 @@ struct srmcons_private {
        struct tty_struct *tty;
        struct timer_list timer;
        spinlock_t lock;
-};
+} srmcons_singleton;
 
 typedef union _srmcons_result {
        struct {
@@ -153,44 +153,11 @@ srmcons_chars_in_buffer(struct tty_struct *tty)
        return 0;
 }
 
-static int
-srmcons_get_private_struct(struct srmcons_private **ps)
-{
-       static struct srmcons_private *srmconsp = NULL;
-       static DEFINE_SPINLOCK(srmconsp_lock);
-       unsigned long flags;
-       int retval = 0;
-
-       if (srmconsp == NULL) {
-               srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
-               spin_lock_irqsave(&srmconsp_lock, flags);
-
-               if (srmconsp == NULL)
-                       retval = -ENOMEM;
-               else {
-                       srmconsp->tty = NULL;
-                       spin_lock_init(&srmconsp->lock);
-                       setup_timer(&srmconsp->timer, srmcons_receive_chars,
-                                       (unsigned long)srmconsp);
-               }
-
-               spin_unlock_irqrestore(&srmconsp_lock, flags);
-       }
-
-       *ps = srmconsp;
-       return retval;
-}
-
 static int
 srmcons_open(struct tty_struct *tty, struct file *filp)
 {
-       struct srmcons_private *srmconsp;
+       struct srmcons_private *srmconsp = &srmcons_singleton;
        unsigned long flags;
-       int retval;
-
-       retval = srmcons_get_private_struct(&srmconsp);
-       if (retval)
-               return retval;
 
        spin_lock_irqsave(&srmconsp->lock, flags);
 
@@ -236,6 +203,9 @@ static const struct tty_operations srmcons_ops = {
 static int __init
 srmcons_init(void)
 {
+       spin_lock_init(&srmcons_singleton.lock);
+       setup_timer(&srmcons_singleton.timer, srmcons_receive_chars,
+                       (unsigned long)&srmcons_singleton);
        if (srm_is_registered_console) {
                struct tty_driver *driver;
                int err;