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/line.c | 186 ++++++++++++++++++++++++++-------------- arch/um/drivers/stdio_console.c | 6 +- 2 files changed, 125 insertions(+), 67 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 83301e1..799fca3 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -191,7 +191,6 @@ void line_flush_buffer(struct tty_struct *tty) /*XXX: copied from line_write, verify if it is correct!*/ if(tty->stopped) return; - //return 0; spin_lock_irqsave(&line->lock, flags); err = flush_buffer(line); @@ -421,42 +420,84 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) return err; } +/* Normally, a driver like this can rely mostly on the tty layer + * locking, particularly when it comes to the driver structure. + * However, in this case, mconsole requests can come in "from the + * side", and race with opens and closes. + * + * The problem comes from line_setup not wanting to sleep if + * the device is open or being opened. This can happen because the + * first opener of a device is responsible for setting it up on the + * host, and that can sleep. The open of a port device will sleep + * until someone telnets to it. + * + * The obvious solution of putting everything under a mutex fails + * because then trying (and failing) to change the configuration of an + * open(ing) device will block until the open finishes. The right + * thing to happen is for it to fail immediately. + * + * We can put the opening (and closing) of the host device under a + * separate lock, but that has to be taken before the count lock is + * released. Otherwise, you open a window in which another open can + * come through and assume that the host side is opened and working. + * + * So, if the tty count is one, open will take the open mutex + * inside the count lock. Otherwise, it just returns. This will sleep + * if the last close is pending, and will block a setup or get_config, + * but that should not last long. + * + * So, what we end up with is that open and close take the count lock. + * If the first open or last close are happening, then the open mutex + * is taken inside the count lock and the host opening or closing is done. + * + * setup and get_config only take the count lock. setup modifies the + * device configuration only if the open count is zero. Arbitrarily + * long blocking of setup doesn't happen because something would have to be + * waiting for an open to happen. However, a second open with + * tty->count == 1 can't happen, and a close can't happen until the open + * had finished. + * + * We can't maintain our own count here because the tty layer doesn't + * match opens and closes. It will call close if an open failed, and + * a tty hangup will result in excess closes. So, we rely on + * tty->count instead. It is one on both the first open and last close. + */ + int line_open(struct line *lines, struct tty_struct *tty) { - struct line *line; + struct line *line = &lines[tty->index]; int err = -ENODEV; - line = &lines[tty->index]; - tty->driver_data = line; + spin_lock(&line->count_lock); + if(!line->valid) + goto out_unlock; + + err = 0; + if(tty->count > 1) + goto out_unlock; - /* The IRQ which takes this lock is not yet enabled and won't be run - * before the end, so we don't need to use spin_lock_irq.*/ - spin_lock(&line->lock); + mutex_lock(&line->open_mutex); + spin_unlock(&line->count_lock); tty->driver_data = line; line->tty = tty; - if(!line->valid) - goto out; - if(tty->count == 1){ - /* Here the device is opened, if necessary, and interrupt - * is registered. - */ - enable_chan(line); - INIT_DELAYED_WORK(&line->task, line_timer_cb); - - if(!line->sigio){ - chan_enable_winch(&line->chan_list, tty); - line->sigio = 1; - } + enable_chan(line); + INIT_DELAYED_WORK(&line->task, line_timer_cb); - chan_window_size(&line->chan_list, &tty->winsize.ws_row, - &tty->winsize.ws_col); + if(!line->sigio){ + chan_enable_winch(&line->chan_list, tty); + line->sigio = 1; } - err = 0; -out: - spin_unlock(&line->lock); + chan_window_size(&line->chan_list, &tty->winsize.ws_row, + &tty->winsize.ws_col); + + mutex_unlock(&line->open_mutex); + return err; + +out_unlock: + spin_unlock(&line->count_lock); return err; } @@ -466,25 +507,38 @@ void line_close(struct tty_struct *tty, struct file * filp) { struct line *line = tty->driver_data; - /* XXX: I assume this should be called in process context, not with - * interrupts disabled! - */ - spin_lock_irq(&line->lock); + /* If line_open fails (and tty->driver_data is never set), + * tty_open will call line_close. So just return in this case. + */ + if(line == NULL) + return; /* We ignore the error anyway! */ flush_buffer(line); - if(tty->count == 1){ - line->tty = NULL; - tty->driver_data = NULL; + spin_lock(&line->count_lock); + if(!line->valid) + goto out_unlock; + + if(tty->count > 1) + goto out_unlock; - if(line->sigio){ - unregister_winch(tty); - line->sigio = 0; - } + mutex_lock(&line->open_mutex); + spin_unlock(&line->count_lock); + + line->tty = NULL; + tty->driver_data = NULL; + + if(line->sigio){ + unregister_winch(tty); + line->sigio = 0; } - spin_unlock_irq(&line->lock); + mutex_unlock(&line->open_mutex); + return; + +out_unlock: + spin_unlock(&line->count_lock); } void close_lines(struct line *lines, int nlines) @@ -495,6 +549,30 @@ void close_lines(struct line *lines, int nlines) close_chan(&lines[i].chan_list, 0); } +static void setup_one_line(struct line *lines, int n, char *init, int init_prio) +{ + struct line *line = &lines[n]; + + spin_lock(&line->count_lock); + + if(line->tty != NULL){ + printk("line_setup - device %d is open\n", n); + goto out; + } + + if (line->init_pri <= init_prio){ + line->init_pri = init_prio; + if (!strcmp(init, "none")) + line->valid = 0; + else { + line->init_str = init; + line->valid = 1; + } + } +out: + spin_unlock(&line->count_lock); +} + /* Common setup code for both startup command line and mconsole initialization. * @lines contains the array (of size @num) to modify; * @init is the setup string; @@ -526,32 +604,11 @@ int line_setup(struct line *lines, unsigned int num, char *init) n, num - 1); return 0; } - else if (n >= 0){ - if (lines[n].tty != NULL) { - printk("line_setup - device %d is open\n", n); - return 0; - } - if (lines[n].init_pri <= INIT_ONE){ - lines[n].init_pri = INIT_ONE; - if (!strcmp(init, "none")) - lines[n].valid = 0; - else { - lines[n].init_str = init; - lines[n].valid = 1; - } - } - } + else if (n >= 0) + setup_one_line(lines, n, init, INIT_ONE); else { - for(i = 0; i < num; i++){ - if(lines[i].init_pri <= INIT_ALL){ - lines[i].init_pri = INIT_ALL; - if(!strcmp(init, "none")) lines[i].valid = 0; - else { - lines[i].init_str = init; - lines[i].valid = 1; - } - } - } + for(i = 0; i < num; i++) + setup_one_line(lines, i, init, INIT_ALL); } return n == -1 ? num : n; } @@ -602,13 +659,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, line = &lines[dev]; - spin_lock(&line->lock); + spin_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->lock); + spin_unlock(&line->count_lock); return n; } @@ -688,6 +745,7 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) for(i = 0; i < nlines; i++){ line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); + mutex_init(&line->open_mutex); if(line->init_str == NULL) continue; diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 7a4897e..9b2dd0b 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.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/chan_kern.c | 77 +++++++---------------- arch/um/drivers/line.c | 66 ++++++++++++-------- arch/um/drivers/mconsole_kern.c | 40 ++++++++---- arch/um/drivers/net_kern.c | 97 ++++++++++++++--------------- arch/um/drivers/ssl.c | 24 +++++--- arch/um/drivers/stdio_console.c | 22 ++++--- arch/um/drivers/ubd_kern.c | 132 ++++++++++++++++++++++------------------ 7 files changed, 241 insertions(+), 217 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 7d4190e..4e7e3cf 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -19,44 +19,11 @@ #include "line.h" #include "os.h" -/* XXX: could well be moved to somewhere else, if needed. */ -static int my_printf(const char * fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -static int my_printf(const char * fmt, ...) -{ - /* Yes, can be called on atomic context.*/ - char *buf = kmalloc(4096, GFP_ATOMIC); - va_list args; - int r; - - if (!buf) { - /* We print directly fmt. - * Yes, yes, yes, feel free to complain. */ - r = strlen(fmt); - } else { - va_start(args, fmt); - r = vsprintf(buf, fmt, args); - va_end(args); - fmt = buf; - } - - if (r) - r = os_write_file(1, fmt, r); - return r; - -} - #ifdef CONFIG_NOCONFIG_CHAN -/* Despite its name, there's no added trailing newline. */ -static int my_puts(const char * buf) +static void *not_configged_init(char *str, int device, + const struct chan_opts *opts) { - return os_write_file(1, buf, strlen(buf)); -} - -static void *not_configged_init(char *str, int device, struct chan_opts *opts) -{ - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return NULL; } @@ -64,34 +31,34 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts) static int not_configged_open(int input, int output, int primary, void *data, char **dev_out) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -ENODEV; } static void not_configged_close(int fd, void *data) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); } static int not_configged_read(int fd, char *c_out, void *data) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -EIO; } static int not_configged_write(int fd, const char *buf, int len, void *data) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -EIO; } static int not_configged_console_write(int fd, const char *buf, int len) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -EIO; } @@ -99,14 +66,14 @@ static int not_configged_console_write(int fd, const char *buf, int len) static int not_configged_window_size(int fd, void *data, unsigned short *rows, unsigned short *cols) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); return -ENODEV; } static void not_configged_free(void *data) { - my_puts("Using a channel type which is configured out of " + printk("Using a channel type which is configured out of " "UML\n"); } @@ -534,7 +501,7 @@ static const struct chan_type chan_table[] = { }; static struct chan *parse_chan(struct line *line, char *str, int device, - const struct chan_opts *opts) + const struct chan_opts *opts, char **error_out) { const struct chan_type *entry; const struct chan_ops *ops; @@ -553,19 +520,21 @@ static struct chan *parse_chan(struct line *line, char *str, int device, } } if(ops == NULL){ - my_printf("parse_chan couldn't parse \"%s\"\n", - str); + *error_out = "No match for configured backends"; return NULL; } - if(ops->init == NULL) - return NULL; + data = (*ops->init)(str, device, opts); - if(data == NULL) + if(data == NULL){ + *error_out = "Configuration failed"; return NULL; + } chan = kmalloc(sizeof(*chan), GFP_ATOMIC); - if(chan == NULL) + if(chan == NULL){ + *error_out = "Memory allocation failed"; return NULL; + } *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), .free_list = LIST_HEAD_INIT(chan->free_list), @@ -582,7 +551,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device, } int parse_chan_pair(char *str, struct line *line, int device, - const struct chan_opts *opts) + const struct chan_opts *opts, char **error_out) { struct list_head *chans = &line->chan_list; struct chan *new, *chan; @@ -599,14 +568,14 @@ int parse_chan_pair(char *str, struct line *line, int device, in = str; *out = '\0'; out++; - new = parse_chan(line, in, device, opts); + new = parse_chan(line, in, device, opts, error_out); if(new == NULL) return -1; new->input = 1; list_add(&new->list, chans); - new = parse_chan(line, out, device, opts); + new = parse_chan(line, out, device, opts, error_out); if(new == NULL) return -1; @@ -614,7 +583,7 @@ int parse_chan_pair(char *str, struct line *line, int device, new->output = 1; } else { - new = parse_chan(line, str, device, opts); + new = parse_chan(line, str, device, opts, error_out); if(new == NULL) return -1; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 799fca3..e620ed46 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -549,14 +549,16 @@ void close_lines(struct line *lines, int nlines) close_chan(&lines[i].chan_list, 0); } -static void setup_one_line(struct line *lines, int n, char *init, int init_prio) +static int setup_one_line(struct line *lines, int n, char *init, int init_prio, + char **error_out) { struct line *line = &lines[n]; + int err = -EINVAL; spin_lock(&line->count_lock); if(line->tty != NULL){ - printk("line_setup - device %d is open\n", n); + *error_out = "Device is already open"; goto out; } @@ -569,18 +571,22 @@ static void setup_one_line(struct line *lines, int n, char *init, int init_prio) line->valid = 1; } } + err = 0; out: spin_unlock(&line->count_lock); + return err; } /* Common setup code for both startup command line and mconsole initialization. * @lines contains the array (of size @num) to modify; * @init is the setup string; + * @error_out is an error string in the case of failure; */ -int line_setup(struct line *lines, unsigned int num, char *init) +int line_setup(struct line *lines, unsigned int num, char *init, + char **error_out) { - int i, n; + int i, n, err; char *end; if(*init == '=') { @@ -591,52 +597,56 @@ int line_setup(struct line *lines, unsigned int num, char *init) else { n = simple_strtoul(init, &end, 0); if(*end != '='){ - printk(KERN_ERR "line_setup failed to parse \"%s\"\n", - init); - return 0; + *error_out = "Couldn't parse device number"; + return -EINVAL; } init = end; } init++; if (n >= (signed int) num) { - printk("line_setup - %d out of range ((0 ... %d) allowed)\n", - n, num - 1); - return 0; + *error_out = "Device number out of range"; + return -EINVAL; + } + else if (n >= 0){ + err = setup_one_line(lines, n, init, INIT_ONE, error_out); + if(err) + return err; } - else if (n >= 0) - setup_one_line(lines, n, init, INIT_ONE); else { - for(i = 0; i < num; i++) - setup_one_line(lines, i, init, INIT_ALL); + for(i = 0; i < num; i++){ + err = setup_one_line(lines, i, init, INIT_ALL, + error_out); + if(err) + return err; + } } return n == -1 ? num : n; } int line_config(struct line *lines, unsigned int num, char *str, - const struct chan_opts *opts) + const struct chan_opts *opts, char **error_out) { struct line *line; char *new; int n; if(*str == '='){ - printk("line_config - can't configure all devices from " - "mconsole\n"); - return 1; + *error_out = "Can't configure all devices from mconsole"; + return -EINVAL; } new = kstrdup(str, GFP_KERNEL); if(new == NULL){ - printk("line_config - kstrdup failed\n"); - return 1; + *error_out = "Failed to allocate memory"; + return -ENOMEM; } - n = line_setup(lines, num, new); + n = line_setup(lines, num, new, error_out); if(n < 0) - return 1; + return n; line = &lines[n]; - return parse_chan_pair(line->init_str, line, n, opts); + return parse_chan_pair(line->init_str, line, n, opts, error_out); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -685,13 +695,13 @@ int line_id(char **str, int *start_out, int *end_out) return n; } -int line_remove(struct line *lines, unsigned int num, int n) +int line_remove(struct line *lines, unsigned int num, int n, char **error_out) { int err; char config[sizeof("conxxxx=none\0")]; sprintf(config, "%d=none", n); - err = line_setup(lines, num, config); + err = line_setup(lines, num, config, error_out); if(err >= 0) err = 0; return err; @@ -740,6 +750,7 @@ static LIST_HEAD(winch_handlers); void lines_init(struct line *lines, int nlines, struct chan_opts *opts) { struct line *line; + char *error; int i; for(i = 0; i < nlines; i++){ @@ -754,8 +765,9 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) if(line->init_str == NULL) printk("lines_init - kstrdup returned NULL\n"); - if(parse_chan_pair(line->init_str, line, i, opts)){ - printk("parse_chan_pair failed for device %d\n", i); + if(parse_chan_pair(line->init_str, line, i, opts, &error)){ + printk("parse_chan_pair failed for device %d : %s\n", + i, error); line->valid = 0; } } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 96f0189..832d5c7 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -371,14 +371,16 @@ 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; -static int mem_config(char *str) +static int mem_config(char *str, char **error_out) { unsigned long long diff; int err = -EINVAL, i, add; char *ret; - if(str[0] != '=') + if(str[0] != '='){ + *error_out = "Expected '=' after 'mem'"; goto out; + } str++; if(str[0] == '-') @@ -386,12 +388,17 @@ static int mem_config(char *str) else if(str[0] == '+'){ add = 1; } - else goto out; + else { + *error_out = "Expected increment to start with '-' or '+'"; + goto out; + } str++; diff = memparse(str, &ret); - if(*ret != '\0') + if(*ret != '\0'){ + *error_out = "Failed to parse memory increment"; goto out; + } diff /= PAGE_SIZE; @@ -435,11 +442,14 @@ static int mem_config(char *str) unplugged = list_entry(entry, struct unplugged_pages, list); - unplugged->pages[unplug_index++] = addr; err = os_drop_memory(addr, PAGE_SIZE); - if(err) + if(err){ printk("Failed to release memory - " "errno = %d\n", err); + *error_out = "Failed to release memory"; + goto out; + } + unplugged->pages[unplug_index++] = addr; } unplugged_pages_count++; @@ -470,8 +480,9 @@ static int mem_id(char **str, int *start_out, int *end_out) return 0; } -static int mem_remove(int n) +static int mem_remove(int n, char **error_out) { + *error_out = "Memory doesn't support the remove operation"; return -EBUSY; } @@ -542,7 +553,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, void mconsole_config(struct mc_request *req) { struct mc_device *dev; - char *ptr = req->request.data, *name; + char *ptr = req->request.data, *name, *error_string = ""; int err; ptr += strlen("config"); @@ -559,8 +570,8 @@ void mconsole_config(struct mc_request *req) ptr++; if(*ptr == '='){ - err = (*dev->config)(name); - mconsole_reply(req, "", err, 0); + err = (*dev->config)(name, &error_string); + mconsole_reply(req, error_string, err, 0); } else mconsole_get_config(dev->get_config, req, name); } @@ -595,13 +606,16 @@ void mconsole_remove(struct mc_request *req) goto out; } - err = (*dev->remove)(n); + err_msg = NULL; + err = (*dev->remove)(n, &err_msg); switch(err){ case -ENODEV: - err_msg = "Device doesn't exist"; + if(err_msg == NULL) + err_msg = "Device doesn't exist"; break; case -EBUSY: - err_msg = "Device is currently open"; + if(err_msg == NULL) + err_msg = "Device is currently open"; break; default: break; diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index afe3d42..07e839e 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. @@ -91,8 +91,8 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; if(err < 0) { - printk(KERN_ERR - "Device '%s' read returned %d, shutting it down\n", + printk(KERN_ERR + "Device '%s' read returned %d, shutting it down\n", dev->name, err); /* dev_close can't be called in interrupt context, and takes * again lp->lock. @@ -159,7 +159,7 @@ out: static int uml_net_close(struct net_device *dev) { struct uml_net_private *lp = dev->priv; - + netif_stop_queue(dev); free_irq(dev->irq, dev); @@ -194,7 +194,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) /* this is normally done in the interrupt when tx finishes */ netif_wake_queue(dev); - } + } else if(len == 0){ netif_start_queue(dev); lp->stats.tx_dropped++; @@ -333,7 +333,7 @@ static int eth_configure(int n, void *init, char *mac, struct uml_net_private *lp; int save, err, size; - size = transport->private_size + sizeof(struct uml_net_private) + + size = transport->private_size + sizeof(struct uml_net_private) + sizeof(((struct uml_net_private *) 0)->user); device = kzalloc(sizeof(*device), GFP_KERNEL); @@ -438,7 +438,7 @@ static int eth_configure(int n, void *init, char *mac, lp->tl.function = uml_net_user_timer_expire; memcpy(lp->mac, device->mac, sizeof(lp->mac)); - if (transport->user->init) + if (transport->user->init) (*transport->user->init)(&lp->user, dev); set_ether_mac(dev, device->mac); @@ -463,35 +463,33 @@ static struct uml_net *find_device(int n) return(device); } -static int eth_parse(char *str, int *index_out, char **str_out) +static int eth_parse(char *str, int *index_out, char **str_out, + char **error_out) { char *end; - int n; + int n, err = -EINVAL;; n = simple_strtoul(str, &end, 0); if(end == str){ - printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); - return(1); - } - if(n < 0){ - printk(KERN_ERR "eth_setup: device %d is negative\n", n); - return(1); + *error_out = "Bad device number"; + return err; } + str = end; if(*str != '='){ - printk(KERN_ERR - "eth_setup: expected '=' after device number\n"); - return(1); + *error_out = "Expected '=' after device number"; + return err; } + str++; if(find_device(n)){ - printk(KERN_ERR "eth_setup: Device %d already configured\n", - n); - return(1); + *error_out = "Device already configured"; + return err; } - if(index_out) *index_out = n; + + *index_out = n; *str_out = str; - return(0); + return 0; } struct eth_init { @@ -581,11 +579,15 @@ static int eth_setup_common(char *str, int index) static int eth_setup(char *str) { struct eth_init *new; + char *error; int n, err; - err = eth_parse(str, &n, &str); - if(err) + err = eth_parse(str, &n, &str, &error); + if(err){ + printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n", + str, error); return 1; + } new = alloc_bootmem(sizeof(*new)); if (new == NULL){ @@ -619,26 +621,30 @@ static int eth_init(void) if(eth_setup_common(eth->init, eth->index)) list_del(ð->list); } - + return(1); } __initcall(eth_init); #endif -static int net_config(char *str) +static int net_config(char *str, char **error_out) { int n, err; - err = eth_parse(str, &n, &str); - if(err) return(err); + err = eth_parse(str, &n, &str, error_out); + if(err) + return err; + /* This string is broken up and the pieces used by the underlying + * driver. So, it is freed only if eth_setup_common fails. + */ str = kstrdup(str, GFP_KERNEL); if(str == NULL){ - printk(KERN_ERR "net_config failed to strdup string\n"); - return(-1); + *error_out = "net_config failed to strdup string"; + return -ENOMEM; } err = !eth_setup_common(str, n); - if(err) + if(err) kfree(str); return(err); } @@ -658,7 +664,7 @@ static int net_id(char **str, int *start_out, int *end_out) return n; } -static int net_remove(int n) +static int net_remove(int n, char **error_out) { struct uml_net *device; struct net_device *dev; @@ -727,7 +733,7 @@ struct notifier_block uml_inetaddr_notifier = { static int uml_net_init(void) { struct list_head *ele; - struct uml_net_private *lp; + struct uml_net_private *lp; struct in_device *ip; struct in_ifaddr *in; @@ -747,7 +753,7 @@ static int uml_net_init(void) uml_inetaddr_event(NULL, NETDEV_UP, in); in = in->ifa_next; } - } + } return(0); } @@ -783,8 +789,8 @@ struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) return(skb); } -void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, - void *), +void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, + void *), void *arg) { struct net_device *dev = d; @@ -809,11 +815,11 @@ int dev_netmask(void *d, void *m) struct in_ifaddr *in; __be32 *mask_out = m; - if(ip == NULL) + if(ip == NULL) return(1); in = ip->ifa_list; - if(in == NULL) + if(in == NULL) return(1); *mask_out = in->ifa_mask; @@ -835,7 +841,7 @@ void free_output_buffer(void *buffer) free_pages((unsigned long) buffer, 0); } -int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, +int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, char **gate_addr) { char *remain; @@ -854,14 +860,3 @@ unsigned short eth_protocol(struct sk_buff *skb) { return(eth_type_trans(skb, skb->dev)); } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index ed9c590..1e82430 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -46,9 +46,9 @@ static struct chan_opts opts = { .in_kernel = 1, }; -static int ssl_config(char *str); +static int ssl_config(char *str, char **error_out); static int ssl_get_config(char *dev, char *str, int size, char **error_out); -static int ssl_remove(int n); +static int ssl_remove(int n, char **error_out); static struct line_driver driver = { .name = "UML serial line", @@ -80,9 +80,10 @@ static struct line serial_lines[NR_PORTS] = static struct lines lines = LINES_INIT(NR_PORTS); -static int ssl_config(char *str) +static int ssl_config(char *str, char **error_out) { - return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts); + return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts, + error_out); } static int ssl_get_config(char *dev, char *str, int size, char **error_out) @@ -91,9 +92,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out) size, error_out); } -static int ssl_remove(int n) +static int ssl_remove(int n, char **error_out) { - return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); + return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n, + error_out); } static int ssl_open(struct tty_struct *tty, struct file *filp) @@ -212,7 +214,15 @@ __uml_exitcall(ssl_exit); static int ssl_chan_setup(char *str) { - return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str); + char *error; + int ret; + + ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error); + if(ret < 0) + printk(KERN_ERR "Failed to set up serial line with " + "configuration string \"%s\" : %s\n", str, error); + + return 1; } __setup("ssl", ssl_chan_setup); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 9b2dd0b..3cbfe3a 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"); diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 49c047b..f4db97e 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -286,7 +286,7 @@ static int parse_unit(char **ptr) * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it * should not be freed on exit. */ -static int ubd_setup_common(char *str, int *index_out) +static int ubd_setup_common(char *str, int *index_out, char **error_out) { struct ubd *ubd_dev; struct openflags flags = global_openflags; @@ -302,56 +302,54 @@ static int ubd_setup_common(char *str, int *index_out) str++; if(!strcmp(str, "sync")){ global_openflags = of_sync(global_openflags); - return(0); + return 0; } major = simple_strtoul(str, &end, 0); if((*end != '\0') || (end == str)){ - printk(KERN_ERR - "ubd_setup : didn't parse major number\n"); - return(1); + *error_out = "Didn't parse major number"; + return -EINVAL; } - err = 1; - mutex_lock(&ubd_lock); - if(fake_major != MAJOR_NR){ - printk(KERN_ERR "Can't assign a fake major twice\n"); - goto out1; - } + err = -EINVAL; + mutex_lock(&ubd_lock); + if(fake_major != MAJOR_NR){ + *error_out = "Can't assign a fake major twice"; + goto out1; + } - fake_major = major; + fake_major = major; printk(KERN_INFO "Setting extra ubd major number to %d\n", major); - err = 0; - out1: - mutex_unlock(&ubd_lock); - return(err); + err = 0; + out1: + mutex_unlock(&ubd_lock); + return err; } n = parse_unit(&str); if(n < 0){ - printk(KERN_ERR "ubd_setup : couldn't parse unit number " - "'%s'\n", str); - return(1); + *error_out = "Couldn't parse device number"; + return -EINVAL; } if(n >= MAX_DEV){ - printk(KERN_ERR "ubd_setup : index %d out of range " - "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1); - return(1); + *error_out = "Device number out of range"; + return 1; } - err = 1; + err = -EBUSY; mutex_lock(&ubd_lock); ubd_dev = &ubd_devs[n]; if(ubd_dev->file != NULL){ - printk(KERN_ERR "ubd_setup : device already configured\n"); + *error_out = "Device is already configured"; goto out; } if (index_out) *index_out = n; + err = -EINVAL; for (i = 0; i < sizeof("rscd="); i++) { switch (*str) { case 'r': @@ -370,47 +368,54 @@ static int ubd_setup_common(char *str, int *index_out) str++; goto break_loop; default: - printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n"); + *error_out = "Expected '=' or flag letter " + "(r, s, c, or d)"; goto out; } str++; } - if (*str == '=') - printk(KERN_ERR "ubd_setup : Too many flags specified\n"); - else - printk(KERN_ERR "ubd_setup : Expected '='\n"); + if (*str == '=') + *error_out = "Too many flags specified"; + else + *error_out = "Missing '='"; goto out; break_loop: - err = 0; backing_file = strchr(str, ','); - if (!backing_file) { + if (backing_file == NULL) backing_file = strchr(str, ':'); - } - if(backing_file){ - if(ubd_dev->no_cow) - printk(KERN_ERR "Can't specify both 'd' and a " - "cow file\n"); + if(backing_file != NULL){ + if(ubd_dev->no_cow){ + *error_out = "Can't specify both 'd' and a cow file"; + goto out; + } else { *backing_file = '\0'; backing_file++; } } + err = 0; ubd_dev->file = str; ubd_dev->cow.file = backing_file; ubd_dev->boot_openflags = flags; out: mutex_unlock(&ubd_lock); - return(err); + return err; } static int ubd_setup(char *str) { - ubd_setup_common(str, NULL); - return(1); + char *error; + int err; + + err = ubd_setup_common(str, NULL, &error); + if(err) + printk(KERN_ERR "Failed to initialize device with \"%s\" : " + "%s\n", str, error); + return 1; } __setup("ubd", ubd_setup); @@ -422,7 +427,7 @@ __uml_help(ubd_setup, " use either a ':' or a ',': the first one allows writing things like;\n" " ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n" " while with a ',' the shell would not expand the 2nd '~'.\n" -" When using only one filename, UML will detect whether to thread it like\n" +" When using only one filename, UML will detect whether to treat it like\n" " a COW file or a backing file. To override this detection, add the 'd'\n" " flag:\n" " ubd0d=BackingFile\n" @@ -668,18 +673,19 @@ static int ubd_disk_register(int major, u64 size, int unit, #define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9)) -static int ubd_add(int n) +static int ubd_add(int n, char **error_out) { struct ubd *ubd_dev = &ubd_devs[n]; - int err; + int err = 0; - err = -ENODEV; if(ubd_dev->file == NULL) goto out; err = ubd_file_size(ubd_dev, &ubd_dev->size); - if(err < 0) + if(err < 0){ + *error_out = "Couldn't determine size of device's file"; goto out; + } ubd_dev->size = ROUND_BLOCK(ubd_dev->size); @@ -701,28 +707,31 @@ out: return err; } -static int ubd_config(char *str) +static int ubd_config(char *str, char **error_out) { int n, ret; + /* This string is possibly broken up and stored, so it's only + * freed if ubd_setup_common fails, or if only general options + * were set. + */ str = kstrdup(str, GFP_KERNEL); if (str == NULL) { - printk(KERN_ERR "ubd_config failed to strdup string\n"); - ret = 1; - goto out; + *error_out = "Failed to allocate memory"; + return -ENOMEM; } - ret = ubd_setup_common(str, &n); - if (ret) { - ret = -1; + + ret = ubd_setup_common(str, &n, error_out); + if (ret) goto err_free; - } + if (n == -1) { ret = 0; goto err_free; } mutex_lock(&ubd_lock); - ret = ubd_add(n); + ret = ubd_add(n, error_out); if (ret) ubd_devs[n].file = NULL; mutex_unlock(&ubd_lock); @@ -777,7 +786,7 @@ static int ubd_id(char **str, int *start_out, int *end_out) return n; } -static int ubd_remove(int n) +static int ubd_remove(int n, char **error_out) { struct ubd *ubd_dev; int err = -ENODEV; @@ -815,7 +824,9 @@ out: return err; } -/* All these are called by mconsole in process context and without ubd-specific locks. */ +/* All these are called by mconsole in process context and without + * ubd-specific locks. + */ static struct mc_device ubd_mc = { .name = "ubd", .config = ubd_config, @@ -851,7 +862,8 @@ static struct platform_driver ubd_driver = { static int __init ubd_init(void) { - int i; + char *error; + int i, err; if (register_blkdev(MAJOR_NR, "ubd")) return -1; @@ -870,8 +882,12 @@ static int __init ubd_init(void) return -1; } platform_driver_register(&ubd_driver); - for (i = 0; i < MAX_DEV; i++) - ubd_add(i); + for (i = 0; i < MAX_DEV; i++){ + err = ubd_add(i, &error); + if(err) + printk(KERN_ERR "Failed to initialize ubd device %d :" + "%s\n", i, error); + } return 0; } -- cgit v1.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') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 3cbfe3a..0b1bca4 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.1 From 190c3e456325942a17785332fe15b68eeb3775ca Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:55 -0800 Subject: [PATCH] uml: lock the irqs_to_free list Fix (i.e. add some) the locking around the irqs_to_free list. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 4e7e3cf..bce9b34 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -222,15 +222,28 @@ void enable_chan(struct line *line) } } +/* Items are added in IRQ context, when free_irq can't be called, and + * removed in process context, when it can. + * This handles interrupt sources which disappear, and which need to + * be permanently disabled. This is discovered in IRQ context, but + * the freeing of the IRQ must be done later. + */ +static DEFINE_SPINLOCK(irqs_to_free_lock); static LIST_HEAD(irqs_to_free); void free_irqs(void) { struct chan *chan; + LIST_HEAD(list); + struct list_head *ele; + + spin_lock_irq(&irqs_to_free_lock); + list_splice_init(&irqs_to_free, &list); + INIT_LIST_HEAD(&irqs_to_free); + spin_unlock_irq(&irqs_to_free_lock); - while(!list_empty(&irqs_to_free)){ - chan = list_entry(irqs_to_free.next, struct chan, free_list); - list_del(&chan->free_list); + list_for_each(ele, &list){ + chan = list_entry(ele, struct chan, free_list); if(chan->input) free_irq(chan->line->driver->read_irq, chan); @@ -246,7 +259,9 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) return; if(delay_free_irq){ + spin_lock_irq(&irqs_to_free_lock); list_add(&chan->free_list, &irqs_to_free); + spin_unlock_irq(&irqs_to_free_lock); } else { if(chan->input) -- cgit v1.1 From d3b7f69de2b92e4b6057d81e6c52f629a8663368 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:56 -0800 Subject: [PATCH] uml: add locking to network transport registration The registration of host network transports needed some locking. The transport list itself is locked, but calls to the registration routines are not. This is compensated for by checking that a transport structure is not yet on any list. I also took the opportunity to const all fields in the transport structure except the list, which obviously can be modified. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/net_kern.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 07e839e..b10154c 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -498,10 +498,8 @@ struct eth_init { int index; }; -/* Filled in at boot time. Will need locking if the transports become - * modular. - */ -struct list_head transports = LIST_HEAD_INIT(transports); +static DEFINE_SPINLOCK(transports_lock); +static LIST_HEAD(transports); /* Filled in during early boot */ struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); @@ -540,7 +538,10 @@ void register_transport(struct transport *new) char *mac = NULL; int match; + spin_lock(&transports_lock); + BUG_ON(!list_empty(&new->list)); list_add(&new->list, &transports); + spin_unlock(&transports_lock); list_for_each_safe(ele, next, ð_cmd_line){ eth = list_entry(ele, struct eth_init, list); -- cgit v1.1 From 4ea21cd9173a0ffa75dc74cc46d08dfc45654f29 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:56 -0800 Subject: [PATCH] uml: network driver whitespace and style fixes Some whitespace and coding style cleanups in the network driver code. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/net_kern.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index b10154c..eede892 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -108,7 +108,7 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) out: spin_unlock(&lp->lock); - return(IRQ_HANDLED); + return IRQ_HANDLED; } static int uml_net_open(struct net_device *dev) @@ -239,7 +239,7 @@ static int uml_net_set_mac(struct net_device *dev, void *addr) set_ether_mac(dev, hwaddr->sa_data); spin_unlock_irq(&lp->lock); - return(0); + return 0; } static int uml_net_change_mtu(struct net_device *dev, int new_mtu) @@ -460,7 +460,7 @@ static struct uml_net *find_device(int n) device = NULL; out: spin_unlock(&devices_lock); - return(device); + return device; } static int eth_parse(char *str, int *index_out, char **str_out, @@ -511,23 +511,23 @@ static int check_transport(struct transport *transport, char *eth, int n, len = strlen(transport->name); if(strncmp(eth, transport->name, len)) - return(0); + return 0; eth += len; if(*eth == ',') eth++; else if(*eth != '\0') - return(0); + return 0; *init_out = kmalloc(transport->setup_size, GFP_KERNEL); if(*init_out == NULL) - return(1); + return 1; if(!transport->setup(eth, mac_out, *init_out)){ kfree(*init_out); *init_out = NULL; } - return(1); + return 1; } void register_transport(struct transport *new) @@ -572,9 +572,9 @@ static int eth_setup_common(char *str, int index) eth_configure(index, init, mac, transport); kfree(init); } - return(1); + return 1; } - return(0); + return 0; } static int eth_setup(char *str) @@ -678,7 +678,7 @@ static int net_remove(int n, char **error_out) dev = device->dev; lp = dev->priv; if(lp->fd > 0) - return -EBUSY; + return -EBUSY; if(lp->remove != NULL) (*lp->remove)(&lp->user); unregister_netdev(dev); platform_device_unregister(&device->pdev); @@ -693,7 +693,7 @@ static struct mc_device net_mc = { .name = "eth", .config = net_config, .get_config = NULL, - .id = net_id, + .id = net_id, .remove = net_remove, }; @@ -706,7 +706,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, void (*proc)(unsigned char *, unsigned char *, void *); unsigned char addr_buf[4], netmask_buf[4]; - if(dev->open != uml_net_open) return(NOTIFY_DONE); + if(dev->open != uml_net_open) + return NOTIFY_DONE; lp = dev->priv; @@ -724,7 +725,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); (*proc)(addr_buf, netmask_buf, &lp->user); } - return(NOTIFY_DONE); + return NOTIFY_DONE; } struct notifier_block uml_inetaddr_notifier = { @@ -834,7 +835,7 @@ void *get_output_buffer(int *len_out) ret = (void *) __get_free_pages(GFP_KERNEL, 0); if(ret) *len_out = PAGE_SIZE; else *len_out = 0; - return(ret); + return ret; } void free_output_buffer(void *buffer) -- cgit v1.1 From 42d36115d25725fb551250c8f70602a12aa8dee2 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:57 -0800 Subject: [PATCH] uml: watchdog driver locking Replace BKL use with a spinlock. Also fix the control so that open doesn't return holding a lock. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/harddog_kern.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 64ff22a..94bbcb5 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -44,12 +44,13 @@ #include #include #include +#include #include #include "mconsole.h" MODULE_LICENSE("GPL"); -/* Locked by the BKL in harddog_open and harddog_release */ +static DEFINE_SPINLOCK(lock); static int timer_alive; static int harddog_in_fd = -1; static int harddog_out_fd = -1; @@ -62,12 +63,12 @@ extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); static int harddog_open(struct inode *inode, struct file *file) { - int err; + int err = -EBUSY; char *sock = NULL; - lock_kernel(); + spin_lock(&lock); if(timer_alive) - return -EBUSY; + goto err; #ifdef CONFIG_HARDDOG_NOWAYOUT __module_get(THIS_MODULE); #endif @@ -76,11 +77,15 @@ static int harddog_open(struct inode *inode, struct file *file) sock = mconsole_notify_socket(); #endif err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock); - if(err) return(err); + if(err) + goto err; timer_alive = 1; - unlock_kernel(); + spin_unlock(&lock); return nonseekable_open(inode, file); +err: + spin_unlock(&lock); + return err; } extern void stop_watchdog(int in_fd, int out_fd); @@ -90,14 +95,16 @@ static int harddog_release(struct inode *inode, struct file *file) /* * Shut off the timer. */ - lock_kernel(); + + spin_lock(&lock); stop_watchdog(harddog_in_fd, harddog_out_fd); harddog_in_fd = -1; harddog_out_fd = -1; timer_alive=0; - unlock_kernel(); + spin_unlock(&lock); + return 0; } -- cgit v1.1 From 5bbcbeca2c8933ee2b3402ea5eca523d971a8785 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:58 -0800 Subject: [PATCH] uml: watchdog driver formatting Whitespace and style fixes. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/harddog_kern.c | 33 +++++++++++---------------------- arch/um/drivers/harddog_user.c | 23 ++++++----------------- 2 files changed, 17 insertions(+), 39 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 94bbcb5..73c5caa 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -9,10 +9,10 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. * * (c) Copyright 1995 Alan Cox * @@ -29,11 +29,11 @@ * Made SMP safe for 2.3.x * * 20011127 Joel Becker (jlbec@evilplan.org> - * Added soft_noboot; Allows testing the softdog trigger without + * Added soft_noboot; Allows testing the softdog trigger without * requiring a recompile. * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. */ - + #include #include #include @@ -58,7 +58,7 @@ static int harddog_out_fd = -1; /* * Allow only one person to hold it open */ - + extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); static int harddog_open(struct inode *inode, struct file *file) @@ -69,7 +69,7 @@ static int harddog_open(struct inode *inode, struct file *file) spin_lock(&lock); if(timer_alive) goto err; -#ifdef CONFIG_HARDDOG_NOWAYOUT +#ifdef CONFIG_HARDDOG_NOWAYOUT __module_get(THIS_MODULE); #endif @@ -117,7 +117,7 @@ static ssize_t harddog_write(struct file *file, const char __user *data, size_t * Refresh the timer. */ if(len) - return(ping_watchdog(harddog_out_fd)); + return ping_watchdog(harddog_out_fd); return 0; } @@ -141,7 +141,7 @@ static int harddog_ioctl(struct inode *inode, struct file *file, case WDIOC_GETBOOTSTATUS: return put_user(0,(int __user *)argp); case WDIOC_KEEPALIVE: - return(ping_watchdog(harddog_out_fd)); + return ping_watchdog(harddog_out_fd); } } @@ -172,7 +172,7 @@ static int __init harddog_init(void) printk(banner); - return(0); + return 0; } static void __exit harddog_exit(void) @@ -182,14 +182,3 @@ static void __exit harddog_exit(void) module_init(harddog_init); module_exit(harddog_exit); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index def013b..c495ecf 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -38,7 +38,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) int in_fds[2], out_fds[2], pid, n, err; char pid_buf[sizeof("nnnnn\0")], c; char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; - char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, + char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, NULL }; char **args = NULL; @@ -96,7 +96,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) } *in_fd_ret = in_fds[0]; *out_fd_ret = out_fds[1]; - return(0); + return 0; out_close_in: os_close_file(in_fds[0]); @@ -105,7 +105,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) os_close_file(out_fds[0]); os_close_file(out_fds[1]); out: - return(err); + return err; } void stop_watchdog(int in_fd, int out_fd) @@ -123,20 +123,9 @@ int ping_watchdog(int fd) if(n != sizeof(c)){ printk("ping_watchdog - write failed, err = %d\n", -n); if(n < 0) - return(n); - return(-EIO); + return n; + return -EIO; } return 1; } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v1.1 From b612e475e75f860002d88dd8440ce250506c5094 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:43:59 -0800 Subject: [PATCH] uml: audio driver locking Comment the lack of locking and make a couple of variables static. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/hostaudio_kern.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index a0d148ea..f61fa05 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -25,9 +25,12 @@ struct hostmixer_state { #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" -/* Only changed from linux_main at boot time */ -char *dsp = HOSTAUDIO_DEV_DSP; -char *mixer = HOSTAUDIO_DEV_MIXER; +/* Changed either at boot time or module load time. At boot, this is + * single-threaded; at module load, multiple modules would each have + * their own copy of these variables. + */ +static char *dsp = HOSTAUDIO_DEV_DSP; +static char *mixer = HOSTAUDIO_DEV_MIXER; #define DSP_HELP \ " This is used to specify the host dsp device to the hostaudio driver.\n" \ -- cgit v1.1 From d471c0fca7eae1ffd4f7d4c11ee835ff70aaa71f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:00 -0800 Subject: [PATCH] uml: audio driver formatting Whitespace and style fixes. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/hostaudio_kern.c | 160 ++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 87 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index f61fa05..10e08a8 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -15,11 +15,11 @@ #include "os.h" struct hostaudio_state { - int fd; + int fd; }; struct hostmixer_state { - int fd; + int fd; }; #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" @@ -72,12 +72,12 @@ MODULE_PARM_DESC(mixer, MIXER_HELP); static ssize_t hostaudio_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct hostaudio_state *state = file->private_data; + struct hostaudio_state *state = file->private_data; void *kbuf; int err; #ifdef DEBUG - printk("hostaudio: read called, count = %d\n", count); + printk("hostaudio: read called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); @@ -91,7 +91,7 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer, if(copy_to_user(buffer, kbuf, err)) err = -EFAULT; - out: +out: kfree(kbuf); return(err); } @@ -99,12 +99,12 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer, static ssize_t hostaudio_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct hostaudio_state *state = file->private_data; + struct hostaudio_state *state = file->private_data; void *kbuf; int err; #ifdef DEBUG - printk("hostaudio: write called, count = %d\n", count); + printk("hostaudio: write called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); @@ -128,24 +128,24 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer, static unsigned int hostaudio_poll(struct file *file, struct poll_table_struct *wait) { - unsigned int mask = 0; + unsigned int mask = 0; #ifdef DEBUG - printk("hostaudio: poll called (unimplemented)\n"); + printk("hostaudio: poll called (unimplemented)\n"); #endif - return(mask); + return(mask); } static int hostaudio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct hostaudio_state *state = file->private_data; + struct hostaudio_state *state = file->private_data; unsigned long data = 0; int err; #ifdef DEBUG - printk("hostaudio: ioctl called, cmd = %u\n", cmd); + printk("hostaudio: ioctl called, cmd = %u\n", cmd); #endif switch(cmd){ case SNDCTL_DSP_SPEED: @@ -182,42 +182,40 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, static int hostaudio_open(struct inode *inode, struct file *file) { - struct hostaudio_state *state; - int r = 0, w = 0; - int ret; + struct hostaudio_state *state; + int r = 0, w = 0; + int ret; #ifdef DEBUG - printk("hostaudio: open called (host: %s)\n", dsp); + printk("hostaudio: open called (host: %s)\n", dsp); #endif - state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); - if(state == NULL) + state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); + if(state == NULL) return(-ENOMEM); - if(file->f_mode & FMODE_READ) r = 1; - if(file->f_mode & FMODE_WRITE) w = 1; + if(file->f_mode & FMODE_READ) r = 1; + if(file->f_mode & FMODE_WRITE) w = 1; ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); - if(ret < 0){ + if(ret < 0){ kfree(state); return(ret); - } - + } state->fd = ret; - file->private_data = state; - return(0); + file->private_data = state; + return(0); } static int hostaudio_release(struct inode *inode, struct file *file) { - struct hostaudio_state *state = file->private_data; + struct hostaudio_state *state = file->private_data; #ifdef DEBUG - printk("hostaudio: release called\n"); + printk("hostaudio: release called\n"); #endif - - os_close_file(state->fd); - kfree(state); + os_close_file(state->fd); + kfree(state); return(0); } @@ -227,10 +225,10 @@ static int hostaudio_release(struct inode *inode, struct file *file) static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct hostmixer_state *state = file->private_data; + struct hostmixer_state *state = file->private_data; #ifdef DEBUG - printk("hostmixer: ioctl called\n"); + printk("hostmixer: ioctl called\n"); #endif return(os_ioctl_generic(state->fd, cmd, arg)); @@ -238,68 +236,67 @@ static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, static int hostmixer_open_mixdev(struct inode *inode, struct file *file) { - struct hostmixer_state *state; - int r = 0, w = 0; - int ret; + struct hostmixer_state *state; + int r = 0, w = 0; + int ret; #ifdef DEBUG - printk("hostmixer: open called (host: %s)\n", mixer); + printk("hostmixer: open called (host: %s)\n", mixer); #endif - state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); - if(state == NULL) return(-ENOMEM); + state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); + if(state == NULL) return(-ENOMEM); - if(file->f_mode & FMODE_READ) r = 1; - if(file->f_mode & FMODE_WRITE) w = 1; + if(file->f_mode & FMODE_READ) r = 1; + if(file->f_mode & FMODE_WRITE) w = 1; ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); - if(ret < 0){ + if(ret < 0){ printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", dsp, -ret); kfree(state); return(ret); - } + } - file->private_data = state; - return(0); + file->private_data = state; + return(0); } static int hostmixer_release(struct inode *inode, struct file *file) { - struct hostmixer_state *state = file->private_data; + struct hostmixer_state *state = file->private_data; #ifdef DEBUG - printk("hostmixer: release called\n"); + printk("hostmixer: release called\n"); #endif - os_close_file(state->fd); - kfree(state); + os_close_file(state->fd); + kfree(state); return(0); } - /* kernel module operations */ static const struct file_operations hostaudio_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = hostaudio_read, - .write = hostaudio_write, - .poll = hostaudio_poll, - .ioctl = hostaudio_ioctl, - .mmap = NULL, - .open = hostaudio_open, - .release = hostaudio_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = hostaudio_read, + .write = hostaudio_write, + .poll = hostaudio_poll, + .ioctl = hostaudio_ioctl, + .mmap = NULL, + .open = hostaudio_open, + .release = hostaudio_release, }; static const struct file_operations hostmixer_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = hostmixer_ioctl_mixdev, - .open = hostmixer_open_mixdev, - .release = hostmixer_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = hostmixer_ioctl_mixdev, + .open = hostmixer_open_mixdev, + .release = hostmixer_release, }; struct { @@ -313,42 +310,31 @@ MODULE_LICENSE("GPL"); static int __init hostaudio_init_module(void) { - printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", + printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", dsp, mixer); module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); - if(module_data.dev_audio < 0){ - printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); - return -ENODEV; - } + if(module_data.dev_audio < 0){ + printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); + return -ENODEV; + } module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); - if(module_data.dev_mixer < 0){ - printk(KERN_ERR "hostmixer: couldn't register mixer " + if(module_data.dev_mixer < 0){ + printk(KERN_ERR "hostmixer: couldn't register mixer " "device!\n"); - unregister_sound_dsp(module_data.dev_audio); - return -ENODEV; - } + unregister_sound_dsp(module_data.dev_audio); + return -ENODEV; + } - return 0; + return 0; } static void __exit hostaudio_cleanup_module (void) { - unregister_sound_mixer(module_data.dev_mixer); - unregister_sound_dsp(module_data.dev_audio); + unregister_sound_mixer(module_data.dev_mixer); + unregister_sound_dsp(module_data.dev_audio); } module_init(hostaudio_init_module); module_exit(hostaudio_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v1.1 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 +++++++++++++++------ arch/um/drivers/net_kern.c | 1 + arch/um/drivers/ssl.c | 1 + arch/um/drivers/ubd_kern.c | 1 + 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 832d5c7..b4dbd10 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 diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index eede892..c183864 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -690,6 +690,7 @@ static int net_remove(int n, char **error_out) } static struct mc_device net_mc = { + .list = LIST_HEAD_INIT(net_mc.list), .name = "eth", .config = net_config, .get_config = NULL, diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 1e82430..fe400ac 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -64,6 +64,7 @@ static struct line_driver driver = { .symlink_from = "serial", .symlink_to = "tts", .mc = { + .list = LIST_HEAD_INIT(driver.mc.list), .name = "ssl", .config = ssl_config, .get_config = ssl_get_config, diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index f4db97e..c1d40fb 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -828,6 +828,7 @@ out: * ubd-specific locks. */ static struct mc_device ubd_mc = { + .list = LIST_HEAD_INIT(ubd_mc.list), .name = "ubd", .config = ubd_config, .get_config = ubd_get_config, -- cgit v1.1 From d832fc60d533d52da7170cf5f95271c331259bca Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:01 -0800 Subject: [PATCH] uml: make two variables static Make a couple of variables static. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/port_kern.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 6dfe632..c688da7 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -129,8 +129,8 @@ static int port_accept(struct port_list *port) return(ret); } -DECLARE_MUTEX(ports_sem); -struct list_head ports = LIST_HEAD_INIT(ports); +static DECLARE_MUTEX(ports_sem); +static struct list_head ports = LIST_HEAD_INIT(ports); void port_work_proc(struct work_struct *unused) { -- cgit v1.1 From 67608e0c809ceca1b44755ee818199af7478ca77 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:02 -0800 Subject: [PATCH] uml: port driver formatting Whitespace and style fixes. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/port_kern.c | 46 ++++++++++++++++++++-------------------- arch/um/drivers/port_user.c | 51 ++++++++++++++++++--------------------------- 2 files changed, 43 insertions(+), 54 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index c688da7..4dd7d8a 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -55,9 +55,9 @@ static irqreturn_t pipe_interrupt(int irq, void *data) fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); if(fd < 0){ if(fd == -EAGAIN) - return(IRQ_NONE); + return IRQ_NONE; - printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", + printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -fd); os_close_file(conn->fd); } @@ -68,7 +68,7 @@ static irqreturn_t pipe_interrupt(int irq, void *data) list_add(&conn->list, &conn->port->connections); complete(&conn->port->done); - return(IRQ_HANDLED); + return IRQ_HANDLED; } #define NO_WAITER_MSG \ @@ -97,14 +97,14 @@ static int port_accept(struct port_list *port) "connection\n"); goto out_close; } - *conn = ((struct connection) + *conn = ((struct connection) { .list = LIST_HEAD_INIT(conn->list), .fd = fd, .socket = { socket[0], socket[1] }, .telnetd_pid = pid, .port = port }); - if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, + if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "telnetd", conn)){ printk(KERN_ERR "port_accept : failed to get IRQ for " @@ -117,17 +117,17 @@ static int port_accept(struct port_list *port) printk("No one waiting for port\n"); } list_add(&conn->list, &port->pending); - return(1); + return 1; out_free: kfree(conn); out_close: os_close_file(fd); - if(pid != -1) + if(pid != -1) os_kill_process(pid, 1); out: - return(ret); -} + return ret; +} static DECLARE_MUTEX(ports_sem); static struct list_head ports = LIST_HEAD_INIT(ports); @@ -158,8 +158,8 @@ static irqreturn_t port_interrupt(int irq, void *data) port->has_connection = 1; schedule_work(&port_work); - return(IRQ_HANDLED); -} + return IRQ_HANDLED; +} void *port_data(int port_num) { @@ -185,14 +185,14 @@ void *port_data(int port_num) port_num, -fd); goto out_free; } - if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "port", - port)){ + if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, + "port", port)){ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); goto out_close; } - *port = ((struct port_list) + *port = ((struct port_list) { .list = LIST_HEAD_INIT(port->list), .wait_count = ATOMIC_INIT(0), .has_connection = 0, @@ -222,7 +222,7 @@ void *port_data(int port_num) os_close_file(fd); out: up(&ports_sem); - return(dev); + return dev; } int port_wait(void *data) @@ -232,15 +232,15 @@ int port_wait(void *data) struct port_list *port = dev->port; int fd; - atomic_inc(&port->wait_count); + atomic_inc(&port->wait_count); while(1){ fd = -ERESTARTSYS; - if(wait_for_completion_interruptible(&port->done)) - goto out; + if(wait_for_completion_interruptible(&port->done)) + goto out; spin_lock(&port->lock); - conn = list_entry(port->connections.next, struct connection, + conn = list_entry(port->connections.next, struct connection, list); list_del(&conn->list); spin_unlock(&port->lock); @@ -248,12 +248,12 @@ int port_wait(void *data) os_shutdown_socket(conn->socket[0], 1, 1); os_close_file(conn->socket[0]); os_shutdown_socket(conn->socket[1], 1, 1); - os_close_file(conn->socket[1]); + os_close_file(conn->socket[1]); /* This is done here because freeing an IRQ can't be done * within the IRQ handler. So, pipe_interrupt always ups * the semaphore regardless of whether it got a successful - * connection. Then we loop here throwing out failed + * connection. Then we loop here throwing out failed * connections until a good one is found. */ free_irq(TELNETD_IRQ, conn); diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index bc6afaf..8050802 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -38,18 +38,18 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) if(*str != ':'){ printk("port_init : channel type 'port' must specify a " "port number\n"); - return(NULL); + return NULL; } str++; port = strtoul(str, &end, 0); if((*end != '\0') || (end == str)){ printk("port_init : couldn't parse port '%s'\n", str); - return(NULL); + return NULL; } kern_data = port_data(port); if(kern_data == NULL) - return(NULL); + return NULL; data = um_kmalloc(sizeof(*data)); if(data == NULL) @@ -59,10 +59,10 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) .kernel_data = kern_data }); sprintf(data->dev, "%d", port); - return(data); + return data; err: port_kern_free(kern_data); - return(NULL); + return NULL; } static void port_free(void *d) @@ -83,14 +83,14 @@ static int port_open(int input, int output, int primary, void *d, if((fd >= 0) && data->raw){ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); if(err) - return(err); + return err; err = raw(fd); if(err) - return(err); + return err; } *dev_out = data->dev; - return(fd); + return fd; } static void port_close(int fd, void *d) @@ -120,8 +120,8 @@ int port_listen_fd(int port) int fd, err, arg; fd = socket(PF_INET, SOCK_STREAM, 0); - if(fd == -1) - return(-errno); + if(fd == -1) + return -errno; arg = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ @@ -136,7 +136,7 @@ int port_listen_fd(int port) err = -errno; goto out; } - + if(listen(fd, 1) < 0){ err = -errno; goto out; @@ -146,10 +146,10 @@ int port_listen_fd(int port) if(err < 0) goto out; - return(fd); + return fd; out: os_close_file(fd); - return(err); + return err; } struct port_pre_exec_data { @@ -173,13 +173,13 @@ void port_pre_exec(void *arg) int port_connection(int fd, int *socket, int *pid_out) { int new, err; - char *argv[] = { "/usr/sbin/in.telnetd", "-L", + char *argv[] = { "/usr/sbin/in.telnetd", "-L", "/usr/lib/uml/port-helper", NULL }; struct port_pre_exec_data data; new = os_accept_connection(fd); if(new < 0) - return(new); + return new; err = os_pipe(socket, 0, 0); if(err < 0) @@ -190,29 +190,18 @@ int port_connection(int fd, int *socket, int *pid_out) .pipe_fd = socket[1] }); err = run_helper(port_pre_exec, &data, argv, NULL); - if(err < 0) + if(err < 0) goto out_shutdown; *pid_out = err; - return(new); + return new; out_shutdown: os_shutdown_socket(socket[0], 1, 1); os_close_file(socket[0]); - os_shutdown_socket(socket[1], 1, 1); + os_shutdown_socket(socket[1], 1, 1); os_close_file(socket[1]); out_close: os_close_file(new); - return(err); + return err; } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v1.1 From c862fc32a3ee4319c652f4ff39462d030120c380 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:04 -0800 Subject: [PATCH] uml: network driver locking and code cleanup Add some missing locking to walks of the transports and opened lists. Delete some dead code. Comment the lack of some locking. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/net_kern.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index c183864..04e31f8 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -502,7 +502,7 @@ static DEFINE_SPINLOCK(transports_lock); static LIST_HEAD(transports); /* Filled in during early boot */ -struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); +static LIST_HEAD(eth_cmd_line); static int check_transport(struct transport *transport, char *eth, int n, void **init_out, char **mac_out) @@ -563,7 +563,9 @@ static int eth_setup_common(char *str, int index) struct transport *transport; void *init; char *mac = NULL; + int found = 0; + spin_lock(&transports_lock); list_for_each(ele, &transports){ transport = list_entry(ele, struct transport, list); if(!check_transport(transport, str, index, &init, &mac)) @@ -572,9 +574,12 @@ static int eth_setup_common(char *str, int index) eth_configure(index, init, mac, transport); kfree(init); } - return 1; + found = 1; + break; } - return 0; + + spin_unlock(&transports_lock); + return found; } static int eth_setup(char *str) @@ -610,24 +615,6 @@ __uml_help(eth_setup, " Configure a network device.\n\n" ); -#if 0 -static int eth_init(void) -{ - struct list_head *ele, *next; - struct eth_init *eth; - - list_for_each_safe(ele, next, ð_cmd_line){ - eth = list_entry(ele, struct eth_init, list); - - if(eth_setup_common(eth->init, eth->index)) - list_del(ð->list); - } - - return(1); -} -__initcall(eth_init); -#endif - static int net_config(char *str, char **error_out) { int n, err; @@ -729,6 +716,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, return NOTIFY_DONE; } +/* uml_net_init shouldn't be called twice on two CPUs at the same time */ struct notifier_block uml_inetaddr_notifier = { .notifier_call = uml_inetaddr_event, }; @@ -747,18 +735,21 @@ static int uml_net_init(void) * didn't get a chance to run for them. This fakes it so that * addresses which have already been set up get handled properly. */ + spin_lock(&opened_lock); list_for_each(ele, &opened){ lp = list_entry(ele, struct uml_net_private, list); ip = lp->dev->ip_ptr; - if(ip == NULL) continue; + if(ip == NULL) + continue; in = ip->ifa_list; while(in != NULL){ uml_inetaddr_event(NULL, NETDEV_UP, in); in = in->ifa_next; } } + spin_unlock(&opened_lock); - return(0); + return 0; } __initcall(uml_net_init); @@ -768,13 +759,16 @@ static void close_devices(void) struct list_head *ele; struct uml_net_private *lp; + spin_lock(&opened_lock); list_for_each(ele, &opened){ lp = list_entry(ele, struct uml_net_private, list); free_irq(lp->dev->irq, lp->dev); if((lp->close != NULL) && (lp->fd >= 0)) (*lp->close)(lp->fd, &lp->user); - if(lp->remove != NULL) (*lp->remove)(&lp->user); + if(lp->remove != NULL) + (*lp->remove)(&lp->user); } + spin_unlock(&opened_lock); } __uml_exitcall(close_devices); -- cgit v1.1 From c59bce6262f9511c8e2504231f60609bf7332833 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:04 -0800 Subject: [PATCH] uml: use LIST_HEAD where possible A couple of list_head declarations can be improved through the use of LIST_HEAD(). 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 | 2 +- arch/um/drivers/port_kern.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index b4dbd10..a5a683d 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -371,7 +371,7 @@ struct unplugged_pages { 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 LIST_HEAD(unplugged_pages); static int unplug_index = UNPLUGGED_PER_PAGE; static int mem_config(char *str, char **error_out) diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 4dd7d8a..1c8efd9 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -130,7 +130,7 @@ static int port_accept(struct port_list *port) } static DECLARE_MUTEX(ports_sem); -static struct list_head ports = LIST_HEAD_INIT(ports); +static LIST_HEAD(ports); void port_work_proc(struct work_struct *unused) { -- cgit v1.1 From 99b0278f95fc9d55adf65133dc678167a88b632a Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:05 -0800 Subject: [PATCH] uml: locking commentary in the random driver Comment the lack of locking. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 73b2bdd..e942e83 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -78,6 +78,7 @@ static const struct file_operations rng_chrdev_ops = { .read = rng_dev_read, }; +/* rng_init shouldn't be called more than once at boot time */ static struct miscdevice rng_miscdev = { RNG_MISCDEV_MINOR, RNG_MODULE_NAME, -- cgit v1.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/chan_kern.c | 5 ++--- arch/um/drivers/ssl.c | 3 ++- arch/um/drivers/stdio_console.c | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index bce9b34..7b8baf1 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -354,8 +354,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) return ret; } -int console_open_chan(struct line *line, struct console *co, - const struct chan_opts *opts) +int console_open_chan(struct line *line, struct console *co) { int err; @@ -363,7 +362,7 @@ int console_open_chan(struct line *line, struct console *co, if(err) return err; - printk("Console initialized on /dev/%s%d\n",co->name,co->index); + printk("Console initialized on /dev/%s%d\n", co->name, co->index); return 0; } diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index fe400ac..475de52 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -38,6 +38,7 @@ static void ssl_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 = ssl_announce, .xterm_title = "Serial Line #%d", @@ -171,7 +172,7 @@ static int ssl_console_setup(struct console *co, char *options) { struct line *line = &serial_lines[co->index]; - return console_open_chan(line, co, &opts); + return console_open_chan(line, co); } static struct console ssl_cons = { diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 0b1bca4..a83c42c 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.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/line.c | 7 +++---- arch/um/drivers/ssl.c | 16 +++++++--------- arch/um/drivers/stdio_console.c | 17 +++++++---------- 3 files changed, 17 insertions(+), 23 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index e620ed46..433e572 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -707,10 +707,9 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) return err; } -struct tty_driver *line_register_devfs(struct lines *set, - struct line_driver *line_driver, - const struct tty_operations *ops, - struct line *lines, int nlines) +struct tty_driver *register_lines(struct line_driver *line_driver, + const struct tty_operations *ops, + struct line *lines, int nlines) { int i; struct tty_driver *driver = alloc_tty_driver(nlines); diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 475de52..fc22b9b 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -51,6 +51,8 @@ static int ssl_config(char *str, char **error_out); static int ssl_get_config(char *dev, char *str, int size, char **error_out); static int ssl_remove(int n, char **error_out); + +/* Const, except for .mc.list */ static struct line_driver driver = { .name = "UML serial line", .device_name = "ttyS", @@ -62,8 +64,6 @@ static struct line_driver driver = { .read_irq_name = "ssl", .write_irq = SSL_WRITE_IRQ, .write_irq_name = "ssl-write", - .symlink_from = "serial", - .symlink_to = "tts", .mc = { .list = LIST_HEAD_INIT(driver.mc.list), .name = "ssl", @@ -74,14 +74,12 @@ static struct line_driver driver = { }, }; -/* 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 serial_lines[NR_PORTS] = { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; -static struct lines lines = LINES_INIT(NR_PORTS); - static int ssl_config(char *str, char **error_out) { return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts, @@ -175,6 +173,7 @@ static int ssl_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 ssl_cons = { .name = "ttyS", .write = ssl_console_write, @@ -190,9 +189,8 @@ static int ssl_init(void) printk(KERN_INFO "Initializing software serial port version %d\n", ssl_version); - ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, - serial_lines, - ARRAY_SIZE(serial_lines)); + ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, + ARRAY_SIZE(serial_lines)); lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index a83c42c..8dccdd1 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.1 From c6256c68248cfccbeec07ced442ffe395fa393e8 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:08 -0800 Subject: [PATCH] uml: fix previous console locking Eliminate the open_mutex after complaints from Blaisorblade. It turns out that the tty count provides the information needed to tell whether we are the first opener or last closer. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 48 ++++++++---------------------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 433e572..0e1e9a2 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -425,42 +425,15 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) * However, in this case, mconsole requests can come in "from the * side", and race with opens and closes. * - * The problem comes from line_setup not wanting to sleep if - * the device is open or being opened. This can happen because the - * first opener of a device is responsible for setting it up on the - * host, and that can sleep. The open of a port device will sleep - * until someone telnets to it. + * mconsole config requests will want to be sure the device isn't in + * use, and get_config, open, and close will want a stable + * configuration. The checking and modification of the configuration + * is done under a spinlock. Checking whether the device is in use is + * line->tty->count > 1, also under the spinlock. * - * The obvious solution of putting everything under a mutex fails - * because then trying (and failing) to change the configuration of an - * open(ing) device will block until the open finishes. The right - * thing to happen is for it to fail immediately. - * - * We can put the opening (and closing) of the host device under a - * separate lock, but that has to be taken before the count lock is - * released. Otherwise, you open a window in which another open can - * come through and assume that the host side is opened and working. - * - * So, if the tty count is one, open will take the open mutex - * inside the count lock. Otherwise, it just returns. This will sleep - * if the last close is pending, and will block a setup or get_config, - * but that should not last long. - * - * So, what we end up with is that open and close take the count lock. - * If the first open or last close are happening, then the open mutex - * is taken inside the count lock and the host opening or closing is done. - * - * setup and get_config only take the count lock. setup modifies the - * device configuration only if the open count is zero. Arbitrarily - * long blocking of setup doesn't happen because something would have to be - * waiting for an open to happen. However, a second open with - * tty->count == 1 can't happen, and a close can't happen until the open - * had finished. - * - * We can't maintain our own count here because the tty layer doesn't - * match opens and closes. It will call close if an open failed, and - * a tty hangup will result in excess closes. So, we rely on - * tty->count instead. It is one on both the first open and last close. + * tty->count serves to decide whether the device should be enabled or + * disabled on the host. If it's equal to 1, then we are doing the + * first open or last close. Otherwise, open and close just return. */ int line_open(struct line *lines, struct tty_struct *tty) @@ -476,7 +449,6 @@ int line_open(struct line *lines, struct tty_struct *tty) if(tty->count > 1) goto out_unlock; - mutex_lock(&line->open_mutex); spin_unlock(&line->count_lock); tty->driver_data = line; @@ -493,7 +465,6 @@ int line_open(struct line *lines, struct tty_struct *tty) chan_window_size(&line->chan_list, &tty->winsize.ws_row, &tty->winsize.ws_col); - mutex_unlock(&line->open_mutex); return err; out_unlock: @@ -523,7 +494,6 @@ void line_close(struct tty_struct *tty, struct file * filp) if(tty->count > 1) goto out_unlock; - mutex_lock(&line->open_mutex); spin_unlock(&line->count_lock); line->tty = NULL; @@ -534,7 +504,6 @@ void line_close(struct tty_struct *tty, struct file * filp) line->sigio = 0; } - mutex_unlock(&line->open_mutex); return; out_unlock: @@ -755,7 +724,6 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) for(i = 0; i < nlines; i++){ line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); - mutex_init(&line->open_mutex); if(line->init_str == NULL) continue; -- cgit v1.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') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 8dccdd1..7ff0b0f 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.1 From 62f96cb01e8de7a5daee472e540f726db2801499 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:16 -0800 Subject: [PATCH] uml: add per-device queues and locks to ubd driver Replace global queue and lock with per-device queues and locks. Mostly a straightforward replacement of ubd_io_lock with dev->lock and ubd_queue with dev->queue. Complications - There was no way to get a request struct (and queue) from the structure sent to the io_thread, so a pointer to the request was added. This is needed in ubd_handler in order to kick do_ubd_request to process another request. Queue initialization is moved from ubd_init to ubd_add. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 70 ++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index c1d40fb..d863482 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -56,6 +56,7 @@ enum ubd_req { UBD_READ, UBD_WRITE }; struct io_thread_req { + struct request *req; enum ubd_req op; int fds[2]; unsigned long offsets[2]; @@ -106,10 +107,6 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) #define DRIVER_NAME "uml-blkdev" -/* Can be taken in interrupt context, and is passed to the block layer to lock - * the request queue. Kernel side code knows that. */ -static DEFINE_SPINLOCK(ubd_io_lock); - static DEFINE_MUTEX(ubd_lock); /* XXX - this made sense in 2.4 days, now it's only used as a boolean, and @@ -132,9 +129,6 @@ static struct block_device_operations ubd_blops = { .getgeo = ubd_getgeo, }; -/* Protected by the queue_lock */ -static request_queue_t *ubd_queue; - /* Protected by ubd_lock */ static int fake_major = MAJOR_NR; @@ -178,6 +172,8 @@ struct ubd { unsigned no_cow:1; struct cow cow; struct platform_device pdev; + struct request_queue *queue; + spinlock_t lock; }; #define DEFAULT_COW { \ @@ -198,6 +194,7 @@ struct ubd { .no_cow = 0, \ .shared = 0, \ .cow = DEFAULT_COW, \ + .lock = SPIN_LOCK_UNLOCKED, \ } struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; @@ -504,17 +501,20 @@ static void __ubd_finish(struct request *req, int error) * spin_lock_irq()/spin_lock_irqsave() */ static inline void ubd_finish(struct request *req, int error) { - spin_lock(&ubd_io_lock); + struct ubd *dev = req->rq_disk->private_data; + + spin_lock(&dev->lock); __ubd_finish(req, error); - spin_unlock(&ubd_io_lock); + spin_unlock(&dev->lock); } /* XXX - move this inside ubd_intr. */ -/* Called without ubd_io_lock held, and only in interrupt context. */ +/* Called without dev->lock held, and only in interrupt context. */ static void ubd_handler(void) { struct io_thread_req req; - struct request *rq = elv_next_request(ubd_queue); + struct request *rq; + struct ubd *dev; int n; do_ubd = 0; @@ -523,17 +523,17 @@ static void ubd_handler(void) if(n != sizeof(req)){ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " "err = %d\n", os_getpid(), -n); - spin_lock(&ubd_io_lock); - end_request(rq, 0); - spin_unlock(&ubd_io_lock); return; } + rq = req.req; + dev = rq->rq_disk->private_data; + ubd_finish(rq, req.error); - reactivate_fd(thread_fd, UBD_IRQ); - spin_lock(&ubd_io_lock); - do_ubd_request(ubd_queue); - spin_unlock(&ubd_io_lock); + reactivate_fd(thread_fd, UBD_IRQ); + spin_lock(&dev->lock); + do_ubd_request(dev->queue); + spin_unlock(&dev->lock); } static irqreturn_t ubd_intr(int irq, void *dev) @@ -664,7 +664,7 @@ static int ubd_disk_register(int major, u64 size, int unit, } disk->private_data = &ubd_devs[unit]; - disk->queue = ubd_queue; + disk->queue = ubd_devs[unit].queue; add_disk(disk); *disk_out = disk; @@ -689,13 +689,23 @@ static int ubd_add(int n, char **error_out) ubd_dev->size = ROUND_BLOCK(ubd_dev->size); - err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); - if(err) + err = -ENOMEM; + ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); + if (ubd_dev->queue == NULL) { + *error_out = "Failed to initialize device queue"; goto out; + } + ubd_dev->queue->queuedata = ubd_dev; + + err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); + if(err){ + *error_out = "Failed to register device"; + goto out_cleanup; + } if(fake_major != MAJOR_NR) ubd_disk_register(fake_major, ubd_dev->size, n, - &fake_gendisk[n]); + &fake_gendisk[n]); /* perhaps this should also be under the "if (fake_major)" above */ /* using the fake_disk->disk_name and also the fakehd_set name */ @@ -705,6 +715,10 @@ static int ubd_add(int n, char **error_out) err = 0; out: return err; + +out_cleanup: + blk_cleanup_queue(ubd_dev->queue); + goto out; } static int ubd_config(char *str, char **error_out) @@ -816,6 +830,7 @@ static int ubd_remove(int n, char **error_out) fake_gendisk[n] = NULL; } + blk_cleanup_queue(ubd_dev->queue); platform_device_unregister(&ubd_dev->pdev); *ubd_dev = ((struct ubd) DEFAULT_UBD); err = 0; @@ -869,12 +884,6 @@ static int __init ubd_init(void) if (register_blkdev(MAJOR_NR, "ubd")) return -1; - ubd_queue = blk_init_queue(do_ubd_request, &ubd_io_lock); - if (!ubd_queue) { - unregister_blkdev(MAJOR_NR, "ubd"); - return -1; - } - if (fake_major != MAJOR_NR) { char name[sizeof("ubd_nnn\0")]; @@ -1020,7 +1029,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, req->bitmap_words, bitmap_len); } -/* Called with ubd_io_lock held */ +/* Called with dev->lock held */ static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; @@ -1039,6 +1048,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) offset = ((__u64) req->sector) << 9; len = req->current_nr_sectors << 9; + io_req->req = req; io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; io_req->fds[1] = ubd_dev->fd; io_req->cow_offset = -1; @@ -1060,7 +1070,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) return(0); } -/* Called with ubd_io_lock held */ +/* Called with dev->lock held */ static void do_ubd_request(request_queue_t *q) { struct io_thread_req io_req; -- cgit v1.1 From b8831a1d2c78c03b8193ab3acf56664fa3457265 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:17 -0800 Subject: [PATCH] uml: locking fixes in the ubd driver Some small locking and formatting fixes in the ubd driver. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index d863482..da0badc 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -131,7 +131,6 @@ static struct block_device_operations ubd_blops = { /* Protected by ubd_lock */ static int fake_major = MAJOR_NR; - static struct gendisk *ubd_gendisk[MAX_DEV]; static struct gendisk *fake_gendisk[MAX_DEV]; @@ -142,10 +141,6 @@ static struct gendisk *fake_gendisk[MAX_DEV]; #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \ .cl = 1 }) #endif - -/* Not protected - changed only in ubd_setup_common and then only to - * to enable O_SYNC. - */ static struct openflags global_openflags = OPEN_FLAGS; struct cow { @@ -197,6 +192,7 @@ struct ubd { .lock = SPIN_LOCK_UNLOCKED, \ } +/* Protected by ubd_lock */ struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; /* Only changed by fake_ide_setup which is a setup */ @@ -288,7 +284,7 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out) struct ubd *ubd_dev; struct openflags flags = global_openflags; char *backing_file; - int n, err, i; + int n, err = 0, i; if(index_out) *index_out = -1; n = *str; @@ -299,15 +295,16 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out) str++; if(!strcmp(str, "sync")){ global_openflags = of_sync(global_openflags); - return 0; + goto out1; } + + err = -EINVAL; major = simple_strtoul(str, &end, 0); if((*end != '\0') || (end == str)){ *error_out = "Didn't parse major number"; - return -EINVAL; + goto out1; } - err = -EINVAL; mutex_lock(&ubd_lock); if(fake_major != MAJOR_NR){ *error_out = "Can't assign a fake major twice"; @@ -473,12 +470,6 @@ static void do_ubd_request(request_queue_t * q); /* Only changed by ubd_init, which is an initcall. */ int thread_fd = -1; -/* Changed by ubd_handler, which is serialized because interrupts only - * happen on CPU 0. - * XXX: currently unused. - */ -static int intr_count = 0; - /* call ubd_finish if you need to serialize */ static void __ubd_finish(struct request *req, int error) { @@ -518,7 +509,6 @@ static void ubd_handler(void) int n; do_ubd = 0; - intr_count++; n = os_read_file(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " @@ -637,8 +627,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) } static int ubd_disk_register(int major, u64 size, int unit, - struct gendisk **disk_out) - + struct gendisk **disk_out) { struct gendisk *disk; @@ -840,7 +829,7 @@ out: } /* All these are called by mconsole in process context and without - * ubd-specific locks. + * ubd-specific locks. The structure itself is const except for .list. */ static struct mc_device ubd_mc = { .list = LIST_HEAD_INIT(ubd_mc.list), @@ -863,13 +852,17 @@ static int __init ubd0_init(void) { struct ubd *ubd_dev = &ubd_devs[0]; + mutex_lock(&ubd_lock); if(ubd_dev->file == NULL) ubd_dev->file = "root_fs"; + mutex_unlock(&ubd_lock); + return(0); } __initcall(ubd0_init); +/* Used in ubd_init, which is an initcall */ static struct platform_driver ubd_driver = { .driver = { .name = DRIVER_NAME, @@ -892,12 +885,14 @@ static int __init ubd_init(void) return -1; } platform_driver_register(&ubd_driver); + mutex_lock(&ubd_lock); for (i = 0; i < MAX_DEV; i++){ err = ubd_add(i, &error); if(err) printk(KERN_ERR "Failed to initialize ubd device %d :" "%s\n", i, error); } + mutex_unlock(&ubd_lock); return 0; } @@ -1129,7 +1124,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, sizeof(ubd_id))) return(-EFAULT); return(0); - + case CDROMVOLREAD: if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) return(-EFAULT); -- cgit v1.1 From de5fe76e436d9e98f8af8005ff23a2e6066aea10 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:25 -0800 Subject: [PATCH] uml: umid tidying Add an error message when two umids are put on the command line. umid.h is kind of pointless since it only declares one thing, and that is already declared in os.h. Commented the lack of locking of some data in os-Linux/umid.h. 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 | 1 - arch/um/drivers/mconsole_user.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index a5a683d..178b2ef 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -33,7 +33,6 @@ #include "irq_user.h" #include "init.h" #include "os.h" -#include "umid.h" #include "irq_kern.h" #include "choose-mode.h" diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 75aef6f..f02634f 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -16,7 +16,7 @@ #include "user.h" #include "sysdep/ptrace.h" #include "mconsole.h" -#include "umid.h" +#include "os.h" #include "user_util.h" static struct mconsole_command commands[] = { -- cgit v1.1 From b653d081c17e26101980c858a9808740533b78b4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 10 Feb 2007 01:45:54 -0800 Subject: [PATCH] proc: remove useless (and buggy) ->nlink settings Bug: pnx8550 code creates directory but resets ->nlink to 1. create_proc_entry() et al will correctly set ->nlink for you. Signed-off-by: Alexey Dobriyan Cc: Ralf Baechle Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jeff Dike Cc: Corey Minyard Cc: Alan Cox Cc: Kyle McMartin Cc: Martin Schwidefsky Cc: Greg KH Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index da0badc..f98d26e 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -235,7 +235,6 @@ static void make_ide_entries(char *dev_name) ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); if(!ent) return; - ent->nlink = 1; ent->data = NULL; ent->read_proc = proc_ide_read_media; ent->write_proc = NULL; -- cgit v1.1 From ab521dc0f8e117fd808d3e425216864d60390500 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 12 Feb 2007 00:53:00 -0800 Subject: [PATCH] tty: update the tty layer to work with struct pid Of kernel subsystems that work with pids the tty layer is probably the largest consumer. But it has the nice virtue that the assiation with a session only lasts until the session leader exits. Which means that no reference counting is required. So using struct pid winds up being a simple optimization to avoid hash table lookups. In the long term the use of pid_nr also ensures that when we have multiple pid spaces mixed everything will work correctly. Signed-off-by: Eric W. Biederman Cc: Alan Cox Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 0e1e9a2..01d4ab6 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -774,7 +774,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) line = tty->driver_data; chan_window_size(&line->chan_list, &tty->winsize.ws_row, &tty->winsize.ws_col); - kill_pg(tty->pgrp, SIGWINCH, 1); + kill_pgrp(tty->pgrp, SIGWINCH, 1); } out: if(winch->fd != -1) -- cgit v1.1 From 5dfe4c964a0dd7bb3a1d64a4166835a153146207 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 12 Feb 2007 00:55:31 -0800 Subject: [PATCH] mark struct file_operations const 2 Many struct file_operations in the kernel can be "const". Marking them const moves these to the .rodata section, which avoids false sharing with potential dirty data. In addition it'll catch accidental writes at compile time to these shared resources. [akpm@osdl.org: sparc64 fix] Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/harddog_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um/drivers') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 73c5caa..5560168 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -145,7 +145,7 @@ static int harddog_ioctl(struct inode *inode, struct file *file, } } -static struct file_operations harddog_fops = { +static const struct file_operations harddog_fops = { .owner = THIS_MODULE, .write = harddog_write, .ioctl = harddog_ioctl, -- cgit v1.1