From d79a580936396bbcd2f4fae2c6215f9cf81e3c0d Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:52 -0800 Subject: [PATCH] uml: console locking fixes Clean up the console driver locking. There are various problems here, including sleeping under a spinlock and spinlock recursion, some of which are fixed here. This patch deals with the locking involved with opens and closes. The problem is that an mconsole request to change a console's configuration can race with an open. Changing a configuration should only be done when a console isn't opened. Also, an open must be looking at a stable configuration. In addition, a get configuration request must observe the same locking since it must also see a stable configuration. With the old locking, it was possible for this to hang indefinitely in some cases because open would block for a long time waiting for a connection from the host while holding the lock needed by the mconsole request. As explained in the long comment, this is fixed by adding a spinlock for the use count and configuration and a mutex for the actual open and close. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/stdio_console.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/um/drivers/stdio_console.c') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 7a4897e27f42..9b2dd0b8a43b 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -83,9 +83,9 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS); /* The array is initialized by line_init, which is an initcall. The * individual elements are protected by individual semaphores. */ -struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), - [ 1 ... MAX_TTYS - 1 ] = - LINE_INIT(CONFIG_CON_CHAN, &driver) }; +static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), + [ 1 ... MAX_TTYS - 1 ] = + LINE_INIT(CONFIG_CON_CHAN, &driver) }; static int con_config(char *str) { -- cgit v1.2.1 From f28169d2000177e8b72ccc6d72887be779dceca8 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:53 -0800 Subject: [PATCH] uml: return hotplug errors to host I noticed that errors happening while hotplugging devices from the host were never returned back to the mconsole client. In some cases, success was returned instead of even an information-free error. This patch cleans that up by having the low-level configuration code pass back an error string along with an error code. At the top level, which knows whether it is early boot time or responding to an mconsole request, the string is printk'd or returned to the mconsole client. There are also whitespace and trivial code cleanups in the surrounding code. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/stdio_console.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'arch/um/drivers/stdio_console.c') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 9b2dd0b8a43b..3cbfe3a88607 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -52,9 +52,9 @@ static struct chan_opts opts = { .in_kernel = 1, }; -static int con_config(char *str); +static int con_config(char *str, char **error_out); static int con_get_config(char *dev, char *str, int size, char **error_out); -static int con_remove(int n); +static int con_remove(int n, char **con_remove); static struct line_driver driver = { .name = "UML console", @@ -87,9 +87,9 @@ static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), [ 1 ... MAX_TTYS - 1 ] = LINE_INIT(CONFIG_CON_CHAN, &driver) }; -static int con_config(char *str) +static int con_config(char *str, char **error_out) { - return line_config(vts, ARRAY_SIZE(vts), str, &opts); + return line_config(vts, ARRAY_SIZE(vts), str, &opts, error_out); } static int con_get_config(char *dev, char *str, int size, char **error_out) @@ -97,9 +97,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out) return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out); } -static int con_remove(int n) +static int con_remove(int n, char **error_out) { - return line_remove(vts, ARRAY_SIZE(vts), n); + return line_remove(vts, ARRAY_SIZE(vts), n, error_out); } static int con_open(struct tty_struct *tty, struct file *filp) @@ -192,7 +192,15 @@ __uml_exitcall(console_exit); static int console_chan_setup(char *str) { - return line_setup(vts, ARRAY_SIZE(vts), str); + char *error; + int ret; + + ret = line_setup(vts, ARRAY_SIZE(vts), str, &error); + if(ret < 0) + printk(KERN_ERR "Failed to set up console with " + "configuration string \"%s\" : %s\n", str, error); + + return 1; } __setup("con", console_chan_setup); __channel_help(console_chan_setup, "con"); -- cgit v1.2.1 From 894be2a485b75bce9a4d45d3e431aafd4c89f1ea Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:54 -0800 Subject: [PATCH] uml: console whitespace and comment tidying Some comment and whitespace cleanups in the console and mconsole code. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/stdio_console.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/um/drivers/stdio_console.c') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 3cbfe3a88607..0b1bca498049 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -30,8 +30,6 @@ #define MAX_TTYS (16) -/* ----------------------------------------------------------------------------- */ - /* Referenced only by tty_driver below - presumably it's locked correctly * by the tty driver. */ -- cgit v1.2.1 From a52f362f864f56238c9036f5c56f763a80e2ddd5 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:06 -0800 Subject: [PATCH] uml: mostly const a structure The chan_opts structure is mostly const, and needs no locking. Comment the lack of locking on the one field that can change. Make all the other fields const. It turned out that console_open_chan didn't use its chan_opts argument, so that is deleted from the function and its callers. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/stdio_console.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/um/drivers/stdio_console.c') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 0b1bca498049..a83c42c263b3 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -42,6 +42,7 @@ void stdio_announce(char *dev_name, int dev) dev_name); } +/* Almost const, except that xterm_title may be changed in an initcall */ static struct chan_opts opts = { .announce = stdio_announce, .xterm_title = "Virtual Console #%d", @@ -144,7 +145,7 @@ static int uml_console_setup(struct console *co, char *options) { struct line *line = &vts[co->index]; - return console_open_chan(line, co, &opts); + return console_open_chan(line, co); } static struct console stdiocons = { -- cgit v1.2.1 From d5c9ffc6c6d15d4f655236e26942a21ad61fe3ad Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:08 -0800 Subject: [PATCH] uml: console locking commentary and code cleanup Remove the last vestiges of devfs from console registration. Change the name of the function, plus remove a couple of unused fields from the line_driver structure. struct lines is no longer needed, all traces of it are gone. The only way that I can see to mark a structure as being almost-const is to individually const the fields. This is the case for the line_driver structure, which has only one modifiable field - a list_head in a sub-structure. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/stdio_console.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'arch/um/drivers/stdio_console.c') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index a83c42c263b3..8dccdd193d94 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -55,6 +55,8 @@ static int con_config(char *str, char **error_out); static int con_get_config(char *dev, char *str, int size, char **error_out); static int con_remove(int n, char **con_remove); + +/* Const, except for .mc.list */ static struct line_driver driver = { .name = "UML console", .device_name = "tty", @@ -66,8 +68,6 @@ static struct line_driver driver = { .read_irq_name = "console", .write_irq = CONSOLE_WRITE_IRQ, .write_irq_name = "console-write", - .symlink_from = "ttys", - .symlink_to = "vc", .mc = { .name = "con", .config = con_config, @@ -77,10 +77,8 @@ static struct line_driver driver = { }, }; -static struct lines console_lines = LINES_INIT(MAX_TTYS); - -/* The array is initialized by line_init, which is an initcall. The - * individual elements are protected by individual semaphores. +/* The array is initialized by line_init, at initcall time. The + * elements are locked individually as needed. */ static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), [ 1 ... MAX_TTYS - 1 ] = @@ -148,6 +146,7 @@ static int uml_console_setup(struct console *co, char *options) return console_open_chan(line, co); } +/* No locking for register_console call - relies on single-threaded initcalls */ static struct console stdiocons = { .name = "tty", .write = uml_console_write, @@ -155,16 +154,14 @@ static struct console stdiocons = { .setup = uml_console_setup, .flags = CON_PRINTBUFFER, .index = -1, - .data = &vts, }; int stdio_init(void) { char *new_title; - console_driver = line_register_devfs(&console_lines, &driver, - &console_ops, vts, - ARRAY_SIZE(vts)); + console_driver = register_lines(&driver, &console_ops, vts, + ARRAY_SIZE(vts)); if (console_driver == NULL) return -1; printk(KERN_INFO "Initialized stdio console driver\n"); -- cgit v1.2.1 From c0961c1804c46bf5bb253e1bd6bc93e4627b79a1 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:11 -0800 Subject: [PATCH] uml: initialize a list head We need to initialize lists properly. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/stdio_console.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um/drivers/stdio_console.c') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 8dccdd193d94..7ff0b0fc37e7 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -69,6 +69,7 @@ static struct line_driver driver = { .write_irq = CONSOLE_WRITE_IRQ, .write_irq_name = "console-write", .mc = { + .list = LIST_HEAD_INIT(driver.mc.list), .name = "con", .config = con_config, .get_config = con_get_config, -- cgit v1.2.1