diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/drivers/chan_kern.c | 77 | ||||
-rw-r--r-- | arch/um/drivers/line.c | 66 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 40 | ||||
-rw-r--r-- | arch/um/drivers/net_kern.c | 97 | ||||
-rw-r--r-- | arch/um/drivers/ssl.c | 24 | ||||
-rw-r--r-- | arch/um/drivers/stdio_console.c | 22 | ||||
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 132 | ||||
-rw-r--r-- | arch/um/include/chan_kern.h | 2 | ||||
-rw-r--r-- | arch/um/include/line.h | 8 | ||||
-rw-r--r-- | arch/um/include/mconsole_kern.h | 15 | ||||
-rw-r--r-- | arch/um/kernel/tt/gdb.c | 4 | ||||
-rw-r--r-- | arch/um/kernel/tt/gdb_kern.c | 4 |
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. */ | ||
23 | static int my_printf(const char * fmt, ...) | ||
24 | __attribute__ ((format (printf, 1, 2))); | ||
25 | |||
26 | static 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. */ | 23 | static void *not_configged_init(char *str, int device, |
52 | static 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 | |||
57 | static 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) | |||
64 | static int not_configged_open(int input, int output, int primary, void *data, | 31 | static 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 | ||
72 | static void not_configged_close(int fd, void *data) | 39 | static 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 | ||
78 | static int not_configged_read(int fd, char *c_out, void *data) | 45 | static 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 | ||
85 | static int not_configged_write(int fd, const char *buf, int len, void *data) | 52 | static 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 | ||
92 | static int not_configged_console_write(int fd, const char *buf, int len) | 59 | static 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) | |||
99 | static int not_configged_window_size(int fd, void *data, unsigned short *rows, | 66 | static 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 | ||
107 | static void not_configged_free(void *data) | 74 | static 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 | ||
536 | static struct chan *parse_chan(struct line *line, char *str, int device, | 503 | static 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 | ||
584 | int parse_chan_pair(char *str, struct line *line, int device, | 553 | int 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 | ||
552 | static void setup_one_line(struct line *lines, int n, char *init, int init_prio) | 552 | static 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; | ||
572 | out: | 575 | out: |
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 | ||
581 | int line_setup(struct line *lines, unsigned int num, char *init) | 586 | int 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 | ||
616 | int line_config(struct line *lines, unsigned int num, char *str, | 627 | int 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 | ||
642 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | 652 | 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) | |||
685 | return n; | 695 | return n; |
686 | } | 696 | } |
687 | 697 | ||
688 | int line_remove(struct line *lines, unsigned int num, int n) | 698 | int 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); | |||
740 | void lines_init(struct line *lines, int nlines, struct chan_opts *opts) | 750 | void 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; | |||
371 | static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages); | 371 | static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages); |
372 | static int unplug_index = UNPLUGGED_PER_PAGE; | 372 | static int unplug_index = UNPLUGGED_PER_PAGE; |
373 | 373 | ||
374 | static int mem_config(char *str) | 374 | static 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 | ||
473 | static int mem_remove(int n) | 483 | static 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, | |||
542 | void mconsole_config(struct mc_request *req) | 553 | void 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: | |||
159 | static int uml_net_close(struct net_device *dev) | 159 | static 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 | ||
466 | static int eth_parse(char *str, int *index_out, char **str_out) | 466 | static 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 | ||
497 | struct eth_init { | 495 | struct eth_init { |
@@ -581,11 +579,15 @@ static int eth_setup_common(char *str, int index) | |||
581 | static int eth_setup(char *str) | 579 | static 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(ð->list); | 622 | list_del(ð->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 | ||
628 | static int net_config(char *str) | 630 | static 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 | ||
661 | static int net_remove(int n) | 667 | static 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 = { | |||
727 | static int uml_net_init(void) | 733 | static 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 | ||
786 | void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, | 792 | void 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 | ||
838 | int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, | 844 | int 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 | ||
49 | static int ssl_config(char *str); | 49 | static int ssl_config(char *str, char **error_out); |
50 | static int ssl_get_config(char *dev, char *str, int size, char **error_out); | 50 | static int ssl_get_config(char *dev, char *str, int size, char **error_out); |
51 | static int ssl_remove(int n); | 51 | static int ssl_remove(int n, char **error_out); |
52 | 52 | ||
53 | static struct line_driver driver = { | 53 | static 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 | ||
81 | static struct lines lines = LINES_INIT(NR_PORTS); | 81 | static struct lines lines = LINES_INIT(NR_PORTS); |
82 | 82 | ||
83 | static int ssl_config(char *str) | 83 | static 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 | ||
88 | static int ssl_get_config(char *dev, char *str, int size, char **error_out) | 89 | 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) | |||
91 | size, error_out); | 92 | size, error_out); |
92 | } | 93 | } |
93 | 94 | ||
94 | static int ssl_remove(int n) | 95 | static 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 | ||
99 | static int ssl_open(struct tty_struct *tty, struct file *filp) | 101 | static int ssl_open(struct tty_struct *tty, struct file *filp) |
@@ -212,7 +214,15 @@ __uml_exitcall(ssl_exit); | |||
212 | 214 | ||
213 | static int ssl_chan_setup(char *str) | 215 | static 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 | ||
55 | static int con_config(char *str); | 55 | static int con_config(char *str, char **error_out); |
56 | static int con_get_config(char *dev, char *str, int size, char **error_out); | 56 | static int con_get_config(char *dev, char *str, int size, char **error_out); |
57 | static int con_remove(int n); | 57 | static int con_remove(int n, char **con_remove); |
58 | 58 | ||
59 | static struct line_driver driver = { | 59 | static 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 | ||
90 | static int con_config(char *str) | 90 | static 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 | ||
95 | static int con_get_config(char *dev, char *str, int size, char **error_out) | 95 | 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) | |||
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 | ||
100 | static int con_remove(int n) | 100 | static 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 | ||
105 | static int con_open(struct tty_struct *tty, struct file *filp) | 105 | static int con_open(struct tty_struct *tty, struct file *filp) |
@@ -192,7 +192,15 @@ __uml_exitcall(console_exit); | |||
192 | 192 | ||
193 | static int console_chan_setup(char *str) | 193 | static 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 | */ |
289 | static int ubd_setup_common(char *str, int *index_out) | 289 | static 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 | ||
385 | break_loop: | 384 | break_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; |
405 | out: | 404 | out: |
406 | mutex_unlock(&ubd_lock); | 405 | mutex_unlock(&ubd_lock); |
407 | return(err); | 406 | return err; |
408 | } | 407 | } |
409 | 408 | ||
410 | static int ubd_setup(char *str) | 409 | static 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 | ||
671 | static int ubd_add(int n) | 676 | static 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 | ||
704 | static int ubd_config(char *str) | 710 | static 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 | ||
780 | static int ubd_remove(int n) | 789 | static 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 | */ | ||
819 | static struct mc_device ubd_mc = { | 830 | static 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 | ||
852 | static int __init ubd_init(void) | 863 | static 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 { | |||
30 | extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, | 30 | extern 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); |
32 | extern int parse_chan_pair(char *str, struct line *line, int device, | 32 | extern 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); |
34 | extern int open_chan(struct list_head *chans); | 34 | extern int open_chan(struct list_head *chans); |
35 | extern int write_chan(struct list_head *chans, const char *buf, int len, | 35 | extern 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 { | |||
76 | extern void line_close(struct tty_struct *tty, struct file * filp); | 76 | extern void line_close(struct tty_struct *tty, struct file * filp); |
77 | extern int line_open(struct line *lines, struct tty_struct *tty); | 77 | extern int line_open(struct line *lines, struct tty_struct *tty); |
78 | extern int line_setup(struct line *lines, unsigned int sizeof_lines, | 78 | extern int line_setup(struct line *lines, unsigned int sizeof_lines, |
79 | char *init); | 79 | char *init, char **error_out); |
80 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, | 80 | extern int line_write(struct tty_struct *tty, const unsigned char *buf, |
81 | int len); | 81 | int len); |
82 | extern void line_put_char(struct tty_struct *tty, unsigned char ch); | 82 | 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); | |||
102 | extern void close_lines(struct line *lines, int nlines); | 102 | extern void close_lines(struct line *lines, int nlines); |
103 | 103 | ||
104 | extern int line_config(struct line *lines, unsigned int sizeof_lines, | 104 | extern 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); | ||
106 | extern int line_id(char **str, int *start_out, int *end_out); | 107 | extern int line_id(char **str, int *start_out, int *end_out); |
107 | extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); | 108 | extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n, |
109 | char **error_out); | ||
108 | extern int line_get_config(char *dev, struct line *lines, | 110 | extern 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 { | |||
18 | struct mc_device { | 18 | struct 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 | ||
142 | int gdb_config(char *str) | 142 | int 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 | ||
157 | int gdb_remove(int unused) | 157 | int 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 | ||
11 | extern int gdb_config(char *str); | 11 | extern int gdb_config(char *str, char **error_out); |
12 | extern int gdb_remove(int n); | 12 | extern int gdb_remove(int n, char **error_out); |
13 | 13 | ||
14 | static struct mc_device gdb_mc = { | 14 | static struct mc_device gdb_mc = { |
15 | .name = "gdb", | 15 | .name = "gdb", |