aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-02-10 04:43:53 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:21 -0500
commitf28169d2000177e8b72ccc6d72887be779dceca8 (patch)
tree0ef842014c67d8a136cc26c99113b69e2ede87ea /arch
parentd79a580936396bbcd2f4fae2c6215f9cf81e3c0d (diff)
[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 <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/um/drivers/chan_kern.c77
-rw-r--r--arch/um/drivers/line.c66
-rw-r--r--arch/um/drivers/mconsole_kern.c40
-rw-r--r--arch/um/drivers/net_kern.c97
-rw-r--r--arch/um/drivers/ssl.c24
-rw-r--r--arch/um/drivers/stdio_console.c22
-rw-r--r--arch/um/drivers/ubd_kern.c132
-rw-r--r--arch/um/include/chan_kern.h2
-rw-r--r--arch/um/include/line.h8
-rw-r--r--arch/um/include/mconsole_kern.h15
-rw-r--r--arch/um/kernel/tt/gdb.c4
-rw-r--r--arch/um/kernel/tt/gdb_kern.c4
12 files changed, 253 insertions, 238 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 7d4190e55654..4e7e3cfa21f9 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -19,44 +19,11 @@
19#include "line.h" 19#include "line.h"
20#include "os.h" 20#include "os.h"
21 21
22/* XXX: could well be moved to somewhere else, if needed. */
23static int my_printf(const char * fmt, ...)
24 __attribute__ ((format (printf, 1, 2)));
25
26static int my_printf(const char * fmt, ...)
27{
28 /* Yes, can be called on atomic context.*/
29 char *buf = kmalloc(4096, GFP_ATOMIC);
30 va_list args;
31 int r;
32
33 if (!buf) {
34 /* We print directly fmt.
35 * Yes, yes, yes, feel free to complain. */
36 r = strlen(fmt);
37 } else {
38 va_start(args, fmt);
39 r = vsprintf(buf, fmt, args);
40 va_end(args);
41 fmt = buf;
42 }
43
44 if (r)
45 r = os_write_file(1, fmt, r);
46 return r;
47
48}
49
50#ifdef CONFIG_NOCONFIG_CHAN 22#ifdef CONFIG_NOCONFIG_CHAN
51/* Despite its name, there's no added trailing newline. */ 23static void *not_configged_init(char *str, int device,
52static int my_puts(const char * buf) 24 const struct chan_opts *opts)
53{ 25{
54 return os_write_file(1, buf, strlen(buf)); 26 printk("Using a channel type which is configured out of "
55}
56
57static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{
59 my_puts("Using a channel type which is configured out of "
60 "UML\n"); 27 "UML\n");
61 return NULL; 28 return NULL;
62} 29}
@@ -64,34 +31,34 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
64static int not_configged_open(int input, int output, int primary, void *data, 31static int not_configged_open(int input, int output, int primary, void *data,
65 char **dev_out) 32 char **dev_out)
66{ 33{
67 my_puts("Using a channel type which is configured out of " 34 printk("Using a channel type which is configured out of "
68 "UML\n"); 35 "UML\n");
69 return -ENODEV; 36 return -ENODEV;
70} 37}
71 38
72static void not_configged_close(int fd, void *data) 39static void not_configged_close(int fd, void *data)
73{ 40{
74 my_puts("Using a channel type which is configured out of " 41 printk("Using a channel type which is configured out of "
75 "UML\n"); 42 "UML\n");
76} 43}
77 44
78static int not_configged_read(int fd, char *c_out, void *data) 45static int not_configged_read(int fd, char *c_out, void *data)
79{ 46{
80 my_puts("Using a channel type which is configured out of " 47 printk("Using a channel type which is configured out of "
81 "UML\n"); 48 "UML\n");
82 return -EIO; 49 return -EIO;
83} 50}
84 51
85static int not_configged_write(int fd, const char *buf, int len, void *data) 52static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 53{
87 my_puts("Using a channel type which is configured out of " 54 printk("Using a channel type which is configured out of "
88 "UML\n"); 55 "UML\n");
89 return -EIO; 56 return -EIO;
90} 57}
91 58
92static int not_configged_console_write(int fd, const char *buf, int len) 59static int not_configged_console_write(int fd, const char *buf, int len)
93{ 60{
94 my_puts("Using a channel type which is configured out of " 61 printk("Using a channel type which is configured out of "
95 "UML\n"); 62 "UML\n");
96 return -EIO; 63 return -EIO;
97} 64}
@@ -99,14 +66,14 @@ static int not_configged_console_write(int fd, const char *buf, int len)
99static int not_configged_window_size(int fd, void *data, unsigned short *rows, 66static int not_configged_window_size(int fd, void *data, unsigned short *rows,
100 unsigned short *cols) 67 unsigned short *cols)
101{ 68{
102 my_puts("Using a channel type which is configured out of " 69 printk("Using a channel type which is configured out of "
103 "UML\n"); 70 "UML\n");
104 return -ENODEV; 71 return -ENODEV;
105} 72}
106 73
107static void not_configged_free(void *data) 74static void not_configged_free(void *data)
108{ 75{
109 my_puts("Using a channel type which is configured out of " 76 printk("Using a channel type which is configured out of "
110 "UML\n"); 77 "UML\n");
111} 78}
112 79
@@ -534,7 +501,7 @@ static const struct chan_type chan_table[] = {
534}; 501};
535 502
536static struct chan *parse_chan(struct line *line, char *str, int device, 503static struct chan *parse_chan(struct line *line, char *str, int device,
537 const struct chan_opts *opts) 504 const struct chan_opts *opts, char **error_out)
538{ 505{
539 const struct chan_type *entry; 506 const struct chan_type *entry;
540 const struct chan_ops *ops; 507 const struct chan_ops *ops;
@@ -553,19 +520,21 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
553 } 520 }
554 } 521 }
555 if(ops == NULL){ 522 if(ops == NULL){
556 my_printf("parse_chan couldn't parse \"%s\"\n", 523 *error_out = "No match for configured backends";
557 str);
558 return NULL; 524 return NULL;
559 } 525 }
560 if(ops->init == NULL) 526
561 return NULL;
562 data = (*ops->init)(str, device, opts); 527 data = (*ops->init)(str, device, opts);
563 if(data == NULL) 528 if(data == NULL){
529 *error_out = "Configuration failed";
564 return NULL; 530 return NULL;
531 }
565 532
566 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 533 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
567 if(chan == NULL) 534 if(chan == NULL){
535 *error_out = "Memory allocation failed";
568 return NULL; 536 return NULL;
537 }
569 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 538 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
570 .free_list = 539 .free_list =
571 LIST_HEAD_INIT(chan->free_list), 540 LIST_HEAD_INIT(chan->free_list),
@@ -582,7 +551,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
582} 551}
583 552
584int parse_chan_pair(char *str, struct line *line, int device, 553int parse_chan_pair(char *str, struct line *line, int device,
585 const struct chan_opts *opts) 554 const struct chan_opts *opts, char **error_out)
586{ 555{
587 struct list_head *chans = &line->chan_list; 556 struct list_head *chans = &line->chan_list;
588 struct chan *new, *chan; 557 struct chan *new, *chan;
@@ -599,14 +568,14 @@ int parse_chan_pair(char *str, struct line *line, int device,
599 in = str; 568 in = str;
600 *out = '\0'; 569 *out = '\0';
601 out++; 570 out++;
602 new = parse_chan(line, in, device, opts); 571 new = parse_chan(line, in, device, opts, error_out);
603 if(new == NULL) 572 if(new == NULL)
604 return -1; 573 return -1;
605 574
606 new->input = 1; 575 new->input = 1;
607 list_add(&new->list, chans); 576 list_add(&new->list, chans);
608 577
609 new = parse_chan(line, out, device, opts); 578 new = parse_chan(line, out, device, opts, error_out);
610 if(new == NULL) 579 if(new == NULL)
611 return -1; 580 return -1;
612 581
@@ -614,7 +583,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
614 new->output = 1; 583 new->output = 1;
615 } 584 }
616 else { 585 else {
617 new = parse_chan(line, str, device, opts); 586 new = parse_chan(line, str, device, opts, error_out);
618 if(new == NULL) 587 if(new == NULL)
619 return -1; 588 return -1;
620 589
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 799fca3644e9..e620ed46ed3f 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)
549 close_chan(&lines[i].chan_list, 0); 549 close_chan(&lines[i].chan_list, 0);
550} 550}
551 551
552static void setup_one_line(struct line *lines, int n, char *init, int init_prio) 552static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
553 char **error_out)
553{ 554{
554 struct line *line = &lines[n]; 555 struct line *line = &lines[n];
556 int err = -EINVAL;
555 557
556 spin_lock(&line->count_lock); 558 spin_lock(&line->count_lock);
557 559
558 if(line->tty != NULL){ 560 if(line->tty != NULL){
559 printk("line_setup - device %d is open\n", n); 561 *error_out = "Device is already open";
560 goto out; 562 goto out;
561 } 563 }
562 564
@@ -569,18 +571,22 @@ static void setup_one_line(struct line *lines, int n, char *init, int init_prio)
569 line->valid = 1; 571 line->valid = 1;
570 } 572 }
571 } 573 }
574 err = 0;
572out: 575out:
573 spin_unlock(&line->count_lock); 576 spin_unlock(&line->count_lock);
577 return err;
574} 578}
575 579
576/* Common setup code for both startup command line and mconsole initialization. 580/* Common setup code for both startup command line and mconsole initialization.
577 * @lines contains the array (of size @num) to modify; 581 * @lines contains the array (of size @num) to modify;
578 * @init is the setup string; 582 * @init is the setup string;
583 * @error_out is an error string in the case of failure;
579 */ 584 */
580 585
581int line_setup(struct line *lines, unsigned int num, char *init) 586int line_setup(struct line *lines, unsigned int num, char *init,
587 char **error_out)
582{ 588{
583 int i, n; 589 int i, n, err;
584 char *end; 590 char *end;
585 591
586 if(*init == '=') { 592 if(*init == '=') {
@@ -591,52 +597,56 @@ int line_setup(struct line *lines, unsigned int num, char *init)
591 else { 597 else {
592 n = simple_strtoul(init, &end, 0); 598 n = simple_strtoul(init, &end, 0);
593 if(*end != '='){ 599 if(*end != '='){
594 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 600 *error_out = "Couldn't parse device number";
595 init); 601 return -EINVAL;
596 return 0;
597 } 602 }
598 init = end; 603 init = end;
599 } 604 }
600 init++; 605 init++;
601 606
602 if (n >= (signed int) num) { 607 if (n >= (signed int) num) {
603 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 608 *error_out = "Device number out of range";
604 n, num - 1); 609 return -EINVAL;
605 return 0; 610 }
611 else if (n >= 0){
612 err = setup_one_line(lines, n, init, INIT_ONE, error_out);
613 if(err)
614 return err;
606 } 615 }
607 else if (n >= 0)
608 setup_one_line(lines, n, init, INIT_ONE);
609 else { 616 else {
610 for(i = 0; i < num; i++) 617 for(i = 0; i < num; i++){
611 setup_one_line(lines, i, init, INIT_ALL); 618 err = setup_one_line(lines, i, init, INIT_ALL,
619 error_out);
620 if(err)
621 return err;
622 }
612 } 623 }
613 return n == -1 ? num : n; 624 return n == -1 ? num : n;
614} 625}
615 626
616int line_config(struct line *lines, unsigned int num, char *str, 627int line_config(struct line *lines, unsigned int num, char *str,
617 const struct chan_opts *opts) 628 const struct chan_opts *opts, char **error_out)
618{ 629{
619 struct line *line; 630 struct line *line;
620 char *new; 631 char *new;
621 int n; 632 int n;
622 633
623 if(*str == '='){ 634 if(*str == '='){
624 printk("line_config - can't configure all devices from " 635 *error_out = "Can't configure all devices from mconsole";
625 "mconsole\n"); 636 return -EINVAL;
626 return 1;
627 } 637 }
628 638
629 new = kstrdup(str, GFP_KERNEL); 639 new = kstrdup(str, GFP_KERNEL);
630 if(new == NULL){ 640 if(new == NULL){
631 printk("line_config - kstrdup failed\n"); 641 *error_out = "Failed to allocate memory";
632 return 1; 642 return -ENOMEM;
633 } 643 }
634 n = line_setup(lines, num, new); 644 n = line_setup(lines, num, new, error_out);
635 if(n < 0) 645 if(n < 0)
636 return 1; 646 return n;
637 647
638 line = &lines[n]; 648 line = &lines[n];
639 return parse_chan_pair(line->init_str, line, n, opts); 649 return parse_chan_pair(line->init_str, line, n, opts, error_out);
640} 650}
641 651
642int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 652int 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)
685 return n; 695 return n;
686} 696}
687 697
688int line_remove(struct line *lines, unsigned int num, int n) 698int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
689{ 699{
690 int err; 700 int err;
691 char config[sizeof("conxxxx=none\0")]; 701 char config[sizeof("conxxxx=none\0")];
692 702
693 sprintf(config, "%d=none", n); 703 sprintf(config, "%d=none", n);
694 err = line_setup(lines, num, config); 704 err = line_setup(lines, num, config, error_out);
695 if(err >= 0) 705 if(err >= 0)
696 err = 0; 706 err = 0;
697 return err; 707 return err;
@@ -740,6 +750,7 @@ static LIST_HEAD(winch_handlers);
740void lines_init(struct line *lines, int nlines, struct chan_opts *opts) 750void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
741{ 751{
742 struct line *line; 752 struct line *line;
753 char *error;
743 int i; 754 int i;
744 755
745 for(i = 0; i < nlines; i++){ 756 for(i = 0; i < nlines; i++){
@@ -754,8 +765,9 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
754 if(line->init_str == NULL) 765 if(line->init_str == NULL)
755 printk("lines_init - kstrdup returned NULL\n"); 766 printk("lines_init - kstrdup returned NULL\n");
756 767
757 if(parse_chan_pair(line->init_str, line, i, opts)){ 768 if(parse_chan_pair(line->init_str, line, i, opts, &error)){
758 printk("parse_chan_pair failed for device %d\n", i); 769 printk("parse_chan_pair failed for device %d : %s\n",
770 i, error);
759 line->valid = 0; 771 line->valid = 0;
760 } 772 }
761 } 773 }
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 96f0189327af..832d5c766ca8 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;
371static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages); 371static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages);
372static int unplug_index = UNPLUGGED_PER_PAGE; 372static int unplug_index = UNPLUGGED_PER_PAGE;
373 373
374static int mem_config(char *str) 374static int mem_config(char *str, char **error_out)
375{ 375{
376 unsigned long long diff; 376 unsigned long long diff;
377 int err = -EINVAL, i, add; 377 int err = -EINVAL, i, add;
378 char *ret; 378 char *ret;
379 379
380 if(str[0] != '=') 380 if(str[0] != '='){
381 *error_out = "Expected '=' after 'mem'";
381 goto out; 382 goto out;
383 }
382 384
383 str++; 385 str++;
384 if(str[0] == '-') 386 if(str[0] == '-')
@@ -386,12 +388,17 @@ static int mem_config(char *str)
386 else if(str[0] == '+'){ 388 else if(str[0] == '+'){
387 add = 1; 389 add = 1;
388 } 390 }
389 else goto out; 391 else {
392 *error_out = "Expected increment to start with '-' or '+'";
393 goto out;
394 }
390 395
391 str++; 396 str++;
392 diff = memparse(str, &ret); 397 diff = memparse(str, &ret);
393 if(*ret != '\0') 398 if(*ret != '\0'){
399 *error_out = "Failed to parse memory increment";
394 goto out; 400 goto out;
401 }
395 402
396 diff /= PAGE_SIZE; 403 diff /= PAGE_SIZE;
397 404
@@ -435,11 +442,14 @@ static int mem_config(char *str)
435 unplugged = list_entry(entry, 442 unplugged = list_entry(entry,
436 struct unplugged_pages, 443 struct unplugged_pages,
437 list); 444 list);
438 unplugged->pages[unplug_index++] = addr;
439 err = os_drop_memory(addr, PAGE_SIZE); 445 err = os_drop_memory(addr, PAGE_SIZE);
440 if(err) 446 if(err){
441 printk("Failed to release memory - " 447 printk("Failed to release memory - "
442 "errno = %d\n", err); 448 "errno = %d\n", err);
449 *error_out = "Failed to release memory";
450 goto out;
451 }
452 unplugged->pages[unplug_index++] = addr;
443 } 453 }
444 454
445 unplugged_pages_count++; 455 unplugged_pages_count++;
@@ -470,8 +480,9 @@ static int mem_id(char **str, int *start_out, int *end_out)
470 return 0; 480 return 0;
471} 481}
472 482
473static int mem_remove(int n) 483static int mem_remove(int n, char **error_out)
474{ 484{
485 *error_out = "Memory doesn't support the remove operation";
475 return -EBUSY; 486 return -EBUSY;
476} 487}
477 488
@@ -542,7 +553,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
542void mconsole_config(struct mc_request *req) 553void mconsole_config(struct mc_request *req)
543{ 554{
544 struct mc_device *dev; 555 struct mc_device *dev;
545 char *ptr = req->request.data, *name; 556 char *ptr = req->request.data, *name, *error_string = "";
546 int err; 557 int err;
547 558
548 ptr += strlen("config"); 559 ptr += strlen("config");
@@ -559,8 +570,8 @@ void mconsole_config(struct mc_request *req)
559 ptr++; 570 ptr++;
560 571
561 if(*ptr == '='){ 572 if(*ptr == '='){
562 err = (*dev->config)(name); 573 err = (*dev->config)(name, &error_string);
563 mconsole_reply(req, "", err, 0); 574 mconsole_reply(req, error_string, err, 0);
564 } 575 }
565 else mconsole_get_config(dev->get_config, req, name); 576 else mconsole_get_config(dev->get_config, req, name);
566} 577}
@@ -595,13 +606,16 @@ void mconsole_remove(struct mc_request *req)
595 goto out; 606 goto out;
596 } 607 }
597 608
598 err = (*dev->remove)(n); 609 err_msg = NULL;
610 err = (*dev->remove)(n, &err_msg);
599 switch(err){ 611 switch(err){
600 case -ENODEV: 612 case -ENODEV:
601 err_msg = "Device doesn't exist"; 613 if(err_msg == NULL)
614 err_msg = "Device doesn't exist";
602 break; 615 break;
603 case -EBUSY: 616 case -EBUSY:
604 err_msg = "Device is currently open"; 617 if(err_msg == NULL)
618 err_msg = "Device is currently open";
605 break; 619 break;
606 default: 620 default:
607 break; 621 break;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index afe3d427ddfa..07e839e387db 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net). 3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here. 4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL. 5 * Licensed under the GPL.
@@ -91,8 +91,8 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
91 spin_lock(&lp->lock); 91 spin_lock(&lp->lock);
92 while((err = uml_net_rx(dev)) > 0) ; 92 while((err = uml_net_rx(dev)) > 0) ;
93 if(err < 0) { 93 if(err < 0) {
94 printk(KERN_ERR 94 printk(KERN_ERR
95 "Device '%s' read returned %d, shutting it down\n", 95 "Device '%s' read returned %d, shutting it down\n",
96 dev->name, err); 96 dev->name, err);
97 /* dev_close can't be called in interrupt context, and takes 97 /* dev_close can't be called in interrupt context, and takes
98 * again lp->lock. 98 * again lp->lock.
@@ -159,7 +159,7 @@ out:
159static int uml_net_close(struct net_device *dev) 159static int uml_net_close(struct net_device *dev)
160{ 160{
161 struct uml_net_private *lp = dev->priv; 161 struct uml_net_private *lp = dev->priv;
162 162
163 netif_stop_queue(dev); 163 netif_stop_queue(dev);
164 164
165 free_irq(dev->irq, dev); 165 free_irq(dev->irq, dev);
@@ -194,7 +194,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
194 194
195 /* this is normally done in the interrupt when tx finishes */ 195 /* this is normally done in the interrupt when tx finishes */
196 netif_wake_queue(dev); 196 netif_wake_queue(dev);
197 } 197 }
198 else if(len == 0){ 198 else if(len == 0){
199 netif_start_queue(dev); 199 netif_start_queue(dev);
200 lp->stats.tx_dropped++; 200 lp->stats.tx_dropped++;
@@ -333,7 +333,7 @@ static int eth_configure(int n, void *init, char *mac,
333 struct uml_net_private *lp; 333 struct uml_net_private *lp;
334 int save, err, size; 334 int save, err, size;
335 335
336 size = transport->private_size + sizeof(struct uml_net_private) + 336 size = transport->private_size + sizeof(struct uml_net_private) +
337 sizeof(((struct uml_net_private *) 0)->user); 337 sizeof(((struct uml_net_private *) 0)->user);
338 338
339 device = kzalloc(sizeof(*device), GFP_KERNEL); 339 device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -438,7 +438,7 @@ static int eth_configure(int n, void *init, char *mac,
438 lp->tl.function = uml_net_user_timer_expire; 438 lp->tl.function = uml_net_user_timer_expire;
439 memcpy(lp->mac, device->mac, sizeof(lp->mac)); 439 memcpy(lp->mac, device->mac, sizeof(lp->mac));
440 440
441 if (transport->user->init) 441 if (transport->user->init)
442 (*transport->user->init)(&lp->user, dev); 442 (*transport->user->init)(&lp->user, dev);
443 443
444 set_ether_mac(dev, device->mac); 444 set_ether_mac(dev, device->mac);
@@ -463,35 +463,33 @@ static struct uml_net *find_device(int n)
463 return(device); 463 return(device);
464} 464}
465 465
466static int eth_parse(char *str, int *index_out, char **str_out) 466static int eth_parse(char *str, int *index_out, char **str_out,
467 char **error_out)
467{ 468{
468 char *end; 469 char *end;
469 int n; 470 int n, err = -EINVAL;;
470 471
471 n = simple_strtoul(str, &end, 0); 472 n = simple_strtoul(str, &end, 0);
472 if(end == str){ 473 if(end == str){
473 printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); 474 *error_out = "Bad device number";
474 return(1); 475 return err;
475 }
476 if(n < 0){
477 printk(KERN_ERR "eth_setup: device %d is negative\n", n);
478 return(1);
479 } 476 }
477
480 str = end; 478 str = end;
481 if(*str != '='){ 479 if(*str != '='){
482 printk(KERN_ERR 480 *error_out = "Expected '=' after device number";
483 "eth_setup: expected '=' after device number\n"); 481 return err;
484 return(1);
485 } 482 }
483
486 str++; 484 str++;
487 if(find_device(n)){ 485 if(find_device(n)){
488 printk(KERN_ERR "eth_setup: Device %d already configured\n", 486 *error_out = "Device already configured";
489 n); 487 return err;
490 return(1);
491 } 488 }
492 if(index_out) *index_out = n; 489
490 *index_out = n;
493 *str_out = str; 491 *str_out = str;
494 return(0); 492 return 0;
495} 493}
496 494
497struct eth_init { 495struct eth_init {
@@ -581,11 +579,15 @@ static int eth_setup_common(char *str, int index)
581static int eth_setup(char *str) 579static int eth_setup(char *str)
582{ 580{
583 struct eth_init *new; 581 struct eth_init *new;
582 char *error;
584 int n, err; 583 int n, err;
585 584
586 err = eth_parse(str, &n, &str); 585 err = eth_parse(str, &n, &str, &error);
587 if(err) 586 if(err){
587 printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n",
588 str, error);
588 return 1; 589 return 1;
590 }
589 591
590 new = alloc_bootmem(sizeof(*new)); 592 new = alloc_bootmem(sizeof(*new));
591 if (new == NULL){ 593 if (new == NULL){
@@ -619,26 +621,30 @@ static int eth_init(void)
619 if(eth_setup_common(eth->init, eth->index)) 621 if(eth_setup_common(eth->init, eth->index))
620 list_del(&eth->list); 622 list_del(&eth->list);
621 } 623 }
622 624
623 return(1); 625 return(1);
624} 626}
625__initcall(eth_init); 627__initcall(eth_init);
626#endif 628#endif
627 629
628static int net_config(char *str) 630static int net_config(char *str, char **error_out)
629{ 631{
630 int n, err; 632 int n, err;
631 633
632 err = eth_parse(str, &n, &str); 634 err = eth_parse(str, &n, &str, error_out);
633 if(err) return(err); 635 if(err)
636 return err;
634 637
638 /* This string is broken up and the pieces used by the underlying
639 * driver. So, it is freed only if eth_setup_common fails.
640 */
635 str = kstrdup(str, GFP_KERNEL); 641 str = kstrdup(str, GFP_KERNEL);
636 if(str == NULL){ 642 if(str == NULL){
637 printk(KERN_ERR "net_config failed to strdup string\n"); 643 *error_out = "net_config failed to strdup string";
638 return(-1); 644 return -ENOMEM;
639 } 645 }
640 err = !eth_setup_common(str, n); 646 err = !eth_setup_common(str, n);
641 if(err) 647 if(err)
642 kfree(str); 648 kfree(str);
643 return(err); 649 return(err);
644} 650}
@@ -658,7 +664,7 @@ static int net_id(char **str, int *start_out, int *end_out)
658 return n; 664 return n;
659} 665}
660 666
661static int net_remove(int n) 667static int net_remove(int n, char **error_out)
662{ 668{
663 struct uml_net *device; 669 struct uml_net *device;
664 struct net_device *dev; 670 struct net_device *dev;
@@ -727,7 +733,7 @@ struct notifier_block uml_inetaddr_notifier = {
727static int uml_net_init(void) 733static int uml_net_init(void)
728{ 734{
729 struct list_head *ele; 735 struct list_head *ele;
730 struct uml_net_private *lp; 736 struct uml_net_private *lp;
731 struct in_device *ip; 737 struct in_device *ip;
732 struct in_ifaddr *in; 738 struct in_ifaddr *in;
733 739
@@ -747,7 +753,7 @@ static int uml_net_init(void)
747 uml_inetaddr_event(NULL, NETDEV_UP, in); 753 uml_inetaddr_event(NULL, NETDEV_UP, in);
748 in = in->ifa_next; 754 in = in->ifa_next;
749 } 755 }
750 } 756 }
751 757
752 return(0); 758 return(0);
753} 759}
@@ -783,8 +789,8 @@ struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
783 return(skb); 789 return(skb);
784} 790}
785 791
786void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, 792void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
787 void *), 793 void *),
788 void *arg) 794 void *arg)
789{ 795{
790 struct net_device *dev = d; 796 struct net_device *dev = d;
@@ -809,11 +815,11 @@ int dev_netmask(void *d, void *m)
809 struct in_ifaddr *in; 815 struct in_ifaddr *in;
810 __be32 *mask_out = m; 816 __be32 *mask_out = m;
811 817
812 if(ip == NULL) 818 if(ip == NULL)
813 return(1); 819 return(1);
814 820
815 in = ip->ifa_list; 821 in = ip->ifa_list;
816 if(in == NULL) 822 if(in == NULL)
817 return(1); 823 return(1);
818 824
819 *mask_out = in->ifa_mask; 825 *mask_out = in->ifa_mask;
@@ -835,7 +841,7 @@ void free_output_buffer(void *buffer)
835 free_pages((unsigned long) buffer, 0); 841 free_pages((unsigned long) buffer, 0);
836} 842}
837 843
838int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, 844int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
839 char **gate_addr) 845 char **gate_addr)
840{ 846{
841 char *remain; 847 char *remain;
@@ -854,14 +860,3 @@ unsigned short eth_protocol(struct sk_buff *skb)
854{ 860{
855 return(eth_type_trans(skb, skb->dev)); 861 return(eth_type_trans(skb, skb->dev));
856} 862}
857
858/*
859 * Overrides for Emacs so that we follow Linus's tabbing style.
860 * Emacs will notice this stuff at the end of the file and automatically
861 * adjust the settings for this buffer only. This must remain at the end
862 * of the file.
863 * ---------------------------------------------------------------------------
864 * Local variables:
865 * c-file-style: "linux"
866 * End:
867 */
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index ed9c59082d0d..1e82430b8444 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -46,9 +46,9 @@ static struct chan_opts opts = {
46 .in_kernel = 1, 46 .in_kernel = 1,
47}; 47};
48 48
49static int ssl_config(char *str); 49static int ssl_config(char *str, char **error_out);
50static int ssl_get_config(char *dev, char *str, int size, char **error_out); 50static int ssl_get_config(char *dev, char *str, int size, char **error_out);
51static int ssl_remove(int n); 51static int ssl_remove(int n, char **error_out);
52 52
53static struct line_driver driver = { 53static struct line_driver driver = {
54 .name = "UML serial line", 54 .name = "UML serial line",
@@ -80,9 +80,10 @@ static struct line serial_lines[NR_PORTS] =
80 80
81static struct lines lines = LINES_INIT(NR_PORTS); 81static struct lines lines = LINES_INIT(NR_PORTS);
82 82
83static int ssl_config(char *str) 83static int ssl_config(char *str, char **error_out)
84{ 84{
85 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts); 85 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts,
86 error_out);
86} 87}
87 88
88static int ssl_get_config(char *dev, char *str, int size, char **error_out) 89static 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)
91 size, error_out); 92 size, error_out);
92} 93}
93 94
94static int ssl_remove(int n) 95static int ssl_remove(int n, char **error_out)
95{ 96{
96 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); 97 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n,
98 error_out);
97} 99}
98 100
99static int ssl_open(struct tty_struct *tty, struct file *filp) 101static int ssl_open(struct tty_struct *tty, struct file *filp)
@@ -212,7 +214,15 @@ __uml_exitcall(ssl_exit);
212 214
213static int ssl_chan_setup(char *str) 215static int ssl_chan_setup(char *str)
214{ 216{
215 return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str); 217 char *error;
218 int ret;
219
220 ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error);
221 if(ret < 0)
222 printk(KERN_ERR "Failed to set up serial line with "
223 "configuration string \"%s\" : %s\n", str, error);
224
225 return 1;
216} 226}
217 227
218__setup("ssl", ssl_chan_setup); 228__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 9b2dd0b8a43b..3cbfe3a88607 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -52,9 +52,9 @@ static struct chan_opts opts = {
52 .in_kernel = 1, 52 .in_kernel = 1,
53}; 53};
54 54
55static int con_config(char *str); 55static int con_config(char *str, char **error_out);
56static int con_get_config(char *dev, char *str, int size, char **error_out); 56static int con_get_config(char *dev, char *str, int size, char **error_out);
57static int con_remove(int n); 57static int con_remove(int n, char **con_remove);
58 58
59static struct line_driver driver = { 59static struct line_driver driver = {
60 .name = "UML console", 60 .name = "UML console",
@@ -87,9 +87,9 @@ static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
87 [ 1 ... MAX_TTYS - 1 ] = 87 [ 1 ... MAX_TTYS - 1 ] =
88 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 88 LINE_INIT(CONFIG_CON_CHAN, &driver) };
89 89
90static int con_config(char *str) 90static int con_config(char *str, char **error_out)
91{ 91{
92 return line_config(vts, ARRAY_SIZE(vts), str, &opts); 92 return line_config(vts, ARRAY_SIZE(vts), str, &opts, error_out);
93} 93}
94 94
95static int con_get_config(char *dev, char *str, int size, char **error_out) 95static 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)
97 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out); 97 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
98} 98}
99 99
100static int con_remove(int n) 100static int con_remove(int n, char **error_out)
101{ 101{
102 return line_remove(vts, ARRAY_SIZE(vts), n); 102 return line_remove(vts, ARRAY_SIZE(vts), n, error_out);
103} 103}
104 104
105static int con_open(struct tty_struct *tty, struct file *filp) 105static int con_open(struct tty_struct *tty, struct file *filp)
@@ -192,7 +192,15 @@ __uml_exitcall(console_exit);
192 192
193static int console_chan_setup(char *str) 193static int console_chan_setup(char *str)
194{ 194{
195 return line_setup(vts, ARRAY_SIZE(vts), str); 195 char *error;
196 int ret;
197
198 ret = line_setup(vts, ARRAY_SIZE(vts), str, &error);
199 if(ret < 0)
200 printk(KERN_ERR "Failed to set up console with "
201 "configuration string \"%s\" : %s\n", str, error);
202
203 return 1;
196} 204}
197__setup("con", console_chan_setup); 205__setup("con", console_chan_setup);
198__channel_help(console_chan_setup, "con"); 206__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 49c047b75cc5..f4db97efc014 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)
286 * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it 286 * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it
287 * should not be freed on exit. 287 * should not be freed on exit.
288 */ 288 */
289static int ubd_setup_common(char *str, int *index_out) 289static int ubd_setup_common(char *str, int *index_out, char **error_out)
290{ 290{
291 struct ubd *ubd_dev; 291 struct ubd *ubd_dev;
292 struct openflags flags = global_openflags; 292 struct openflags flags = global_openflags;
@@ -302,56 +302,54 @@ static int ubd_setup_common(char *str, int *index_out)
302 str++; 302 str++;
303 if(!strcmp(str, "sync")){ 303 if(!strcmp(str, "sync")){
304 global_openflags = of_sync(global_openflags); 304 global_openflags = of_sync(global_openflags);
305 return(0); 305 return 0;
306 } 306 }
307 major = simple_strtoul(str, &end, 0); 307 major = simple_strtoul(str, &end, 0);
308 if((*end != '\0') || (end == str)){ 308 if((*end != '\0') || (end == str)){
309 printk(KERN_ERR 309 *error_out = "Didn't parse major number";
310 "ubd_setup : didn't parse major number\n"); 310 return -EINVAL;
311 return(1);
312 } 311 }
313 312
314 err = 1; 313 err = -EINVAL;
315 mutex_lock(&ubd_lock); 314 mutex_lock(&ubd_lock);
316 if(fake_major != MAJOR_NR){ 315 if(fake_major != MAJOR_NR){
317 printk(KERN_ERR "Can't assign a fake major twice\n"); 316 *error_out = "Can't assign a fake major twice";
318 goto out1; 317 goto out1;
319 } 318 }
320 319
321 fake_major = major; 320 fake_major = major;
322 321
323 printk(KERN_INFO "Setting extra ubd major number to %d\n", 322 printk(KERN_INFO "Setting extra ubd major number to %d\n",
324 major); 323 major);
325 err = 0; 324 err = 0;
326 out1: 325 out1:
327 mutex_unlock(&ubd_lock); 326 mutex_unlock(&ubd_lock);
328 return(err); 327 return err;
329 } 328 }
330 329
331 n = parse_unit(&str); 330 n = parse_unit(&str);
332 if(n < 0){ 331 if(n < 0){
333 printk(KERN_ERR "ubd_setup : couldn't parse unit number " 332 *error_out = "Couldn't parse device number";
334 "'%s'\n", str); 333 return -EINVAL;
335 return(1);
336 } 334 }
337 if(n >= MAX_DEV){ 335 if(n >= MAX_DEV){
338 printk(KERN_ERR "ubd_setup : index %d out of range " 336 *error_out = "Device number out of range";
339 "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1); 337 return 1;
340 return(1);
341 } 338 }
342 339
343 err = 1; 340 err = -EBUSY;
344 mutex_lock(&ubd_lock); 341 mutex_lock(&ubd_lock);
345 342
346 ubd_dev = &ubd_devs[n]; 343 ubd_dev = &ubd_devs[n];
347 if(ubd_dev->file != NULL){ 344 if(ubd_dev->file != NULL){
348 printk(KERN_ERR "ubd_setup : device already configured\n"); 345 *error_out = "Device is already configured";
349 goto out; 346 goto out;
350 } 347 }
351 348
352 if (index_out) 349 if (index_out)
353 *index_out = n; 350 *index_out = n;
354 351
352 err = -EINVAL;
355 for (i = 0; i < sizeof("rscd="); i++) { 353 for (i = 0; i < sizeof("rscd="); i++) {
356 switch (*str) { 354 switch (*str) {
357 case 'r': 355 case 'r':
@@ -370,47 +368,54 @@ static int ubd_setup_common(char *str, int *index_out)
370 str++; 368 str++;
371 goto break_loop; 369 goto break_loop;
372 default: 370 default:
373 printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n"); 371 *error_out = "Expected '=' or flag letter "
372 "(r, s, c, or d)";
374 goto out; 373 goto out;
375 } 374 }
376 str++; 375 str++;
377 } 376 }
378 377
379 if (*str == '=') 378 if (*str == '=')
380 printk(KERN_ERR "ubd_setup : Too many flags specified\n"); 379 *error_out = "Too many flags specified";
381 else 380 else
382 printk(KERN_ERR "ubd_setup : Expected '='\n"); 381 *error_out = "Missing '='";
383 goto out; 382 goto out;
384 383
385break_loop: 384break_loop:
386 err = 0;
387 backing_file = strchr(str, ','); 385 backing_file = strchr(str, ',');
388 386
389 if (!backing_file) { 387 if (backing_file == NULL)
390 backing_file = strchr(str, ':'); 388 backing_file = strchr(str, ':');
391 }
392 389
393 if(backing_file){ 390 if(backing_file != NULL){
394 if(ubd_dev->no_cow) 391 if(ubd_dev->no_cow){
395 printk(KERN_ERR "Can't specify both 'd' and a " 392 *error_out = "Can't specify both 'd' and a cow file";
396 "cow file\n"); 393 goto out;
394 }
397 else { 395 else {
398 *backing_file = '\0'; 396 *backing_file = '\0';
399 backing_file++; 397 backing_file++;
400 } 398 }
401 } 399 }
400 err = 0;
402 ubd_dev->file = str; 401 ubd_dev->file = str;
403 ubd_dev->cow.file = backing_file; 402 ubd_dev->cow.file = backing_file;
404 ubd_dev->boot_openflags = flags; 403 ubd_dev->boot_openflags = flags;
405out: 404out:
406 mutex_unlock(&ubd_lock); 405 mutex_unlock(&ubd_lock);
407 return(err); 406 return err;
408} 407}
409 408
410static int ubd_setup(char *str) 409static int ubd_setup(char *str)
411{ 410{
412 ubd_setup_common(str, NULL); 411 char *error;
413 return(1); 412 int err;
413
414 err = ubd_setup_common(str, NULL, &error);
415 if(err)
416 printk(KERN_ERR "Failed to initialize device with \"%s\" : "
417 "%s\n", str, error);
418 return 1;
414} 419}
415 420
416__setup("ubd", ubd_setup); 421__setup("ubd", ubd_setup);
@@ -422,7 +427,7 @@ __uml_help(ubd_setup,
422" use either a ':' or a ',': the first one allows writing things like;\n" 427" use either a ':' or a ',': the first one allows writing things like;\n"
423" ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n" 428" ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n"
424" while with a ',' the shell would not expand the 2nd '~'.\n" 429" while with a ',' the shell would not expand the 2nd '~'.\n"
425" When using only one filename, UML will detect whether to thread it like\n" 430" When using only one filename, UML will detect whether to treat it like\n"
426" a COW file or a backing file. To override this detection, add the 'd'\n" 431" a COW file or a backing file. To override this detection, add the 'd'\n"
427" flag:\n" 432" flag:\n"
428" ubd0d=BackingFile\n" 433" ubd0d=BackingFile\n"
@@ -668,18 +673,19 @@ static int ubd_disk_register(int major, u64 size, int unit,
668 673
669#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9)) 674#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
670 675
671static int ubd_add(int n) 676static int ubd_add(int n, char **error_out)
672{ 677{
673 struct ubd *ubd_dev = &ubd_devs[n]; 678 struct ubd *ubd_dev = &ubd_devs[n];
674 int err; 679 int err = 0;
675 680
676 err = -ENODEV;
677 if(ubd_dev->file == NULL) 681 if(ubd_dev->file == NULL)
678 goto out; 682 goto out;
679 683
680 err = ubd_file_size(ubd_dev, &ubd_dev->size); 684 err = ubd_file_size(ubd_dev, &ubd_dev->size);
681 if(err < 0) 685 if(err < 0){
686 *error_out = "Couldn't determine size of device's file";
682 goto out; 687 goto out;
688 }
683 689
684 ubd_dev->size = ROUND_BLOCK(ubd_dev->size); 690 ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
685 691
@@ -701,28 +707,31 @@ out:
701 return err; 707 return err;
702} 708}
703 709
704static int ubd_config(char *str) 710static int ubd_config(char *str, char **error_out)
705{ 711{
706 int n, ret; 712 int n, ret;
707 713
714 /* This string is possibly broken up and stored, so it's only
715 * freed if ubd_setup_common fails, or if only general options
716 * were set.
717 */
708 str = kstrdup(str, GFP_KERNEL); 718 str = kstrdup(str, GFP_KERNEL);
709 if (str == NULL) { 719 if (str == NULL) {
710 printk(KERN_ERR "ubd_config failed to strdup string\n"); 720 *error_out = "Failed to allocate memory";
711 ret = 1; 721 return -ENOMEM;
712 goto out;
713 } 722 }
714 ret = ubd_setup_common(str, &n); 723
715 if (ret) { 724 ret = ubd_setup_common(str, &n, error_out);
716 ret = -1; 725 if (ret)
717 goto err_free; 726 goto err_free;
718 } 727
719 if (n == -1) { 728 if (n == -1) {
720 ret = 0; 729 ret = 0;
721 goto err_free; 730 goto err_free;
722 } 731 }
723 732
724 mutex_lock(&ubd_lock); 733 mutex_lock(&ubd_lock);
725 ret = ubd_add(n); 734 ret = ubd_add(n, error_out);
726 if (ret) 735 if (ret)
727 ubd_devs[n].file = NULL; 736 ubd_devs[n].file = NULL;
728 mutex_unlock(&ubd_lock); 737 mutex_unlock(&ubd_lock);
@@ -777,7 +786,7 @@ static int ubd_id(char **str, int *start_out, int *end_out)
777 return n; 786 return n;
778} 787}
779 788
780static int ubd_remove(int n) 789static int ubd_remove(int n, char **error_out)
781{ 790{
782 struct ubd *ubd_dev; 791 struct ubd *ubd_dev;
783 int err = -ENODEV; 792 int err = -ENODEV;
@@ -815,7 +824,9 @@ out:
815 return err; 824 return err;
816} 825}
817 826
818/* All these are called by mconsole in process context and without ubd-specific locks. */ 827/* All these are called by mconsole in process context and without
828 * ubd-specific locks.
829 */
819static struct mc_device ubd_mc = { 830static struct mc_device ubd_mc = {
820 .name = "ubd", 831 .name = "ubd",
821 .config = ubd_config, 832 .config = ubd_config,
@@ -851,7 +862,8 @@ static struct platform_driver ubd_driver = {
851 862
852static int __init ubd_init(void) 863static int __init ubd_init(void)
853{ 864{
854 int i; 865 char *error;
866 int i, err;
855 867
856 if (register_blkdev(MAJOR_NR, "ubd")) 868 if (register_blkdev(MAJOR_NR, "ubd"))
857 return -1; 869 return -1;
@@ -870,8 +882,12 @@ static int __init ubd_init(void)
870 return -1; 882 return -1;
871 } 883 }
872 platform_driver_register(&ubd_driver); 884 platform_driver_register(&ubd_driver);
873 for (i = 0; i < MAX_DEV; i++) 885 for (i = 0; i < MAX_DEV; i++){
874 ubd_add(i); 886 err = ubd_add(i, &error);
887 if(err)
888 printk(KERN_ERR "Failed to initialize ubd device %d :"
889 "%s\n", i, error);
890 }
875 return 0; 891 return 0;
876} 892}
877 893
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 9003a343e148..2d9aa7ef4c27 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -30,7 +30,7 @@ struct chan {
30extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, 30extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
31 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
32extern int parse_chan_pair(char *str, struct line *line, int device, 32extern int parse_chan_pair(char *str, struct line *line, int device,
33 const struct chan_opts *opts); 33 const struct chan_opts *opts, char **error_out);
34extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
35extern int write_chan(struct list_head *chans, const char *buf, int len, 35extern int write_chan(struct list_head *chans, const char *buf, int len,
36 int write_irq); 36 int write_irq);
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index b79643eeee08..a2486b4cc9fe 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -76,7 +76,7 @@ struct lines {
76extern void line_close(struct tty_struct *tty, struct file * filp); 76extern void line_close(struct tty_struct *tty, struct file * filp);
77extern int line_open(struct line *lines, struct tty_struct *tty); 77extern int line_open(struct line *lines, struct tty_struct *tty);
78extern int line_setup(struct line *lines, unsigned int sizeof_lines, 78extern int line_setup(struct line *lines, unsigned int sizeof_lines,
79 char *init); 79 char *init, char **error_out);
80extern int line_write(struct tty_struct *tty, const unsigned char *buf, 80extern int line_write(struct tty_struct *tty, const unsigned char *buf,
81 int len); 81 int len);
82extern void line_put_char(struct tty_struct *tty, unsigned char ch); 82extern 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);
102extern void close_lines(struct line *lines, int nlines); 102extern void close_lines(struct line *lines, int nlines);
103 103
104extern int line_config(struct line *lines, unsigned int sizeof_lines, 104extern int line_config(struct line *lines, unsigned int sizeof_lines,
105 char *str, const struct chan_opts *opts); 105 char *str, const struct chan_opts *opts,
106 char **error_out);
106extern int line_id(char **str, int *start_out, int *end_out); 107extern int line_id(char **str, int *start_out, int *end_out);
107extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 108extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
109 char **error_out);
108extern int line_get_config(char *dev, struct line *lines, 110extern int line_get_config(char *dev, struct line *lines,
109 unsigned int sizeof_lines, char *str, 111 unsigned int sizeof_lines, char *str,
110 int size, char **error_out); 112 int size, char **error_out);
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 1ea6d928e1cd..73030e52b2ce 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -18,10 +18,10 @@ struct mconsole_entry {
18struct mc_device { 18struct mc_device {
19 struct list_head list; 19 struct list_head list;
20 char *name; 20 char *name;
21 int (*config)(char *); 21 int (*config)(char *, char **);
22 int (*get_config)(char *, char *, int, char **); 22 int (*get_config)(char *, char *, int, char **);
23 int (*id)(char **, int *, int *); 23 int (*id)(char **, int *, int *);
24 int (*remove)(int); 24 int (*remove)(int, char **);
25}; 25};
26 26
27#define CONFIG_CHUNK(str, size, current, chunk, end) \ 27#define CONFIG_CHUNK(str, size, current, chunk, end) \
@@ -50,14 +50,3 @@ static inline void mconsole_register_dev(struct mc_device *new)
50#endif 50#endif
51 51
52#endif 52#endif
53
54/*
55 * Overrides for Emacs so that we follow Linus's tabbing style.
56 * Emacs will notice this stuff at the end of the file and automatically
57 * adjust the settings for this buffer only. This must remain at the end
58 * of the file.
59 * ---------------------------------------------------------------------------
60 * Local variables:
61 * c-file-style: "linux"
62 * End:
63 */
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 786e4edd86c5..8eba8f7dca68 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)
139 init_proxy(debugger_pid, 0, 0); 139 init_proxy(debugger_pid, 0, 0);
140} 140}
141 141
142int gdb_config(char *str) 142int gdb_config(char *str, char **error_out)
143{ 143{
144 struct gdb_data data; 144 struct gdb_data data;
145 145
@@ -154,7 +154,7 @@ void remove_gdb_cb(void *unused)
154 exit_debugger_cb(NULL); 154 exit_debugger_cb(NULL);
155} 155}
156 156
157int gdb_remove(int unused) 157int gdb_remove(int unused, char **error_out)
158{ 158{
159 initial_thread_cb(remove_gdb_cb, NULL); 159 initial_thread_cb(remove_gdb_cb, NULL);
160 return 0; 160 return 0;
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 68e1bf63cd0a..a1af96ef9ee2 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -8,8 +8,8 @@
8 8
9#ifdef CONFIG_MCONSOLE 9#ifdef CONFIG_MCONSOLE
10 10
11extern int gdb_config(char *str); 11extern int gdb_config(char *str, char **error_out);
12extern int gdb_remove(int n); 12extern int gdb_remove(int n, char **error_out);
13 13
14static struct mc_device gdb_mc = { 14static struct mc_device gdb_mc = {
15 .name = "gdb", 15 .name = "gdb",