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 +- arch/um/include/line.h | 14 +-- 3 files changed, 134 insertions(+), 72 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 83301e1ef67..799fca3644e 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 7a4897e27f4..9b2dd0b8a43 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) { diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 5f232ae89fb..b79643eeee0 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -11,6 +11,7 @@ #include "linux/tty.h" #include "linux/interrupt.h" #include "linux/spinlock.h" +#include "linux/mutex.h" #include "chan_user.h" #include "mconsole_kern.h" @@ -32,15 +33,17 @@ struct line_driver { struct line { struct tty_struct *tty; + spinlock_t count_lock; + int valid; + + struct mutex open_mutex; char *init_str; int init_pri; struct list_head chan_list; - int valid; - int count; - int throttled; + /*This lock is actually, mostly, local to*/ spinlock_t lock; - + int throttled; /* Yes, this is a real circular buffer. * XXX: And this should become a struct kfifo! * @@ -57,7 +60,8 @@ struct line { }; #define LINE_INIT(str, d) \ - { .init_str = str, \ + { .count_lock = SPIN_LOCK_UNLOCKED, \ + .init_str = str, \ .init_pri = INIT_STATIC, \ .valid = 1, \ .lock = SPIN_LOCK_UNLOCKED, \ -- cgit v1.2.3 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 ++++++++++++++++++++++------------------ arch/um/include/chan_kern.h | 2 +- arch/um/include/line.h | 8 ++- arch/um/include/mconsole_kern.h | 15 +---- arch/um/kernel/tt/gdb.c | 4 +- arch/um/kernel/tt/gdb_kern.c | 4 +- 12 files changed, 253 insertions(+), 238 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 7d4190e5565..4e7e3cfa21f 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 799fca3644e..e620ed46ed3 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 96f0189327a..832d5c766ca 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 afe3d427ddf..07e839e387d 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 ed9c59082d0..1e82430b844 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 9b2dd0b8a43..3cbfe3a8860 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 49c047b75cc..f4db97efc01 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; } diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 9003a343e14..2d9aa7ef4c2 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -30,7 +30,7 @@ struct chan { extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, struct tty_struct *tty, int irq); extern int parse_chan_pair(char *str, struct line *line, int device, - const struct chan_opts *opts); + const struct chan_opts *opts, char **error_out); extern int open_chan(struct list_head *chans); extern int write_chan(struct list_head *chans, const char *buf, int len, int write_irq); diff --git a/arch/um/include/line.h b/arch/um/include/line.h index b79643eeee0..a2486b4cc9f 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -76,7 +76,7 @@ struct lines { extern void line_close(struct tty_struct *tty, struct file * filp); extern int line_open(struct line *lines, struct tty_struct *tty); extern int line_setup(struct line *lines, unsigned int sizeof_lines, - char *init); + char *init, char **error_out); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); @@ -102,9 +102,11 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); extern void close_lines(struct line *lines, int nlines); extern int line_config(struct line *lines, unsigned int sizeof_lines, - char *str, const struct chan_opts *opts); + char *str, const struct chan_opts *opts, + char **error_out); extern int line_id(char **str, int *start_out, int *end_out); -extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); +extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n, + char **error_out); extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, int size, char **error_out); diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h index 1ea6d928e1c..73030e52b2c 100644 --- a/arch/um/include/mconsole_kern.h +++ b/arch/um/include/mconsole_kern.h @@ -18,10 +18,10 @@ struct mconsole_entry { struct mc_device { struct list_head list; char *name; - int (*config)(char *); + int (*config)(char *, char **); int (*get_config)(char *, char *, int, char **); int (*id)(char **, int *, int *); - int (*remove)(int); + int (*remove)(int, char **); }; #define CONFIG_CHUNK(str, size, current, chunk, end) \ @@ -50,14 +50,3 @@ static inline void mconsole_register_dev(struct mc_device *new) #endif #endif - -/* - * 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/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 786e4edd86c..8eba8f7dca6 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c @@ -139,7 +139,7 @@ static void config_gdb_cb(void *arg) init_proxy(debugger_pid, 0, 0); } -int gdb_config(char *str) +int gdb_config(char *str, char **error_out) { struct gdb_data data; @@ -154,7 +154,7 @@ void remove_gdb_cb(void *unused) exit_debugger_cb(NULL); } -int gdb_remove(int unused) +int gdb_remove(int unused, char **error_out) { initial_thread_cb(remove_gdb_cb, NULL); return 0; diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c index 68e1bf63cd0..a1af96ef9ee 100644 --- a/arch/um/kernel/tt/gdb_kern.c +++ b/arch/um/kernel/tt/gdb_kern.c @@ -8,8 +8,8 @@ #ifdef CONFIG_MCONSOLE -extern int gdb_config(char *str); -extern int gdb_remove(int n); +extern int gdb_config(char *str, char **error_out); +extern int gdb_remove(int n, char **error_out); static struct mc_device gdb_mc = { .name = "gdb", -- cgit v1.2.3 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 -- arch/um/include/mconsole_kern.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 3cbfe3a8860..0b1bca49804 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. */ diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h index 73030e52b2c..d2fe07e7895 100644 --- a/arch/um/include/mconsole_kern.h +++ b/arch/um/include/mconsole_kern.h @@ -20,7 +20,7 @@ struct mc_device { char *name; int (*config)(char *, char **); int (*get_config)(char *, char *, int, char **); - int (*id)(char **, int *, int *); + int (*id)(char **, int *, int *); int (*remove)(int, char **); }; -- cgit v1.2.3 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') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 4e7e3cfa21f..bce9b3427b0 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.2.3 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 +++++---- arch/um/include/net_kern.h | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 07e839e387d..b10154cc46b 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); diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 218f8b47fdc..92f76d82a6e 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h @@ -52,12 +52,12 @@ struct net_kern_info { struct transport { struct list_head list; - char *name; - int (*setup)(char *, char **, void *); + const char *name; + int (* const setup)(char *, char **, void *); const struct net_user_info *user; const struct net_kern_info *kern; - int private_size; - int setup_size; + const int private_size; + const int setup_size; }; extern struct net_device *ether_init(int); -- cgit v1.2.3 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 +++++++++++++++-------------- arch/um/include/net_kern.h | 6 +++--- 2 files changed, 18 insertions(+), 17 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index b10154cc46b..eede892a4f3 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) diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 92f76d82a6e..125ab42df18 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -36,7 +36,7 @@ struct uml_net_private { void (*remove)(void *); int (*read)(int, struct sk_buff **skb, struct uml_net_private *); int (*write)(int, struct sk_buff **skb, struct uml_net_private *); - + void (*add_address)(unsigned char *, unsigned char *, void *); void (*delete_address)(unsigned char *, unsigned char *, void *); int (*set_mtu)(int mtu, void *); @@ -63,7 +63,7 @@ struct transport { extern struct net_device *ether_init(int); extern unsigned short ether_protocol(struct sk_buff *); extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); -extern int tap_setup_common(char *str, char *type, char **dev_name, +extern int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, char **gate_addr); extern void register_transport(struct transport *new); extern unsigned short eth_protocol(struct sk_buff *skb); -- cgit v1.2.3 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') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 64ff22aa077..94bbcb5b922 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.2.3 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') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 94bbcb5b922..73c5caa7a15 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 def013b5a3c..c495ecf263b 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.2.3 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') diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index a0d148ea63d..f61fa056220 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.2.3 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') diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index f61fa056220..10e08a8c17c 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.2.3 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 + arch/um/kernel/tt/gdb_kern.c | 1 + 5 files changed, 19 insertions(+), 6 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 832d5c766ca..b4dbd102da0 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 eede892a4f3..c1838645ae2 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 1e82430b844..fe400acc975 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 f4db97efc01..c1d40fb738e 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, diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c index a1af96ef9ee..03b06bc0077 100644 --- a/arch/um/kernel/tt/gdb_kern.c +++ b/arch/um/kernel/tt/gdb_kern.c @@ -12,6 +12,7 @@ extern int gdb_config(char *str, char **error_out); extern int gdb_remove(int n, char **error_out); static struct mc_device gdb_mc = { + .list = INIT_LIST_HEAD(gdb_mc.list), .name = "gdb", .config = gdb_config, .remove = gdb_remove, -- cgit v1.2.3 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') diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 6dfe632f1c1..c688da72217 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.2.3 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') diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index c688da72217..4dd7d8a11db 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 bc6afaf74c1..80508023054 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.2.3 From f9795220521e0575dfd4ed0737d3a7848264662c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:03 -0800 Subject: [PATCH] uml: Kill a compilation warning Kill a compilation warning. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 8d56ec6cca7..121166400e2 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -39,9 +39,9 @@ static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { long error; +#ifdef CONFIG_TTY_LOG struct tty_struct *tty; -#ifdef CONFIG_TTY_LOG mutex_lock(&tty_mutex); tty = get_current_tty(); if (tty) -- cgit v1.2.3 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') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index c1838645ae2..04e31f86c10 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.2.3 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') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index b4dbd102da0..a5a683d6fc5 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 4dd7d8a11db..1c8efd95c42 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.2.3 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') diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 73b2bdd6d2d..e942e836f99 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.2.3 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 ++- arch/um/include/chan_kern.h | 3 +-- arch/um/include/chan_user.h | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index bce9b3427b0..7b8baf146ac 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 fe400acc975..475de52783e 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 0b1bca49804..a83c42c263b 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 = { diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 2d9aa7ef4c2..c4b41bb1035 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -36,8 +36,7 @@ extern int write_chan(struct list_head *chans, const char *buf, int len, int write_irq); extern int console_write_chan(struct list_head *chans, const char *buf, int len); -extern int console_open_chan(struct line *line, struct console *co, - const struct chan_opts *opts); +extern int console_open_chan(struct line *line, struct console *co); extern void deactivate_chan(struct list_head *chans, int irq); extern void reactivate_chan(struct list_head *chans, int irq); extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index a795547a1db..ad671eb9ede 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h @@ -9,11 +9,11 @@ #include "init.h" struct chan_opts { - void (*announce)(char *dev_name, int dev); + void (*const announce)(char *dev_name, int dev); char *xterm_title; - int raw; - unsigned long tramp_stack; - int in_kernel; + const int raw; + const unsigned long tramp_stack; + const int in_kernel; }; enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; -- cgit v1.2.3 From b4ac91a0eac36f347a509afda07e4305e931de61 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:07 -0800 Subject: [PATCH] uml: chan_user.h formatting fixes Whitespace fixes and emacs comment removal. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/chan_user.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index ad671eb9ede..38f16d812e7 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -54,14 +54,3 @@ __uml_help(fn, prefix "[0-9]*=\n" \ ); #endif - -/* - * 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.2.3 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 +++++++---------- arch/um/include/line.h | 36 ++++++++++++++---------------------- 4 files changed, 31 insertions(+), 45 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index e620ed46ed3..433e572fb19 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 475de52783e..fc22b9bd915 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 a83c42c263b..8dccdd193d9 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"); diff --git a/arch/um/include/line.h b/arch/um/include/line.h index a2486b4cc9f..3477a858eaa 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -15,19 +15,18 @@ #include "chan_user.h" #include "mconsole_kern.h" +/* There's only one modifiable field in this - .mc.list */ struct line_driver { - char *name; - char *device_name; - short major; - short minor_start; - short type; - short subtype; - int read_irq; - char *read_irq_name; - int write_irq; - char *write_irq_name; - char *symlink_from; - char *symlink_to; + const char *name; + const char *device_name; + const short major; + const short minor_start; + const short type; + const short subtype; + const int read_irq; + const char *read_irq_name; + const int write_irq; + const char *write_irq_name; struct mc_device mc; }; @@ -67,12 +66,6 @@ struct line { .lock = SPIN_LOCK_UNLOCKED, \ .driver = d } -struct lines { - int num; -}; - -#define LINES_INIT(n) { .num = n } - extern void line_close(struct tty_struct *tty, struct file * filp); extern int line_open(struct line *lines, struct tty_struct *tty); extern int line_setup(struct line *lines, unsigned int sizeof_lines, @@ -94,10 +87,9 @@ extern char *add_xterm_umid(char *base); extern int line_setup_irq(int fd, int input, int output, struct line *line, void *data); extern void line_close_chan(struct line *line); -extern struct tty_driver * line_register_devfs(struct lines *set, - struct line_driver *line_driver, - const struct tty_operations *driver, - struct line *lines, int nlines); +extern struct tty_driver *register_lines(struct line_driver *line_driver, + const struct tty_operations *driver, + struct line *lines, int nlines); extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); extern void close_lines(struct line *lines, int nlines); -- cgit v1.2.3 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 ++++++++---------------------------------------- arch/um/include/line.h | 1 - 2 files changed, 8 insertions(+), 41 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 433e572fb19..0e1e9a20a4d 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; diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 3477a858eaa..1223f2c844b 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -35,7 +35,6 @@ struct line { spinlock_t count_lock; int valid; - struct mutex open_mutex; char *init_str; int init_pri; struct list_head chan_list; -- cgit v1.2.3 From 94c282d79e17a83ccc876990e05378ed6dfbccae Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:09 -0800 Subject: [PATCH] uml: locking comments in iomem driver Comment some lack of locking in the iomem driver. Also, a couple of variables are in the wrong place, so they are moved. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/mem.c | 10 ---------- arch/um/kernel/physmem.c | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index c95855ba6ab..fb11992f0b8 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -367,16 +367,6 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) return pte; } -struct iomem_region *iomem_regions = NULL; -int iomem_size = 0; - -extern int parse_iomem(char *str, int *add) __init; - -__uml_setup("iomem=", parse_iomem, -"iomem=,\n" -" Configure as an IO memory region named .\n\n" -); - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index abafa64b872..22d3cf35966 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -398,6 +398,23 @@ __uml_setup("mem=", uml_mem_setup, " Example: mem=64M\n\n" ); +extern int __init parse_iomem(char *str, int *add); + +__uml_setup("iomem=", parse_iomem, +"iomem=,\n" +" Configure as an IO memory region named .\n\n" +); + +/* + * This list is constructed in parse_iomem and addresses filled in in + * setup_iomem, both of which run during early boot. Afterwards, it's + * unchanged. + */ +struct iomem_region *iomem_regions = NULL; + +/* Initialized in parse_iomem */ +int iomem_size = 0; + unsigned long find_iomem(char *driver, unsigned long *len_out) { struct iomem_region *region = iomem_regions; -- cgit v1.2.3 From 60678bbc76685bea47043e61981b8fc5cffc10da Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:10 -0800 Subject: [PATCH] uml: mem.c and physmem.c formatting fixes Fix a bunch of style violations in mem.c and physmem.c Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/mem.c | 77 +++++++++++++++++++++--------------------------- arch/um/kernel/physmem.c | 57 +++++++++++++++-------------------- 2 files changed, 57 insertions(+), 77 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index fb11992f0b8..d1480ff0f2a 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -65,8 +65,8 @@ void mem_init(void) { max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT; - /* clear the zero-page */ - memset((void *) empty_zero_page, 0, PAGE_SIZE); + /* clear the zero-page */ + memset((void *) empty_zero_page, 0, PAGE_SIZE); /* Map in the area just after the brk now that kmalloc is about * to be turned on. @@ -253,8 +253,10 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order) int i; again: - if(page == NULL) return(page); - if(PageHighMem(page)) return(page); + if(page == NULL) + return page; + if(PageHighMem(page)) + return page; addr = (unsigned long) page_address(page); for(i = 0; i < (1 << order); i++){ @@ -263,13 +265,15 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order) sizeof(zero), ¤t->thread.fault_addr, ¤t->thread.fault_catcher)){ - if(!(mask & __GFP_WAIT)) return(NULL); + if(!(mask & __GFP_WAIT)) + return NULL; else break; } addr += PAGE_SIZE; } - if(i == (1 << order)) return(page); + if(i == (1 << order)) + return page; page = alloc_pages(mask, order); goto again; } @@ -283,7 +287,6 @@ void free_initmem(void) } #ifdef CONFIG_BLK_DEV_INITRD - void free_initrd_mem(unsigned long start, unsigned long end) { if (start < end) @@ -296,37 +299,36 @@ void free_initrd_mem(unsigned long start, unsigned long end) totalram_pages++; } } - #endif void show_mem(void) { - int pfn, total = 0, reserved = 0; - int shared = 0, cached = 0; - int highmem = 0; + int pfn, total = 0, reserved = 0; + int shared = 0, cached = 0; + int highmem = 0; struct page *page; - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - pfn = max_mapnr; - while(pfn-- > 0) { + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); + pfn = max_mapnr; + while(pfn-- > 0) { page = pfn_to_page(pfn); - total++; - if(PageHighMem(page)) - highmem++; - if(PageReserved(page)) - reserved++; - else if(PageSwapCache(page)) - cached++; - else if(page_count(page)) - shared += page_count(page) - 1; - } - printk("%d pages of RAM\n", total); - printk("%d pages of HIGHMEM\n", highmem); - printk("%d reserved pages\n", reserved); - printk("%d pages shared\n", shared); - printk("%d pages swap cached\n", cached); + total++; + if(PageHighMem(page)) + highmem++; + if(PageReserved(page)) + reserved++; + else if(PageSwapCache(page)) + cached++; + else if(page_count(page)) + shared += page_count(page) - 1; + } + printk("%d pages of RAM\n", total); + printk("%d pages of HIGHMEM\n", highmem); + printk("%d reserved pages\n", reserved); + printk("%d pages shared\n", shared); + printk("%d pages swap cached\n", cached); } /* @@ -362,18 +364,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *pte; - + pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } - -/* - * 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/kernel/physmem.c b/arch/um/kernel/physmem.c index 22d3cf35966..638f3b5f609 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -40,7 +40,7 @@ static struct rb_node **find_rb(void *virt) while(*n != NULL){ d = rb_entry(*n, struct phys_desc, rb); if(d->virt == virt) - return(n); + return n; if(d->virt > virt) n = &(*n)->rb_left; @@ -48,7 +48,7 @@ static struct rb_node **find_rb(void *virt) n = &(*n)->rb_right; } - return(n); + return n; } static struct phys_desc *find_phys_mapping(void *virt) @@ -56,9 +56,9 @@ static struct phys_desc *find_phys_mapping(void *virt) struct rb_node **n = find_rb(virt); if(*n == NULL) - return(NULL); + return NULL; - return(rb_entry(*n, struct phys_desc, rb)); + return rb_entry(*n, struct phys_desc, rb); } static void insert_phys_mapping(struct phys_desc *desc) @@ -89,10 +89,10 @@ static struct desc_mapping *find_mapping(int fd) list_for_each(ele, &descriptor_mappings){ desc = list_entry(ele, struct desc_mapping, list); if(desc->fd == fd) - return(desc); + return desc; } - return(NULL); + return NULL; } static struct desc_mapping *descriptor_mapping(int fd) @@ -101,11 +101,11 @@ static struct desc_mapping *descriptor_mapping(int fd) desc = find_mapping(fd); if(desc != NULL) - return(desc); + return desc; desc = kmalloc(sizeof(*desc), GFP_ATOMIC); if(desc == NULL) - return(NULL); + return NULL; *desc = ((struct desc_mapping) { .fd = fd, @@ -113,7 +113,7 @@ static struct desc_mapping *descriptor_mapping(int fd) .pages = LIST_HEAD_INIT(desc->pages) }); list_add(&desc->list, &descriptor_mappings); - return(desc); + return desc; } int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) @@ -125,11 +125,11 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) fd_maps = descriptor_mapping(fd); if(fd_maps == NULL) - return(-ENOMEM); + return -ENOMEM; phys = __pa(virt); desc = find_phys_mapping(virt); - if(desc != NULL) + if(desc != NULL) panic("Address 0x%p is already substituted\n", virt); err = -ENOMEM; @@ -155,7 +155,7 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) rb_erase(&desc->rb, &phys_mappings); kfree(desc); out: - return(err); + return err; } static int physmem_fd = -1; @@ -182,10 +182,10 @@ int physmem_remove_mapping(void *virt) virt = (void *) ((unsigned long) virt & PAGE_MASK); desc = find_phys_mapping(virt); if(desc == NULL) - return(0); + return 0; remove_mapping(desc); - return(1); + return 1; } void physmem_forget_descriptor(int fd) @@ -239,9 +239,9 @@ void arch_free_page(struct page *page, int order) int is_remapped(void *virt) { - struct phys_desc *desc = find_phys_mapping(virt); + struct phys_desc *desc = find_phys_mapping(virt); - return(desc != NULL); + return desc != NULL; } /* Changed during early boot */ @@ -276,7 +276,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) else map = alloc_bootmem_low_pages(total_len); if(map == NULL) - return(-ENOMEM); + return -ENOMEM; for(i = 0; i < total_pages; i++){ p = &map[i]; @@ -286,7 +286,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) } max_mapnr = total_pages; - return(0); + return 0; } /* Changed during early boot */ @@ -296,7 +296,7 @@ unsigned long get_kmem_end(void) { if(kmem_top == 0) kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); - return(kmem_top); + return kmem_top; } void map_memory(unsigned long virt, unsigned long phys, unsigned long len, @@ -379,7 +379,7 @@ int phys_mapping(unsigned long phys, __u64 *offset_out) *offset_out = phys - iomem_size; } - return(fd); + return fd; } static int __init uml_mem_setup(char *line, int *add) @@ -422,13 +422,13 @@ unsigned long find_iomem(char *driver, unsigned long *len_out) while(region != NULL){ if(!strcmp(region->driver, driver)){ *len_out = region->size; - return(region->virt); + return region->virt; } region = region->next; } - return(0); + return 0; } int setup_iomem(void) @@ -452,18 +452,7 @@ int setup_iomem(void) region = region->next; } - return(0); + return 0; } __initcall(setup_iomem); - -/* - * 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.2.3 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') diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 8dccdd193d9..7ff0b0fc37e 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -69,6 +69,7 @@ static struct line_driver driver = { .write_irq = CONSOLE_WRITE_IRQ, .write_irq_name = "console-write", .mc = { + .list = LIST_HEAD_INIT(driver.mc.list), .name = "con", .config = con_config, .get_config = con_get_config, -- cgit v1.2.3 From 490ba1714b31a131cdc6318231aa227d19bf0761 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:12 -0800 Subject: [PATCH] uml: make time data per-cpu prev_nsecs and delta need to be arrays, and indexed by CPU number. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/time.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 2e354b3ca06..b1f8b075241 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -35,31 +35,31 @@ unsigned long long sched_clock(void) return (unsigned long long)jiffies_64 * (1000000000 / HZ); } -static unsigned long long prev_nsecs; +static unsigned long long prev_nsecs[NR_CPUS]; #ifdef CONFIG_UML_REAL_TIME_CLOCK -static long long delta; /* Deviation per interval */ +static long long delta[NR_CPUS]; /* Deviation per interval */ #endif void timer_irq(union uml_pt_regs *regs) { unsigned long long ticks = 0; - #ifdef CONFIG_UML_REAL_TIME_CLOCK - if(prev_nsecs){ + int c = cpu(); + if(prev_nsecs[c]){ /* We've had 1 tick */ unsigned long long nsecs = os_nsecs(); - delta += nsecs - prev_nsecs; - prev_nsecs = nsecs; + delta[c] += nsecs - prev_nsecs[c]; + prev_nsecs[c] = nsecs; /* Protect against the host clock being set backwards */ - if(delta < 0) - delta = 0; + if(delta[c] < 0) + delta[c] = 0; - ticks += (delta * HZ) / BILLION; - delta -= (ticks * BILLION) / HZ; + ticks += (delta[c] * HZ) / BILLION; + delta[c] -= (ticks * BILLION) / HZ; } - else prev_nsecs = os_nsecs(); + else prev_nsecs[c] = os_nsecs(); #else ticks = 1; #endif @@ -69,8 +69,8 @@ void timer_irq(union uml_pt_regs *regs) } } +/* Protects local_offset */ static DEFINE_SPINLOCK(timer_spinlock); - static unsigned long long local_offset = 0; static inline unsigned long long get_time(void) -- cgit v1.2.3 From b42e1eacc1f245581a2f7580ec1082ff4d6c65cd Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:12 -0800 Subject: [PATCH] uml: delete unused file It turns out that resource.c isn't needed. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/Makefile | 2 +- arch/um/kernel/resource.c | 23 ----------------------- 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 arch/um/kernel/resource.c (limited to 'arch/um') diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 6fa63a2a89e..c5cf4a0827b 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ - physmem.o process.o ptrace.o reboot.o resource.o sigio.o \ + physmem.o process.o ptrace.o reboot.o sigio.o \ signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ um_arch.o umid.o diff --git a/arch/um/kernel/resource.c b/arch/um/kernel/resource.c deleted file mode 100644 index 32188e12e8a..00000000000 --- a/arch/um/kernel/resource.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/pci.h" - -unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, - unsigned long start, unsigned long size) -{ - return start; -} - -/* - * 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.2.3 From 6d1b18b16fc917e5c9af568a53c7e37923821d70 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:13 -0800 Subject: [PATCH] uml: remove unused variable and function syscall_index and next_syscall_index turn out not to be used. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/kern_util.h | 1 - arch/um/kernel/syscall.c | 16 ---------------- 2 files changed, 17 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index cec9fcc57bf..3368ef97437 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -61,7 +61,6 @@ extern int set_signals(int enable); extern void force_sigbus(void); extern int pid_to_processor_id(int pid); extern void deliver_signals(void *t); -extern int next_syscall_index(int max); extern int next_trap_index(int max); extern void default_idle(void); extern void finish_fork(void); diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index f5ed8624648..2828c528322 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -149,22 +149,6 @@ long sys_olduname(struct oldold_utsname __user * name) return error; } -DEFINE_SPINLOCK(syscall_lock); - -static int syscall_index = 0; - -int next_syscall_index(int limit) -{ - int ret; - - spin_lock(&syscall_lock); - ret = syscall_index; - if(++syscall_index == limit) - syscall_index = 0; - spin_unlock(&syscall_lock); - return(ret); -} - int kernel_execve(const char *filename, char *const argv[], char *const envp[]) { mm_segment_t fs; -- cgit v1.2.3 From 27aa6ef3c0e8220b27b0a8d2d0bae7cd0a6d2f78 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:14 -0800 Subject: [PATCH] uml: make signal handlers static A bunch of the signal handlers can be made static. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/kern_util.h | 4 ---- arch/um/kernel/trap.c | 28 ++++++++++++++-------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 3368ef97437..173af029d12 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -87,7 +87,6 @@ extern void timer_irq(union uml_pt_regs *regs); extern void unprotect_stack(unsigned long stack); extern void do_uml_exitcalls(void); extern int attach_debugger(int idle_pid, int pid, int stop); -extern void bad_segv(struct faultinfo fi, unsigned long ip); extern int config_gdb(char *str); extern int remove_gdb(void); extern char *uml_strdup(char *string); @@ -103,8 +102,6 @@ extern int clear_user_proc(void *buf, int size); extern int copy_to_user_proc(void *to, void *from, int size); extern int copy_from_user_proc(void *to, void *from, int size); extern int strlen_user_proc(char *str); -extern void bus_handler(int sig, union uml_pt_regs *regs); -extern void winch(int sig, union uml_pt_regs *regs); extern long execute_syscall(void *r); extern int smp_sigio_handler(void); extern void *get_current(void); @@ -119,7 +116,6 @@ extern void time_init_kern(void); /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ extern int __cant_sleep(void); -extern void segv_handler(int sig, union uml_pt_regs *regs); extern void sigio_handler(int sig, union uml_pt_regs *regs); #endif diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index b5f124a2f6a..26f15c45857 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -128,7 +128,18 @@ out_of_memory: goto out; } -void segv_handler(int sig, union uml_pt_regs *regs) +static void bad_segv(struct faultinfo fi, unsigned long ip) +{ + struct siginfo si; + + si.si_signo = SIGSEGV; + si.si_code = SEGV_ACCERR; + si.si_addr = (void __user *) FAULT_ADDRESS(fi); + current->thread.arch.faultinfo = fi; + force_sig_info(SIGSEGV, &si, current); +} + +static void segv_handler(int sig, union uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); @@ -205,17 +216,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) return(0); } -void bad_segv(struct faultinfo fi, unsigned long ip) -{ - struct siginfo si; - - si.si_signo = SIGSEGV; - si.si_code = SEGV_ACCERR; - si.si_addr = (void __user *) FAULT_ADDRESS(fi); - current->thread.arch.faultinfo = fi; - force_sig_info(SIGSEGV, &si, current); -} - void relay_signal(int sig, union uml_pt_regs *regs) { if(arch_handle_signal(sig, regs)) @@ -232,14 +232,14 @@ void relay_signal(int sig, union uml_pt_regs *regs) force_sig(sig, current); } -void bus_handler(int sig, union uml_pt_regs *regs) +static void bus_handler(int sig, union uml_pt_regs *regs) { if(current->thread.fault_catcher != NULL) do_longjmp(current->thread.fault_catcher, 1); else relay_signal(sig, regs); } -void winch(int sig, union uml_pt_regs *regs) +static void winch(int sig, union uml_pt_regs *regs) { do_IRQ(WINCH_IRQ, regs); } -- cgit v1.2.3 From 0d0d0ed426f8f5ba6b74ba30fcdcd27c54ce4724 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:15 -0800 Subject: [PATCH] uml: const a variable kstack_depth_to_print can be made const. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/sysrq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 239c98054de..f9e02b31a97 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -50,7 +50,7 @@ void dump_stack(void) EXPORT_SYMBOL(dump_stack); /*Stolen from arch/i386/kernel/traps.c */ -static int kstack_depth_to_print = 24; +static const int kstack_depth_to_print = 24; /* This recently started being used in arch-independent code too, as in * kernel/sched.c.*/ -- cgit v1.2.3 From 92b4202f38cf630350a9e1eb0ab23ca4fc5b687b Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:15 -0800 Subject: [PATCH] uml: remove code controlled by non-existent config option CONFIG_HOST_TASK_SIZE doesn't exist any more. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/mem.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 0d2cce62113..7c18dfcd7d8 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -14,13 +14,9 @@ unsigned long set_task_sizes_skas(unsigned long *task_size_out) unsigned long host_task_size = ROUND_4M((unsigned long) &host_task_size); -#ifdef CONFIG_HOST_TASK_SIZE - *host_size_out = ROUND_4M(CONFIG_HOST_TASK_SIZE); - *task_size_out = CONFIG_HOST_TASK_SIZE; -#else if (!skas_needs_stub) *task_size_out = host_task_size; else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; -#endif + return host_task_size; } -- cgit v1.2.3 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') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index c1d40fb738e..d863482cdd2 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.2.3 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') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index d863482cdd2..da0badcd755 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.2.3 From 6bf79482f3288e19697d08c456b0bd6b1755d467 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:18 -0800 Subject: [PATCH] uml: locking comments in memory and tempfile code Locking comments and emacs comment removal in the low-level memory and temp file code. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/tempfile.h | 10 ---------- arch/um/kernel/mem.c | 3 ++- arch/um/os-Linux/mem.c | 7 +++++++ 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/tempfile.h b/arch/um/include/tempfile.h index e36d9e0f510..d441eac936b 100644 --- a/arch/um/include/tempfile.h +++ b/arch/um/include/tempfile.h @@ -9,13 +9,3 @@ extern int make_tempfile(const char *template, char **tempname, int do_unlink); #endif -/* - * 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/kernel/mem.c b/arch/um/kernel/mem.c index d1480ff0f2a..e85d65deea0 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -24,8 +24,9 @@ #include "init.h" #include "kern_constants.h" -/* Changed during early boot */ +/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ unsigned long *empty_zero_page = NULL; +/* allocated in paging_init and unchanged thereafter */ unsigned long *empty_bad_page = NULL; pgd_t swapper_pg_dir[PTRS_PER_PGD]; unsigned long long highmem; diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 4203681e508..82b874580f6 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -20,7 +20,13 @@ #include +/* Modified by which_tmpdir, which is called during early boot */ static char *default_tmpdir = "/tmp"; + +/* + * Modified when creating the physical memory file and when checking + * the tmp filesystem for usability, both happening during early boot. + */ static char *tempdir = NULL; static void __init find_tempdir(void) @@ -83,6 +89,7 @@ static int next(int fd, char *buf, int size, char c) return 1; } +/* which_tmpdir is called only during early boot */ static int checked_tmpdir = 0; /* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner -- cgit v1.2.3 From 7242a4005d1c496bc1140d56a0d898cde1b3e3f6 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:19 -0800 Subject: [PATCH] uml: locking comments in startup code Add a couple of comments about some non-locked data. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/um') diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 7fe92680c7d..5d3bff430d9 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -133,6 +133,7 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, return ret; } +/* Changed only during early boot */ int ptrace_faultinfo = 1; int ptrace_ldt = 1; int proc_mm = 1; @@ -160,6 +161,7 @@ __uml_setup("mode=skas0", mode_skas0_cmd_param, " specify mode=tt. Note that this was recently added - on \n" " older kernels you must use simply \"skas0\".\n\n"); +/* Changed only during early boot */ static int force_sysemu_disabled = 0; static int __init nosysemu_cmd_param(char *str, int* add) -- cgit v1.2.3 From 9eae9b132cd2cebf98cc45550049d421302b9aba Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:20 -0800 Subject: [PATCH] uml: style fixes in startup code Some style fixes in startup.c. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 5d3bff430d9..537084fd834 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -95,7 +95,7 @@ static int start_ptraced_child(void **stack_out) status); *stack_out = stack; - return(pid); + return pid; } /* When testing for SYSEMU support, if it is one of the broken versions, we @@ -182,7 +182,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param, static void __init check_sysemu(void) { void *stack; - int pid, n, status, count=0; + int pid, n, status, count=0; printf("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; @@ -418,7 +418,7 @@ static inline void check_skas3_proc_mm(void) { printf(" - /proc/mm..."); if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { - proc_mm = 0; + proc_mm = 0; printf("not found\n"); } else { @@ -445,7 +445,7 @@ int can_do_skas(void) #else int can_do_skas(void) { - return(0); + return 0; } #endif @@ -493,11 +493,11 @@ int __init parse_iomem(char *str, int *add) iomem_regions = new; iomem_size += new->size + UM_KERN_PAGE_SIZE; - return(0); + return 0; out_close: os_close_file(fd); out: - return(1); + return 1; } -- cgit v1.2.3 From 73c8f4441f07dd3b9d198ec0e97ce83138a6224c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:20 -0800 Subject: [PATCH] uml: libc-dependent code should call libc directly We shouldn't be using the os wrappers from os code - we can use libc directly. This patch replaces wrapper calls with libc calls. It turns out that os_sigio_async had only one caller, which was in startup.c, so that function is moved there and its name changed. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/os.h | 1 - arch/um/os-Linux/file.c | 19 ------------------- arch/um/os-Linux/start_up.c | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 31 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 13a86bd383d..8f602667296 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -137,7 +137,6 @@ extern int os_new_tty_pgrp(int fd, int pid); extern int os_get_ifname(int fd, char *namebuf); extern int os_set_slip(int fd); extern int os_set_owner(int fd, int pid); -extern int os_sigio_async(int master, int slave); extern int os_mode_fd(int fd, int mode); extern int os_seek_file(int fd, __u64 offset); diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index 189fa677085..371b4335f46 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -162,25 +162,6 @@ int os_set_owner(int fd, int pid) return 0; } -/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ -int os_sigio_async(int master, int slave) -{ - int flags; - - flags = fcntl(master, F_GETFL); - if(flags < 0) - return -errno; - - if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)) - return -errno; - - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) - return -errno; - - return(0); -} - int os_mode_fd(int fd, int mode) { int err; diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 537084fd834..735d035a7f3 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -54,7 +54,7 @@ static int ptrace_child(void *arg) perror("ptrace"); os_kill_process(pid, 0); } - os_stop_process(pid); + kill(pid, SIGSTOP); /*This syscall will be intercepted by the parent. Don't call more than * once, please.*/ @@ -417,7 +417,7 @@ static inline void check_skas3_ptrace_ldt(void) static inline void check_skas3_proc_mm(void) { printf(" - /proc/mm..."); - if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { + if (access("/proc/mm", W_OK) < 0) { proc_mm = 0; printf("not found\n"); } @@ -452,9 +452,9 @@ int can_do_skas(void) int __init parse_iomem(char *str, int *add) { struct iomem_region *new; - struct uml_stat buf; + struct stat64 buf; char *file, *driver; - int fd, err, size; + int fd, size; driver = str; file = strchr(str,','); @@ -464,15 +464,14 @@ int __init parse_iomem(char *str, int *add) } *file = '\0'; file++; - fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); + fd = open(file, O_RDWR, 0); if(fd < 0){ os_print_error(fd, "parse_iomem - Couldn't open io file"); goto out; } - err = os_stat_fd(fd, &buf); - if(err < 0){ - os_print_error(err, "parse_iomem - cannot stat_fd file"); + if(fstat64(fd, &buf) < 0){ + perror("parse_iomem - cannot stat_fd file"); goto out_close; } @@ -482,7 +481,7 @@ int __init parse_iomem(char *str, int *add) goto out_close; } - size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); + size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); *new = ((struct iomem_region) { .next = iomem_regions, .driver = driver, @@ -495,7 +494,7 @@ int __init parse_iomem(char *str, int *add) return 0; out_close: - os_close_file(fd); + close(fd); out: return 1; } @@ -528,6 +527,24 @@ static void openpty_cb(void *arg) info->err = -errno; } +static int async_pty(int master, int slave) +{ + int flags; + + flags = fcntl(master, F_GETFL); + if(flags < 0) + return -errno; + + if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || + (fcntl(master, F_SETOWN, os_getpid()) < 0)) + return -errno; + + if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) + return -errno; + + return(0); +} + static void __init check_one_sigio(void (*proc)(int, int)) { struct sigaction old, new; @@ -553,7 +570,7 @@ static void __init check_one_sigio(void (*proc)(int, int)) if (err < 0) panic("check_sigio : __raw failed, errno = %d\n", -err); - err = os_sigio_async(master, slave); + err = async_pty(master, slave); if(err < 0) panic("tty_fds : sigio_async failed, err = %d\n", -err); -- cgit v1.2.3 From 81999a01c786e26c2058968d76b595df60d2f8da Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:21 -0800 Subject: [PATCH] uml: fix style violations Fix a bunch of style violations in mem.c. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/mem.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 82b874580f6..f1ea169db85 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -35,7 +35,8 @@ static void __init find_tempdir(void) int i; char *dir = NULL; - if(tempdir != NULL) return; /* We've already been called */ + if(tempdir != NULL) /* We've already been called */ + return; for(i = 0; dirs[i]; i++){ dir = getenv(dirs[i]); if((dir != NULL) && (*dir != '\0')) @@ -193,7 +194,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink) } else { free(tempname); } - return(fd); + return fd; out: free(tempname); return -1; @@ -238,7 +239,7 @@ int create_tmp_file(unsigned long long len) exit(1); } - return(fd); + return fd; } int create_mem_file(unsigned long long len) @@ -252,7 +253,7 @@ int create_mem_file(unsigned long long len) errno = -err; perror("exec_close"); } - return(fd); + return fd; } -- cgit v1.2.3 From f2e62992a232544d612b7b95e932fbf3592944e1 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:23 -0800 Subject: [PATCH] uml: IRQ handler tidying Tidying the irq code - make a variable static activate_fd can call kmalloc directly since it's now kernel code added a no-locking comment fixed a style violation Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/irq.c | 7 +++---- arch/um/os-Linux/irq.c | 6 +++++- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 5c1e611f628..50a288bb875 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -79,7 +79,7 @@ skip: return 0; } -struct irq_fd *active_fds = NULL; +static struct irq_fd *active_fds = NULL; static struct irq_fd **last_irq_ptr = &active_fds; extern void free_irqs(void); @@ -124,8 +124,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) if (err < 0) goto out; - new_fd = um_kmalloc(sizeof(*new_fd)); err = -ENOMEM; + new_fd = kmalloc(sizeof(struct irq_fd), GFP_KERNEL); if (new_fd == NULL) goto out; @@ -176,9 +176,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) */ spin_unlock_irqrestore(&irq_lock, flags); kfree(tmp_pfd); - tmp_pfd = NULL; - tmp_pfd = um_kmalloc(n); + tmp_pfd = kmalloc(n, GFP_KERNEL); if (tmp_pfd == NULL) goto out_kfree; diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index d46b818c131..d1b61d474e0 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -20,6 +20,10 @@ #include "os.h" #include "um_malloc.h" +/* + * Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd + * and os_free_irq_by_cb, which are called under irq_lock. + */ static struct pollfd *pollfds = NULL; static int pollfds_num = 0; static int pollfds_size = 0; @@ -58,7 +62,7 @@ int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds) if (pollfds_num == pollfds_size) { if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) { /* return min size needed for new pollfds area */ - return((pollfds_size + 1) * sizeof(pollfds[0])); + return (pollfds_size + 1) * sizeof(pollfds[0]); } if (pollfds != NULL) { -- cgit v1.2.3 From d9f9d31983aac7764d178583d0777199d081cb1a Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:23 -0800 Subject: [PATCH] uml: SIGIO locking comment Comment the use of a mysterious-looking lock. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/sigio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um') diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c index 2b0ab438301..1c831f9ee09 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c @@ -42,6 +42,7 @@ int write_sigio_irq(int fd) return(0); } +/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */ static DEFINE_SPINLOCK(sigio_spinlock); void sigio_lock(void) -- cgit v1.2.3 From 4cffb7fa69349d48d900d98766dc9ad52d9c851e Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:24 -0800 Subject: [PATCH] uml: SIGIO formatting fixes Fix formatting in the sigio code. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sigio.h | 11 ----------- arch/um/kernel/sigio.c | 6 +++--- 2 files changed, 3 insertions(+), 14 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h index fe99ea163c2..434f1a9ae4b 100644 --- a/arch/um/include/sigio.h +++ b/arch/um/include/sigio.h @@ -12,14 +12,3 @@ extern void sigio_lock(void); extern void sigio_unlock(void); #endif - -/* - * 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/kernel/sigio.c b/arch/um/kernel/sigio.c index 1c831f9ee09..89f9866a135 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c @@ -23,7 +23,7 @@ static irqreturn_t sigio_interrupt(int irq, void *data) os_read_file(sigio_irq_fd, &c, sizeof(c)); reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); - return(IRQ_HANDLED); + return IRQ_HANDLED; } int write_sigio_irq(int fd) @@ -36,10 +36,10 @@ int write_sigio_irq(int fd) if(err){ printk("write_sigio_irq : um_request_irq failed, err = %d\n", err); - return(-1); + return -1; } sigio_irq_fd = fd; - return(0); + return 0; } /* These are called from os-Linux/sigio.c to protect its pollfds arrays. */ -- cgit v1.2.3 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 +- arch/um/include/umid.h | 22 ---------------------- arch/um/kernel/um_arch.c | 1 - arch/um/kernel/umid.c | 4 +++- arch/um/os-Linux/umid.c | 3 ++- 6 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 arch/um/include/umid.h (limited to 'arch/um') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index a5a683d6fc5..178b2eff4a8 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 75aef6f7ef6..f02634fbf32 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[] = { diff --git a/arch/um/include/umid.h b/arch/um/include/umid.h deleted file mode 100644 index 11373c851f1..00000000000 --- a/arch/um/include/umid.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __UMID_H__ -#define __UMID_H__ - -extern int umid_file_name(char *name, char *buf, int len); - -#endif - -/* - * 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/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 66f43c90682..84e57f6da1d 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -30,7 +30,6 @@ #include "kern.h" #include "mem_user.h" #include "mem.h" -#include "umid.h" #include "initrd.h" #include "init.h" #include "os.h" diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 4eaee823bfd..039e16efcd5 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -16,8 +16,10 @@ static int __init set_umid_arg(char *name, int *add) { int err; - if(umid_inited) + if(umid_inited){ + printf("umid already set\n"); return 0; + } *add = 0; err = set_umid(name); diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index 48092b95c8a..b462863f717 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -18,7 +18,7 @@ #define UMID_LEN 64 /* Changed by set_umid, which is run early in boot */ -char umid[UMID_LEN] = { 0 }; +static char umid[UMID_LEN] = { 0 }; /* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ static char *uml_dir = UML_DIR; @@ -235,6 +235,7 @@ int __init set_umid(char *name) return 0; } +/* Changed in make_umid, which is called during early boot */ static int umid_setup = 0; int __init make_umid(void) -- cgit v1.2.3 From c538b391a7e8f3cb5d7756ec68d1864429d26a0c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:26 -0800 Subject: [PATCH] uml: ELF locking commentary Comment the lack of locking of the elf data extracted from the ELF headers passed to UML. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/elf_aux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 5a99dd3fbed..3a8d7e3aae0 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -21,12 +21,11 @@ typedef Elf32_auxv_t elf_auxv_t; typedef Elf64_auxv_t elf_auxv_t; #endif +/* These are initialized very early in boot and never changed */ char * elf_aux_platform; long elf_aux_hwcap; - unsigned long vsyscall_ehdr; unsigned long vsyscall_end; - unsigned long __kernel_vsyscall; __init void scan_elf_aux( char **envp) -- cgit v1.2.3 From 6c59e2f593d0c00c78ec48146de6eaf52a342dd5 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:26 -0800 Subject: [PATCH] uml: register handling formatting fixes Formatting fixes in the register handling code. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/sys-i386/registers.c | 14 +++++++------- arch/um/os-Linux/sys-x86_64/registers.c | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 7cd0369e02b..79cd93c8c5e 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -34,27 +34,27 @@ void init_thread_registers(union uml_pt_regs *to) int save_fp_registers(int pid, unsigned long *fp_regs) { if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) - return(-errno); - return(0); + return -errno; + return 0; } int restore_fp_registers(int pid, unsigned long *fp_regs) { if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) - return(-errno); - return(0); + return -errno; + return 0; } static int move_registers(int pid, int int_op, union uml_pt_regs *regs, int fp_op, unsigned long *fp_regs) { if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return(-errno); + return -errno; if(ptrace(fp_op, pid, 0, fp_regs) < 0) - return(-errno); + return -errno; - return(0); + return 0; } void save_registers(int pid, union uml_pt_regs *regs) diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index cb8e8a26328..a2d7e0c603f 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -27,12 +27,12 @@ static int move_registers(int pid, int int_op, int fp_op, union uml_pt_regs *regs) { if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return(-errno); + return -errno; if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) - return(-errno); + return -errno; - return(0); + return 0; } void save_registers(int pid, union uml_pt_regs *regs) -- cgit v1.2.3 From 9683da91e2db323ee728041576e29ad7fa9547b9 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:27 -0800 Subject: [PATCH] uml: AIO locking and tidying Comment the lack of locking of data that's set up once at boot time. Also fixed a couple of bogus printks. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/aio.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index f897140cc4a..6ff12743a0b 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -24,9 +24,6 @@ struct aio_thread_req { struct aio_context *aio; }; -static int aio_req_fd_r = -1; -static int aio_req_fd_w = -1; - #if defined(HAVE_AIO_ABI) #include @@ -111,6 +108,7 @@ static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, return err; } +/* Initialized in an initcall and unchanged thereafter */ static aio_context_t ctx = 0; static int aio_thread(void *arg) @@ -137,7 +135,7 @@ static int aio_thread(void *arg) err = os_write_file(reply_fd, &reply, sizeof(reply)); if(err != sizeof(reply)) printk("aio_thread - write failed, fd = %d, " - "err = %d\n", aio_req_fd_r, -err); + "err = %d\n", reply_fd, -err); } } return 0; @@ -182,6 +180,11 @@ out: return err; } +/* These are initialized in initcalls and not changed */ +static int aio_req_fd_r = -1; +static int aio_req_fd_w = -1; +static int aio_pid = -1; + static int not_aio_thread(void *arg) { struct aio_thread_req req; @@ -208,14 +211,12 @@ static int not_aio_thread(void *arg) err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); if(err != sizeof(reply)) printk("not_aio_thread - write failed, fd = %d, " - "err = %d\n", aio_req_fd_r, -err); + "err = %d\n", req.aio->reply_fd, -err); } return 0; } -static int aio_pid = -1; - static int init_aio_24(void) { unsigned long stack; @@ -308,6 +309,7 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, } #endif +/* Initialized in an initcall and unchanged thereafter */ static int aio_24 = DEFAULT_24_AIO; static int __init set_aio_24(char *name, int *add) -- cgit v1.2.3 From 3a150e1da8bc4e840d5a09fc089052011b5b6503 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:28 -0800 Subject: [PATCH] uml: fix error output during early boot The startup code panics a lot if anything goes wrong early on. This is wrong for several reasons, like the kernel isn't running, so you can't really be calling into it yet, but the harm comes from useful error messages being trapped in the printk ring where no one will ever see them. This patch changes these panics to perror and printf in wrappers which also exit. Normal, informational, prints are also wrapped so that fflush(stdout) is called after each one. This is so the output appears in the correct sequence in the event of an error. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 154 ++++++++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 62 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 735d035a7f3..5178eba9afa 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -73,6 +73,34 @@ static int ptrace_child(void *arg) _exit(ret); } +static void fatal_perror(char *str) +{ + perror(str); + exit(1); +} + +static void fatal(char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + vprintf(fmt, list); + va_end(list); + fflush(stdout); + + exit(1); +} + +static void non_fatal(char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + vprintf(fmt, list); + va_end(list); + fflush(stdout); +} + static int start_ptraced_child(void **stack_out) { void *stack; @@ -82,16 +110,16 @@ static int start_ptraced_child(void **stack_out) stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(stack == MAP_FAILED) - panic("check_ptrace : mmap failed, errno = %d", errno); + fatal_perror("check_ptrace : mmap failed"); sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); if(pid < 0) - panic("start_ptraced_child : clone failed, errno = %d", errno); + fatal_perror("start_ptraced_child : clone failed"); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) - panic("check_ptrace : clone failed, errno = %d", errno); + fatal_perror("check_ptrace : clone failed"); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) - panic("check_ptrace : expected SIGSTOP, got status = %d", + fatal("check_ptrace : expected SIGSTOP, got status = %d", status); *stack_out = stack; @@ -105,31 +133,30 @@ static int start_ptraced_child(void **stack_out) * must work anyway! */ static int stop_ptraced_child(int pid, void *stack, int exitcode, - int mustpanic) + int mustexit) { int status, n, ret = 0; if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) - panic("check_ptrace : ptrace failed, errno = %d", errno); + fatal_perror("stop_ptraced_child : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, 0)); if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); if (exit_with == 2) - printf("check_ptrace : child exited with status 2. " - "Serious trouble happening! Try updating your " - "host skas patch!\nDisabling SYSEMU support."); - printf("check_ptrace : child exited with exitcode %d, while " - "expecting %d; status 0x%x", exit_with, - exitcode, status); - if (mustpanic) - panic("\n"); - else - printf("\n"); + non_fatal("check_ptrace : child exited with status 2. " + "Serious trouble happening! Try updating " + "your host skas patch!\nDisabling SYSEMU " + "support."); + non_fatal("check_ptrace : child exited with exitcode %d, while " + "expecting %d; status 0x%x\n", exit_with, + exitcode, status); + if (mustexit) + exit(1); ret = -1; } if(munmap(stack, PAGE_SIZE) < 0) - panic("check_ptrace : munmap failed, errno = %d", errno); + fatal_perror("check_ptrace : munmap failed"); return ret; } @@ -184,7 +211,7 @@ static void __init check_sysemu(void) void *stack; int pid, n, status, count=0; - printf("Checking syscall emulation patch for ptrace..."); + non_fatal("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; pid = start_ptraced_child(&stack); @@ -193,31 +220,30 @@ static void __init check_sysemu(void) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if (n < 0) - panic("check_sysemu : wait failed, errno = %d", errno); + fatal_perror("check_sysemu : wait failed"); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) - panic("check_sysemu : expected SIGTRAP, " - "got status = %d", status); + fatal("check_sysemu : expected SIGTRAP, got status = %d", + status); n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if(n < 0) - panic("check_sysemu : failed to modify system " - "call return, errno = %d", errno); + fatal_perror("check_sysemu : failed to modify system call " + "return"); if (stop_ptraced_child(pid, stack, 0, 0) < 0) goto fail_stopped; sysemu_supported = 1; - printf("OK\n"); + non_fatal("OK\n"); set_using_sysemu(!force_sysemu_disabled); - printf("Checking advanced syscall emulation patch for ptrace..."); + non_fatal("Checking advanced syscall emulation patch for ptrace..."); pid = start_ptraced_child(&stack); - if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, - (void *) PTRACE_O_TRACESYSGOOD) < 0) - panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", - errno); + if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + (void *) PTRACE_O_TRACESYSGOOD) < 0)) + fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); while(1){ count++; @@ -225,29 +251,30 @@ static void __init check_sysemu(void) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) - panic("check_ptrace : wait failed, errno = %d", errno); + fatal_perror("check_ptrace : wait failed"); + if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ if (!count) - panic("check_ptrace : SYSEMU_SINGLESTEP " + fatal("check_ptrace : SYSEMU_SINGLESTEP " "doesn't singlestep"); n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if(n < 0) - panic("check_sysemu : failed to modify system " - "call return, errno = %d", errno); + fatal_perror("check_sysemu : failed to modify " + "system call return"); break; } else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; else - panic("check_ptrace : expected SIGTRAP or " - "(SIGTRAP|0x80), got status = %d", status); + fatal("check_ptrace : expected SIGTRAP or " + "(SIGTRAP | 0x80), got status = %d", status); } if (stop_ptraced_child(pid, stack, 0, 0) < 0) goto fail_stopped; sysemu_supported = 2; - printf("OK\n"); + non_fatal("OK\n"); if ( !force_sysemu_disabled ) set_using_sysemu(sysemu_supported); @@ -256,7 +283,7 @@ static void __init check_sysemu(void) fail: stop_ptraced_child(pid, stack, 1, 0); fail_stopped: - printf("missing\n"); + non_fatal("missing\n"); } static void __init check_ptrace(void) @@ -264,22 +291,25 @@ static void __init check_ptrace(void) void *stack; int pid, syscall, n, status; - printf("Checking that ptrace can change system call numbers..."); + non_fatal("Checking that ptrace can change system call numbers..."); pid = start_ptraced_child(&stack); - if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) - panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", errno); + if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + (void *) PTRACE_O_TRACESYSGOOD) < 0)) + fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); while(1){ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) - panic("check_ptrace : ptrace failed, errno = %d", - errno); + fatal_perror("check_ptrace : ptrace failed"); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) - panic("check_ptrace : wait failed, errno = %d", errno); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80))) - panic("check_ptrace : expected (SIGTRAP|0x80), " - "got status = %d", status); + fatal_perror("check_ptrace : wait failed"); + + if(!WIFSTOPPED(status) || + (WSTOPSIG(status) != (SIGTRAP | 0x80))) + fatal("check_ptrace : expected (SIGTRAP|0x80), " + "got status = %d", status); syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0); @@ -287,13 +317,13 @@ static void __init check_ptrace(void) n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getppid); if(n < 0) - panic("check_ptrace : failed to modify system " - "call, errno = %d", errno); + fatal_perror("check_ptrace : failed to modify " + "system call"); break; } } stop_ptraced_child(pid, stack, 0, 1); - printf("OK\n"); + non_fatal("OK\n"); check_sysemu(); } @@ -352,22 +382,22 @@ static inline void check_skas3_ptrace_faultinfo(void) void *stack; int pid, n; - printf(" - PTRACE_FAULTINFO..."); + non_fatal(" - PTRACE_FAULTINFO..."); pid = start_ptraced_child(&stack); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { ptrace_faultinfo = 0; if(errno == EIO) - printf("not found\n"); + non_fatal("not found\n"); else perror("not found"); } else { if (!ptrace_faultinfo) - printf("found but disabled on command line\n"); + non_fatal("found but disabled on command line\n"); else - printf("found\n"); + non_fatal("found\n"); } init_registers(pid); @@ -385,13 +415,13 @@ static inline void check_skas3_ptrace_ldt(void) .ptr = ldtbuf, .bytecount = sizeof(ldtbuf)}; - printf(" - PTRACE_LDT..."); + non_fatal(" - PTRACE_LDT..."); pid = start_ptraced_child(&stack); n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); if (n < 0) { if(errno == EIO) - printf("not found\n"); + non_fatal("not found\n"); else { perror("not found"); } @@ -399,9 +429,9 @@ static inline void check_skas3_ptrace_ldt(void) } else { if(ptrace_ldt) - printf("found\n"); + non_fatal("found\n"); else - printf("found, but use is disabled\n"); + non_fatal("found, but use is disabled\n"); } stop_ptraced_child(pid, stack, 1, 1); @@ -416,22 +446,22 @@ static inline void check_skas3_ptrace_ldt(void) static inline void check_skas3_proc_mm(void) { - printf(" - /proc/mm..."); + non_fatal(" - /proc/mm..."); if (access("/proc/mm", W_OK) < 0) { proc_mm = 0; - printf("not found\n"); + perror("not found"); } else { if (!proc_mm) - printf("found but disabled on command line\n"); + non_fatal("found but disabled on command line\n"); else - printf("found\n"); + non_fatal("found\n"); } } int can_do_skas(void) { - printf("Checking for the skas3 patch in the host:\n"); + non_fatal("Checking for the skas3 patch in the host:\n"); check_skas3_proc_mm(); check_skas3_ptrace_faultinfo(); -- cgit v1.2.3 From f355559cf78455ed6be103b020e4b800230c64eb Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:29 -0800 Subject: [PATCH] uml: x86_64 thread fixes x86_64 needs some TLS fixes. What was missing was remembering the child thread id during clone and stuffing it into the child during each context switch. The %fs value is stored separately in the thread structure since the host controls what effect it has on the actual register file. The host also needs to store it in its own thread struct, so we need the value kept outside the register file. arch_prctl_skas was fixed to call PTRACE_ARCH_PRCTL appropriately. There is some saving and restoring of registers in the ARCH_SET_* cases so that the correct set of registers are changed on the host and restored to the process when it runs again. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/os.h | 2 + arch/um/os-Linux/sys-x86_64/Makefile | 2 +- arch/um/os-Linux/sys-x86_64/prctl.c | 12 ++++++ arch/um/sys-x86_64/syscalls.c | 73 +++++++++++++++++++++++++++--------- arch/um/sys-x86_64/tls.c | 11 ++++-- 5 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 arch/um/os-Linux/sys-x86_64/prctl.c (limited to 'arch/um') diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 8f602667296..8629bd19149 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -340,4 +340,6 @@ extern void maybe_sigio_broken(int fd, int read); extern void sig_handler_common_skas(int sig, void *sc_ptr); extern void user_signal(int sig, union uml_pt_regs *regs, int pid); +extern int os_arch_prctl(int pid, int code, unsigned long *addr); + #endif diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile index f67842a7735..7955e061a67 100644 --- a/arch/um/os-Linux/sys-x86_64/Makefile +++ b/arch/um/os-Linux/sys-x86_64/Makefile @@ -3,7 +3,7 @@ # Licensed under the GPL # -obj-$(CONFIG_MODE_SKAS) = registers.o signal.o +obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o USER_OBJS := $(obj-y) diff --git a/arch/um/os-Linux/sys-x86_64/prctl.c b/arch/um/os-Linux/sys-x86_64/prctl.c new file mode 100644 index 00000000000..9d34eddb517 --- /dev/null +++ b/arch/um/os-Linux/sys-x86_64/prctl.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com}) + * Licensed under the GPL + */ + +#include +#include + +int os_arch_prctl(int pid, int code, unsigned long *addr) +{ + return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code); +} diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 73ce4463f70..f309fa9bc23 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -16,6 +16,7 @@ #include "asm/prctl.h" /* XXX This should get the constants from libc */ #include "choose-mode.h" #include "kern.h" +#include "os.h" asmlinkage long sys_uname64(struct new_utsname __user * name) { @@ -58,40 +59,67 @@ static long arch_prctl_tt(int code, unsigned long addr) #ifdef CONFIG_MODE_SKAS -/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */ -static long arch_prctl_skas(int code, unsigned long addr) +static long arch_prctl_skas(int code, unsigned long __user *addr) { - long ret = 0; + unsigned long *ptr = addr, tmp; + long ret; + int pid = current->mm->context.skas.id.u.pid; + /* + * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to + * be safe), we need to call arch_prctl on the host because + * setting %fs may result in something else happening (like a + * GDT being set instead). So, we let the host fiddle the + * registers and restore them afterwards. + * + * So, the saved registers are stored to the process (this + * needed because a stub may have been the last thing to run), + * arch_prctl is run on the host, then the registers are read + * back. + */ switch(code){ case ARCH_SET_FS: - current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr; - break; case ARCH_SET_GS: - current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; + restore_registers(pid, ¤t->thread.regs.regs); + break; + case ARCH_GET_FS: + case ARCH_GET_GS: + /* + * With these two, we read to a local pointer and + * put_user it to the userspace pointer that we were + * given. If addr isn't valid (because it hasn't been + * faulted in or is just bogus), we want put_user to + * fault it in (or return -EFAULT) instead of having + * the host return -EFAULT. + */ + ptr = &tmp; + } + + ret = os_arch_prctl(pid, code, ptr); + if(ret) + return ret; + + switch(code){ + case ARCH_SET_FS: + case ARCH_SET_GS: + save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: - ret = put_user(current->thread.regs.regs.skas. - regs[FS_BASE / sizeof(unsigned long)], - (unsigned long __user *)addr); + ret = put_user(tmp, addr); break; case ARCH_GET_GS: - ret = put_user(current->thread.regs.regs.skas. - regs[GS_BASE / sizeof(unsigned long)], - (unsigned long __user *)addr); + ret = put_user(tmp, addr); break; - default: - ret = -EINVAL; - break; } - return(ret); + return ret; } #endif long sys_arch_prctl(int code, unsigned long addr) { - return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr)); + return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, + (unsigned long __user *) addr); } long sys_clone(unsigned long clone_flags, unsigned long newsp, @@ -105,5 +133,14 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, child_tid); current->thread.forking = 0; - return(ret); + return ret; +} + +void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) +{ + if(to->thread.arch.fs == 0) + return; + + arch_prctl_skas(ARCH_SET_FS, (void __user *) to->thread.arch.fs); } + diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c index ce1bf1b81c4..febbc94be25 100644 --- a/arch/um/sys-x86_64/tls.c +++ b/arch/um/sys-x86_64/tls.c @@ -1,14 +1,17 @@ #include "linux/sched.h" -void debug_arch_force_load_TLS(void) -{ -} - void clear_flushed_tls(struct task_struct *task) { } int arch_copy_tls(struct task_struct *t) { + /* + * If CLONE_SETTLS is set, we need to save the thread id + * (which is argument 5, child_tid, of clone) so it can be set + * during context switches. + */ + t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)]; + return 0; } -- cgit v1.2.3 From 6e6d74cfac782a3a4cb5111bd9c25cd95d6b7c6c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 10 Feb 2007 01:44:30 -0800 Subject: [PATCH] uml: x86_64 ptrace fixes This patch fixes some missing ptrace bits on x86_64. PTRACE_ARCH_PRCTL is hooked up and implemented. This required generalizing arch_prctl_skas slightly to take a task_struct to modify. Previously, it always operated on current. Reading and writing the debug registers is also enabled by un-ifdefing the code that implements that. It turns out that x86_64 is identical to i386, so the same code can be used. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/ptrace.c | 7 +++++++ arch/um/sys-x86_64/ptrace.c | 5 ----- arch/um/sys-x86_64/syscalls.c | 14 ++++++++------ 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 9a77fb3c269..627742d8943 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -18,6 +18,7 @@ #include "kern_util.h" #include "skas_ptrace.h" #include "sysdep/ptrace.h" +#include "os.h" static inline void set_singlestepping(struct task_struct *child, int on) { @@ -240,6 +241,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; } +#endif +#ifdef PTRACE_ARCH_PRCTL + case PTRACE_ARCH_PRCTL: + /* XXX Calls ptrace on the host - needs some SMP thinking */ + ret = arch_prctl_skas(child, data, (void *) addr); + break; #endif default: ret = ptrace_request(child, request, addr, data); diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index 147bbf05cbc..55b66e09a98 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c @@ -71,8 +71,6 @@ int poke_user(struct task_struct *child, long addr, long data) if (addr < MAX_REG_OFFSET) return putreg(child, addr, data); - -#if 0 /* Need x86_64 debugregs handling */ else if((addr >= offsetof(struct user, u_debugreg[0])) && (addr <= offsetof(struct user, u_debugreg[7]))){ addr -= offsetof(struct user, u_debugreg[0]); @@ -81,7 +79,6 @@ int poke_user(struct task_struct *child, long addr, long data) child->thread.arch.debugregs[addr] = data; return 0; } -#endif return -EIO; } @@ -119,14 +116,12 @@ int peek_user(struct task_struct *child, long addr, long data) if(addr < MAX_REG_OFFSET){ tmp = getreg(child, addr); } -#if 0 /* Need x86_64 debugregs handling */ else if((addr >= offsetof(struct user, u_debugreg[0])) && (addr <= offsetof(struct user, u_debugreg[7]))){ addr -= offsetof(struct user, u_debugreg[0]); addr = addr >> 2; tmp = child->thread.arch.debugregs[addr]; } -#endif return put_user(tmp, (unsigned long *) data); } diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index f309fa9bc23..01b91f9fa78 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -59,18 +59,20 @@ static long arch_prctl_tt(int code, unsigned long addr) #ifdef CONFIG_MODE_SKAS -static long arch_prctl_skas(int code, unsigned long __user *addr) +long arch_prctl_skas(struct task_struct *task, int code, + unsigned long __user *addr) { unsigned long *ptr = addr, tmp; long ret; - int pid = current->mm->context.skas.id.u.pid; + int pid = task->mm->context.skas.id.u.pid; /* * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to * be safe), we need to call arch_prctl on the host because * setting %fs may result in something else happening (like a - * GDT being set instead). So, we let the host fiddle the - * registers and restore them afterwards. + * GDT or thread.fs being set instead). So, we let the host + * fiddle the registers and thread struct and restore the + * registers afterwards. * * So, the saved registers are stored to the process (this * needed because a stub may have been the last thing to run), @@ -118,7 +120,7 @@ static long arch_prctl_skas(int code, unsigned long __user *addr) long sys_arch_prctl(int code, unsigned long addr) { - return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, + return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code, (unsigned long __user *) addr); } @@ -141,6 +143,6 @@ void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) if(to->thread.arch.fs == 0) return; - arch_prctl_skas(ARCH_SET_FS, (void __user *) to->thread.arch.fs); + arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); } -- cgit v1.2.3 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') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index da0badcd755..f98d26e5138 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.2.3 From 5ea8176994003483a18c8fed580901e2125f8a83 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 11 Feb 2007 15:41:31 +0000 Subject: [PATCH] sort the devres mess out * Split the implementation-agnostic stuff in separate files. * Make sure that targets using non-default request_irq() pull kernel/irq/devres.o * Introduce new symbols (HAS_IOPORT and HAS_IOMEM) defaulting to positive; allow architectures to turn them off (we needed these symbols anyway for dependencies of quite a few drivers). * protect the ioport-related parts of lib/devres.o with CONFIG_HAS_IOPORT. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/um/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/um') diff --git a/arch/um/Kconfig b/arch/um/Kconfig index d32a80e6668..b3a21ba77cd 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -16,6 +16,9 @@ config MMU bool default y +config NO_IOMEM + def_bool y + mainmenu "Linux/Usermode Kernel Configuration" config ISA -- cgit v1.2.3 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') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 0e1e9a20a4d..01d4ab6b0ef 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.2.3 From 19bf7e7a414711dec0058556feda778105798f99 Mon Sep 17 00:00:00 2001 From: Alon Bar-Lev Date: Mon, 12 Feb 2007 00:54:23 -0800 Subject: [PATCH] Dynamic kernel command-line: um 1. Rename saved_command_line into boot_command_line. 2. Set command_line as __initdata. Signed-off-by: Alon Bar-Lev Cc: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/user_util.h | 2 +- arch/um/kernel/um_arch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index 06625fefef3..0f63003a2a3 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -38,7 +38,7 @@ extern unsigned long long highmem; extern char host_info[]; -extern char saved_command_line[]; +extern char __initdata boot_command_line[]; extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; extern unsigned long _unprotected_end; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 84e57f6da1d..668eba2d2e8 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -481,7 +481,7 @@ void __init setup_arch(char **cmdline_p) atomic_notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); paging_init(); - strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); + strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; setup_hostinfo(); } -- cgit v1.2.3 From 7a3a06d0e158fc82a6bf13e18439285c7791d2b8 Mon Sep 17 00:00:00 2001 From: Alon Bar-Lev Date: Mon, 12 Feb 2007 00:54:26 -0800 Subject: [PATCH] Dynamic kernel command-line: fixups Remove in-source externs, linux/init.h is included in all cases. This is a fixups for "Dynamic kernel command-line" patch. It also includes some uml __init fixups so that we can __initdata also its command_line. Signed-off-by: Alon Bar-Lev Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/user_util.h | 2 -- arch/um/kernel/um_arch.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index 0f63003a2a3..023575f6734 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -38,8 +38,6 @@ extern unsigned long long highmem; extern char host_info[]; -extern char __initdata boot_command_line[]; - extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; extern unsigned long _unprotected_end; extern unsigned long brk_start; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 668eba2d2e8..89c6dba731f 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -43,9 +43,9 @@ #define DEFAULT_COMMAND_LINE "root=98:0" /* Changed in linux_main and setup_arch, which run before SMP is started */ -static char command_line[COMMAND_LINE_SIZE] = { 0 }; +static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; -static void add_arg(char *arg) +static void __init add_arg(char *arg) { if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { printf("add_arg: Too many command line arguments!\n"); @@ -330,7 +330,7 @@ EXPORT_SYMBOL(end_iomem); extern char __binary_start; -int linux_main(int argc, char **argv) +int __init linux_main(int argc, char **argv) { unsigned long avail, diff; unsigned long virtmem_size, max_physmem; -- cgit v1.2.3 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') diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 73c5caa7a15..55601687b3b 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.2.3