From 84f48d4f2b511db15fda67fd38462b91abd0af53 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:01 -0800 Subject: [PATCH] uml: mconsole locking Locking fixes. Locking was totally lacking for the mconsole_devices, which got a spin lock, and the unplugged pages data, which got a mutex. The locking of the mconsole console output code was confused. Now, the console_lock (renamed to client_lock) protects the clients list. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mconsole_kern.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'arch/um/drivers/mconsole_kern.c') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 832d5c766ca8..b4dbd102da0e 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -337,13 +337,15 @@ void mconsole_stop(struct mc_request *req) mconsole_reply(req, "", 0, 0); } -/* This list is populated by __initcall routines. */ - +static DEFINE_SPINLOCK(mc_devices_lock); static LIST_HEAD(mconsole_devices); void mconsole_register_dev(struct mc_device *new) { + spin_lock(&mc_devices_lock); + BUG_ON(!list_empty(&new->list)); list_add(&new->list, &mconsole_devices); + spin_unlock(&mc_devices_lock); } static struct mc_device *mconsole_find_dev(char *name) @@ -367,6 +369,7 @@ struct unplugged_pages { void *pages[UNPLUGGED_PER_PAGE]; }; +static DECLARE_MUTEX(plug_mem_mutex); static unsigned long long unplugged_pages_count = 0; static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages); static int unplug_index = UNPLUGGED_PER_PAGE; @@ -402,6 +405,7 @@ static int mem_config(char *str, char **error_out) diff /= PAGE_SIZE; + down(&plug_mem_mutex); for(i = 0; i < diff; i++){ struct unplugged_pages *unplugged; void *addr; @@ -447,7 +451,7 @@ static int mem_config(char *str, char **error_out) printk("Failed to release memory - " "errno = %d\n", err); *error_out = "Failed to release memory"; - goto out; + goto out_unlock; } unplugged->pages[unplug_index++] = addr; } @@ -457,6 +461,8 @@ static int mem_config(char *str, char **error_out) } err = 0; +out_unlock: + up(&plug_mem_mutex); out: return err; } @@ -487,6 +493,7 @@ static int mem_remove(int n, char **error_out) } static struct mc_device mem_mc = { + .list = LIST_HEAD_INIT(mem_mc.list), .name = "mem", .config = mem_config, .get_config = mem_get_config, @@ -629,7 +636,7 @@ struct mconsole_output { struct mc_request *req; }; -static DEFINE_SPINLOCK(console_lock); +static DEFINE_SPINLOCK(client_lock); static LIST_HEAD(clients); static char console_buf[MCONSOLE_MAX_DATA]; static int console_index = 0; @@ -684,16 +691,18 @@ static void with_console(struct mc_request *req, void (*proc)(void *), unsigned long flags; entry.req = req; + spin_lock_irqsave(&client_lock, flags); list_add(&entry.list, &clients); - spin_lock_irqsave(&console_lock, flags); + spin_unlock_irqrestore(&client_lock, flags); (*proc)(arg); mconsole_reply_len(req, console_buf, console_index, 0, 0); console_index = 0; - spin_unlock_irqrestore(&console_lock, flags); + spin_lock_irqsave(&client_lock, flags); list_del(&entry.list); + spin_unlock_irqrestore(&client_lock, flags); } #ifdef CONFIG_MAGIC_SYSRQ -- cgit v1.2.2