um: convert count_lock to mutex, fix a race in line_open()

If two processes are opening the same line, the second to get
into line_open() will decide that it doesn't need to do anything
(correctly) or wait for anything.  The latter, unfortunately,
is incorrect - the first opener might not be through yet.  We
need to have exclusion covering the entire line_init(), including
the blocking parts.  Moreover, the next patch will need to
widen the exclusion on mconsole side of things, also including
the blocking bits, so let's just convert that sucker to mutex...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Richard Weinberger <richard@nod.at>
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 3eea99e..dc7e216 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -409,7 +409,7 @@
 	struct line *line = &lines[tty->index];
 	int err = -ENODEV;
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 	if (!line->valid)
 		goto out_unlock;
 
@@ -421,10 +421,9 @@
 	tty->driver_data = line;
 	line->tty = tty;
 
-	spin_unlock(&line->count_lock);
 	err = enable_chan(line);
 	if (err) /* line_close() will be called by our caller */
-		return err;
+		goto out_unlock;
 
 	INIT_DELAYED_WORK(&line->task, line_timer_cb);
 
@@ -435,11 +434,8 @@
 
 	chan_window_size(&line->chan_list, &tty->winsize.ws_row,
 			 &tty->winsize.ws_col);
-
-	return 0;
-
 out_unlock:
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 	return err;
 }
 
@@ -459,7 +455,7 @@
 	/* We ignore the error anyway! */
 	flush_buffer(line);
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 	BUG_ON(!line->valid);
 
 	if (--line->count)
@@ -468,17 +464,13 @@
 	line->tty = NULL;
 	tty->driver_data = NULL;
 
-	spin_unlock(&line->count_lock);
-
 	if (line->sigio) {
 		unregister_winch(tty);
 		line->sigio = 0;
 	}
 
-	return;
-
 out_unlock:
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 }
 
 void close_lines(struct line *lines, int nlines)
@@ -495,7 +487,7 @@
 	struct line *line = &lines[n];
 	int err = -EINVAL;
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 
 	if (line->count) {
 		*error_out = "Device is already open";
@@ -510,7 +502,7 @@
 	}
 	err = 0;
 out:
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 	return err;
 }
 
@@ -609,13 +601,13 @@
 
 	line = &lines[dev];
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 	if (!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if (line->tty == NULL)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 
 	return n;
 }
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 0c4dadf5..471f477 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -32,7 +32,7 @@
 
 struct line {
 	struct tty_struct *tty;
-	spinlock_t count_lock;
+	struct mutex count_lock;
 	unsigned long count;
 	int valid;
 
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 445288f..23cffd6 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -201,7 +201,7 @@
 			serial_lines[i].valid = 1;
 		}
 		spin_lock_init(&serial_lines[i].lock);
-		spin_lock_init(&serial_lines[i].count_lock);
+		mutex_init(&serial_lines[i].count_lock);
 		serial_lines[i].driver = &driver;
 	}
 	ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 6d244f4..f8d4325 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -173,7 +173,7 @@
 			vts[i].valid = 1;
 		}
 		spin_lock_init(&vts[i].lock);
-		spin_lock_init(&vts[i].count_lock);
+		mutex_init(&vts[i].count_lock);
 		vts[i].driver = &driver;
 	}
 	console_driver = register_lines(&driver, &console_ops, vts,