aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-01-06 15:59:59 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-06 15:59:59 -0500
commitccf18968b1bbc2fb117190a1984ac2a826dac228 (patch)
tree7bc8fbf5722aecf1e84fa50c31c657864cba1daa /arch/um
parente91c021c487110386a07facd0396e6c3b7cf9c1f (diff)
parentd99cf9d679a520d67f81d805b7cb91c68e1847f0 (diff)
Merge ../torvalds-2.6/
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/chan_kern.c273
-rw-r--r--arch/um/drivers/line.c298
-rw-r--r--arch/um/drivers/mconsole_kern.c232
-rw-r--r--arch/um/drivers/mconsole_user.c12
-rw-r--r--arch/um/drivers/net_kern.c8
-rw-r--r--arch/um/drivers/ssl.c47
-rw-r--r--arch/um/drivers/stdio_console.c33
-rw-r--r--arch/um/drivers/ubd_kern.c15
-rw-r--r--arch/um/include/chan_kern.h25
-rw-r--r--arch/um/include/choose-mode.h3
-rw-r--r--arch/um/include/irq_user.h13
-rw-r--r--arch/um/include/kern.h13
-rw-r--r--arch/um/include/line.h37
-rw-r--r--arch/um/include/mconsole.h8
-rw-r--r--arch/um/include/os.h17
-rw-r--r--arch/um/include/user_util.h1
-rw-r--r--arch/um/kernel/Makefile6
-rw-r--r--arch/um/kernel/irq_user.c48
-rw-r--r--arch/um/kernel/process_kern.c4
-rw-r--r--arch/um/kernel/sigio_user.c2
-rw-r--r--arch/um/kernel/um_arch.c4
-rw-r--r--arch/um/kernel/umid.c323
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/aio.c467
-rw-r--r--arch/um/os-Linux/umid.c335
25 files changed, 1178 insertions, 1050 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 5b58fad45290..cd13b91b9ff6 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{ 58{
59 my_puts("Using a channel type which is configured out of " 59 my_puts("Using a channel type which is configured out of "
60 "UML\n"); 60 "UML\n");
61 return(NULL); 61 return NULL;
62} 62}
63 63
64static int not_configged_open(int input, int output, int primary, void *data, 64static int not_configged_open(int input, int output, int primary, void *data,
@@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data,
66{ 66{
67 my_puts("Using a channel type which is configured out of " 67 my_puts("Using a channel type which is configured out of "
68 "UML\n"); 68 "UML\n");
69 return(-ENODEV); 69 return -ENODEV;
70} 70}
71 71
72static void not_configged_close(int fd, void *data) 72static void not_configged_close(int fd, void *data)
@@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data)
79{ 79{
80 my_puts("Using a channel type which is configured out of " 80 my_puts("Using a channel type which is configured out of "
81 "UML\n"); 81 "UML\n");
82 return(-EIO); 82 return -EIO;
83} 83}
84 84
85static int not_configged_write(int fd, const char *buf, int len, void *data) 85static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 86{
87 my_puts("Using a channel type which is configured out of " 87 my_puts("Using a channel type which is configured out of "
88 "UML\n"); 88 "UML\n");
89 return(-EIO); 89 return -EIO;
90} 90}
91 91
92static int not_configged_console_write(int fd, const char *buf, int len) 92static int not_configged_console_write(int fd, const char *buf, int len)
93{ 93{
94 my_puts("Using a channel type which is configured out of " 94 my_puts("Using a channel type which is configured out of "
95 "UML\n"); 95 "UML\n");
96 return(-EIO); 96 return -EIO;
97} 97}
98 98
99static int not_configged_window_size(int fd, void *data, unsigned short *rows, 99static int not_configged_window_size(int fd, void *data, unsigned short *rows,
@@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows,
101{ 101{
102 my_puts("Using a channel type which is configured out of " 102 my_puts("Using a channel type which is configured out of "
103 "UML\n"); 103 "UML\n");
104 return(-ENODEV); 104 return -ENODEV;
105} 105}
106 106
107static void not_configged_free(void *data) 107static void not_configged_free(void *data)
@@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused)
135 n = os_read_file(fd, c_out, sizeof(*c_out)); 135 n = os_read_file(fd, c_out, sizeof(*c_out));
136 136
137 if(n == -EAGAIN) 137 if(n == -EAGAIN)
138 return(0); 138 return 0;
139 else if(n == 0) 139 else if(n == 0)
140 return(-EIO); 140 return -EIO;
141 return(n); 141 return n;
142} 142}
143 143
144/* XXX Trivial wrapper around os_write_file */ 144/* XXX Trivial wrapper around os_write_file */
145 145
146int generic_write(int fd, const char *buf, int n, void *unused) 146int generic_write(int fd, const char *buf, int n, void *unused)
147{ 147{
148 return(os_write_file(fd, buf, n)); 148 return os_write_file(fd, buf, n);
149} 149}
150 150
151int generic_window_size(int fd, void *unused, unsigned short *rows_out, 151int generic_window_size(int fd, void *unused, unsigned short *rows_out,
@@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out,
156 156
157 ret = os_window_size(fd, &rows, &cols); 157 ret = os_window_size(fd, &rows, &cols);
158 if(ret < 0) 158 if(ret < 0)
159 return(ret); 159 return ret;
160 160
161 ret = ((*rows_out != rows) || (*cols_out != cols)); 161 ret = ((*rows_out != rows) || (*cols_out != cols));
162 162
163 *rows_out = rows; 163 *rows_out = rows;
164 *cols_out = cols; 164 *cols_out = cols;
165 165
166 return(ret); 166 return ret;
167} 167}
168 168
169void generic_free(void *data) 169void generic_free(void *data)
@@ -186,25 +186,29 @@ static void tty_receive_char(struct tty_struct *tty, char ch)
186 } 186 }
187 } 187 }
188 188
189 if((tty->flip.flag_buf_ptr == NULL) || 189 if((tty->flip.flag_buf_ptr == NULL) ||
190 (tty->flip.char_buf_ptr == NULL)) 190 (tty->flip.char_buf_ptr == NULL))
191 return; 191 return;
192 tty_insert_flip_char(tty, ch, TTY_NORMAL); 192 tty_insert_flip_char(tty, ch, TTY_NORMAL);
193} 193}
194 194
195static int open_one_chan(struct chan *chan, int input, int output, int primary) 195static int open_one_chan(struct chan *chan)
196{ 196{
197 int fd; 197 int fd;
198 198
199 if(chan->opened) return(0); 199 if(chan->opened)
200 if(chan->ops->open == NULL) fd = 0; 200 return 0;
201 else fd = (*chan->ops->open)(input, output, primary, chan->data, 201
202 &chan->dev); 202 if(chan->ops->open == NULL)
203 if(fd < 0) return(fd); 203 fd = 0;
204 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
205 chan->data, &chan->dev);
206 if(fd < 0)
207 return fd;
204 chan->fd = fd; 208 chan->fd = fd;
205 209
206 chan->opened = 1; 210 chan->opened = 1;
207 return(0); 211 return 0;
208} 212}
209 213
210int open_chan(struct list_head *chans) 214int open_chan(struct list_head *chans)
@@ -215,11 +219,11 @@ int open_chan(struct list_head *chans)
215 219
216 list_for_each(ele, chans){ 220 list_for_each(ele, chans){
217 chan = list_entry(ele, struct chan, list); 221 chan = list_entry(ele, struct chan, list);
218 ret = open_one_chan(chan, chan->input, chan->output, 222 ret = open_one_chan(chan);
219 chan->primary); 223 if(chan->primary)
220 if(chan->primary) err = ret; 224 err = ret;
221 } 225 }
222 return(err); 226 return err;
223} 227}
224 228
225void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 229void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
@@ -236,20 +240,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
236 } 240 }
237} 241}
238 242
239void enable_chan(struct list_head *chans, struct tty_struct *tty) 243void enable_chan(struct line *line)
240{ 244{
241 struct list_head *ele; 245 struct list_head *ele;
242 struct chan *chan; 246 struct chan *chan;
243 247
244 list_for_each(ele, chans){ 248 list_for_each(ele, &line->chan_list){
245 chan = list_entry(ele, struct chan, list); 249 chan = list_entry(ele, struct chan, list);
246 if(!chan->opened) continue; 250 if(open_one_chan(chan))
251 continue;
252
253 if(chan->enabled)
254 continue;
255 line_setup_irq(chan->fd, chan->input, chan->output, line,
256 chan);
257 chan->enabled = 1;
258 }
259}
260
261static LIST_HEAD(irqs_to_free);
262
263void free_irqs(void)
264{
265 struct chan *chan;
266
267 while(!list_empty(&irqs_to_free)){
268 chan = list_entry(irqs_to_free.next, struct chan, free_list);
269 list_del(&chan->free_list);
247 270
248 line_setup_irq(chan->fd, chan->input, chan->output, tty); 271 if(chan->input)
272 free_irq(chan->line->driver->read_irq, chan);
273 if(chan->output)
274 free_irq(chan->line->driver->write_irq, chan);
275 chan->enabled = 0;
276 }
277}
278
279static void close_one_chan(struct chan *chan, int delay_free_irq)
280{
281 if(!chan->opened)
282 return;
283
284 if(delay_free_irq){
285 list_add(&chan->free_list, &irqs_to_free);
249 } 286 }
287 else {
288 if(chan->input)
289 free_irq(chan->line->driver->read_irq, chan);
290 if(chan->output)
291 free_irq(chan->line->driver->write_irq, chan);
292 chan->enabled = 0;
293 }
294 if(chan->ops->close != NULL)
295 (*chan->ops->close)(chan->fd, chan->data);
296
297 chan->opened = 0;
298 chan->fd = -1;
250} 299}
251 300
252void close_chan(struct list_head *chans) 301void close_chan(struct list_head *chans, int delay_free_irq)
253{ 302{
254 struct chan *chan; 303 struct chan *chan;
255 304
@@ -259,15 +308,37 @@ void close_chan(struct list_head *chans)
259 * so it must be the last closed. 308 * so it must be the last closed.
260 */ 309 */
261 list_for_each_entry_reverse(chan, chans, list) { 310 list_for_each_entry_reverse(chan, chans, list) {
262 if(!chan->opened) continue; 311 close_one_chan(chan, delay_free_irq);
263 if(chan->ops->close != NULL) 312 }
264 (*chan->ops->close)(chan->fd, chan->data); 313}
265 chan->opened = 0; 314
266 chan->fd = -1; 315void deactivate_chan(struct list_head *chans, int irq)
316{
317 struct list_head *ele;
318
319 struct chan *chan;
320 list_for_each(ele, chans) {
321 chan = list_entry(ele, struct chan, list);
322
323 if(chan->enabled && chan->input)
324 deactivate_fd(chan->fd, irq);
325 }
326}
327
328void reactivate_chan(struct list_head *chans, int irq)
329{
330 struct list_head *ele;
331 struct chan *chan;
332
333 list_for_each(ele, chans) {
334 chan = list_entry(ele, struct chan, list);
335
336 if(chan->enabled && chan->input)
337 reactivate_fd(chan->fd, irq);
267 } 338 }
268} 339}
269 340
270int write_chan(struct list_head *chans, const char *buf, int len, 341int write_chan(struct list_head *chans, const char *buf, int len,
271 int write_irq) 342 int write_irq)
272{ 343{
273 struct list_head *ele; 344 struct list_head *ele;
@@ -285,7 +356,7 @@ int write_chan(struct list_head *chans, const char *buf, int len,
285 reactivate_fd(chan->fd, write_irq); 356 reactivate_fd(chan->fd, write_irq);
286 } 357 }
287 } 358 }
288 return(ret); 359 return ret;
289} 360}
290 361
291int console_write_chan(struct list_head *chans, const char *buf, int len) 362int console_write_chan(struct list_head *chans, const char *buf, int len)
@@ -301,19 +372,18 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
301 n = chan->ops->console_write(chan->fd, buf, len); 372 n = chan->ops->console_write(chan->fd, buf, len);
302 if(chan->primary) ret = n; 373 if(chan->primary) ret = n;
303 } 374 }
304 return(ret); 375 return ret;
305} 376}
306 377
307int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) 378int console_open_chan(struct line *line, struct console *co,
379 struct chan_opts *opts)
308{ 380{
309 if (!list_empty(&line->chan_list)) 381 int err;
310 return 0; 382
383 err = open_chan(&line->chan_list);
384 if(err)
385 return err;
311 386
312 if (0 != parse_chan_pair(line->init_str, &line->chan_list,
313 line->init_pri, co->index, opts))
314 return -1;
315 if (0 != open_chan(&line->chan_list))
316 return -1;
317 printk("Console initialized on /dev/%s%d\n",co->name,co->index); 387 printk("Console initialized on /dev/%s%d\n",co->name,co->index);
318 return 0; 388 return 0;
319} 389}
@@ -327,32 +397,36 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
327 list_for_each(ele, chans){ 397 list_for_each(ele, chans){
328 chan = list_entry(ele, struct chan, list); 398 chan = list_entry(ele, struct chan, list);
329 if(chan->primary){ 399 if(chan->primary){
330 if(chan->ops->window_size == NULL) return(0); 400 if(chan->ops->window_size == NULL)
331 return(chan->ops->window_size(chan->fd, chan->data, 401 return 0;
332 rows_out, cols_out)); 402 return chan->ops->window_size(chan->fd, chan->data,
403 rows_out, cols_out);
333 } 404 }
334 } 405 }
335 return(0); 406 return 0;
336} 407}
337 408
338void free_one_chan(struct chan *chan) 409void free_one_chan(struct chan *chan, int delay_free_irq)
339{ 410{
340 list_del(&chan->list); 411 list_del(&chan->list);
412
413 close_one_chan(chan, delay_free_irq);
414
341 if(chan->ops->free != NULL) 415 if(chan->ops->free != NULL)
342 (*chan->ops->free)(chan->data); 416 (*chan->ops->free)(chan->data);
343 free_irq_by_fd(chan->fd); 417
344 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); 418 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
345 kfree(chan); 419 kfree(chan);
346} 420}
347 421
348void free_chan(struct list_head *chans) 422void free_chan(struct list_head *chans, int delay_free_irq)
349{ 423{
350 struct list_head *ele, *next; 424 struct list_head *ele, *next;
351 struct chan *chan; 425 struct chan *chan;
352 426
353 list_for_each_safe(ele, next, chans){ 427 list_for_each_safe(ele, next, chans){
354 chan = list_entry(ele, struct chan, list); 428 chan = list_entry(ele, struct chan, list);
355 free_one_chan(chan); 429 free_one_chan(chan, delay_free_irq);
356 } 430 }
357} 431}
358 432
@@ -363,23 +437,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
363 437
364 if(chan == NULL){ 438 if(chan == NULL){
365 CONFIG_CHUNK(str, size, n, "none", 1); 439 CONFIG_CHUNK(str, size, n, "none", 1);
366 return(n); 440 return n;
367 } 441 }
368 442
369 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 443 CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
370 444
371 if(chan->dev == NULL){ 445 if(chan->dev == NULL){
372 CONFIG_CHUNK(str, size, n, "", 1); 446 CONFIG_CHUNK(str, size, n, "", 1);
373 return(n); 447 return n;
374 } 448 }
375 449
376 CONFIG_CHUNK(str, size, n, ":", 0); 450 CONFIG_CHUNK(str, size, n, ":", 0);
377 CONFIG_CHUNK(str, size, n, chan->dev, 0); 451 CONFIG_CHUNK(str, size, n, chan->dev, 0);
378 452
379 return(n); 453 return n;
380} 454}
381 455
382static int chan_pair_config_string(struct chan *in, struct chan *out, 456static int chan_pair_config_string(struct chan *in, struct chan *out,
383 char *str, int size, char **error_out) 457 char *str, int size, char **error_out)
384{ 458{
385 int n; 459 int n;
@@ -390,7 +464,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
390 464
391 if(in == out){ 465 if(in == out){
392 CONFIG_CHUNK(str, size, n, "", 1); 466 CONFIG_CHUNK(str, size, n, "", 1);
393 return(n); 467 return n;
394 } 468 }
395 469
396 CONFIG_CHUNK(str, size, n, ",", 1); 470 CONFIG_CHUNK(str, size, n, ",", 1);
@@ -399,10 +473,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
399 size -= n; 473 size -= n;
400 CONFIG_CHUNK(str, size, n, "", 1); 474 CONFIG_CHUNK(str, size, n, "", 1);
401 475
402 return(n); 476 return n;
403} 477}
404 478
405int chan_config_string(struct list_head *chans, char *str, int size, 479int chan_config_string(struct list_head *chans, char *str, int size,
406 char **error_out) 480 char **error_out)
407{ 481{
408 struct list_head *ele; 482 struct list_head *ele;
@@ -418,7 +492,7 @@ int chan_config_string(struct list_head *chans, char *str, int size,
418 out = chan; 492 out = chan;
419 } 493 }
420 494
421 return(chan_pair_config_string(in, out, str, size, error_out)); 495 return chan_pair_config_string(in, out, str, size, error_out);
422} 496}
423 497
424struct chan_type { 498struct chan_type {
@@ -462,7 +536,7 @@ struct chan_type chan_table[] = {
462#endif 536#endif
463}; 537};
464 538
465static struct chan *parse_chan(char *str, int pri, int device, 539static struct chan *parse_chan(struct line *line, char *str, int device,
466 struct chan_opts *opts) 540 struct chan_opts *opts)
467{ 541{
468 struct chan_type *entry; 542 struct chan_type *entry;
@@ -484,36 +558,42 @@ static struct chan *parse_chan(char *str, int pri, int device,
484 if(ops == NULL){ 558 if(ops == NULL){
485 my_printf("parse_chan couldn't parse \"%s\"\n", 559 my_printf("parse_chan couldn't parse \"%s\"\n",
486 str); 560 str);
487 return(NULL); 561 return NULL;
488 } 562 }
489 if(ops->init == NULL) return(NULL); 563 if(ops->init == NULL)
564 return NULL;
490 data = (*ops->init)(str, device, opts); 565 data = (*ops->init)(str, device, opts);
491 if(data == NULL) return(NULL); 566 if(data == NULL)
567 return NULL;
492 568
493 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 569 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
494 if(chan == NULL) return(NULL); 570 if(chan == NULL)
571 return NULL;
495 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 572 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
573 .free_list =
574 LIST_HEAD_INIT(chan->free_list),
575 .line = line,
496 .primary = 1, 576 .primary = 1,
497 .input = 0, 577 .input = 0,
498 .output = 0, 578 .output = 0,
499 .opened = 0, 579 .opened = 0,
580 .enabled = 0,
500 .fd = -1, 581 .fd = -1,
501 .pri = pri,
502 .ops = ops, 582 .ops = ops,
503 .data = data }); 583 .data = data });
504 return(chan); 584 return chan;
505} 585}
506 586
507int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, 587int parse_chan_pair(char *str, struct line *line, int device,
508 struct chan_opts *opts) 588 struct chan_opts *opts)
509{ 589{
590 struct list_head *chans = &line->chan_list;
510 struct chan *new, *chan; 591 struct chan *new, *chan;
511 char *in, *out; 592 char *in, *out;
512 593
513 if(!list_empty(chans)){ 594 if(!list_empty(chans)){
514 chan = list_entry(chans->next, struct chan, list); 595 chan = list_entry(chans->next, struct chan, list);
515 if(chan->pri >= pri) return(0); 596 free_chan(chans, 0);
516 free_chan(chans);
517 INIT_LIST_HEAD(chans); 597 INIT_LIST_HEAD(chans);
518 } 598 }
519 599
@@ -522,24 +602,30 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
522 in = str; 602 in = str;
523 *out = '\0'; 603 *out = '\0';
524 out++; 604 out++;
525 new = parse_chan(in, pri, device, opts); 605 new = parse_chan(line, in, device, opts);
526 if(new == NULL) return(-1); 606 if(new == NULL)
607 return -1;
608
527 new->input = 1; 609 new->input = 1;
528 list_add(&new->list, chans); 610 list_add(&new->list, chans);
529 611
530 new = parse_chan(out, pri, device, opts); 612 new = parse_chan(line, out, device, opts);
531 if(new == NULL) return(-1); 613 if(new == NULL)
614 return -1;
615
532 list_add(&new->list, chans); 616 list_add(&new->list, chans);
533 new->output = 1; 617 new->output = 1;
534 } 618 }
535 else { 619 else {
536 new = parse_chan(str, pri, device, opts); 620 new = parse_chan(line, str, device, opts);
537 if(new == NULL) return(-1); 621 if(new == NULL)
622 return -1;
623
538 list_add(&new->list, chans); 624 list_add(&new->list, chans);
539 new->input = 1; 625 new->input = 1;
540 new->output = 1; 626 new->output = 1;
541 } 627 }
542 return(0); 628 return 0;
543} 629}
544 630
545int chan_out_fd(struct list_head *chans) 631int chan_out_fd(struct list_head *chans)
@@ -550,9 +636,9 @@ int chan_out_fd(struct list_head *chans)
550 list_for_each(ele, chans){ 636 list_for_each(ele, chans){
551 chan = list_entry(ele, struct chan, list); 637 chan = list_entry(ele, struct chan, list);
552 if(chan->primary && chan->output) 638 if(chan->primary && chan->output)
553 return(chan->fd); 639 return chan->fd;
554 } 640 }
555 return(-1); 641 return -1;
556} 642}
557 643
558void chan_interrupt(struct list_head *chans, struct work_struct *task, 644void chan_interrupt(struct list_head *chans, struct work_struct *task,
@@ -567,9 +653,9 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
567 chan = list_entry(ele, struct chan, list); 653 chan = list_entry(ele, struct chan, list);
568 if(!chan->input || (chan->ops->read == NULL)) continue; 654 if(!chan->input || (chan->ops->read == NULL)) continue;
569 do { 655 do {
570 if((tty != NULL) && 656 if((tty != NULL) &&
571 (tty->flip.count >= TTY_FLIPBUF_SIZE)){ 657 (tty->flip.count >= TTY_FLIPBUF_SIZE)){
572 schedule_work(task); 658 schedule_delayed_work(task, 1);
573 goto out; 659 goto out;
574 } 660 }
575 err = chan->ops->read(chan->fd, &c, chan->data); 661 err = chan->ops->read(chan->fd, &c, chan->data);
@@ -582,29 +668,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
582 if(chan->primary){ 668 if(chan->primary){
583 if(tty != NULL) 669 if(tty != NULL)
584 tty_hangup(tty); 670 tty_hangup(tty);
585 line_disable(tty, irq); 671 close_chan(chans, 1);
586 close_chan(chans);
587 free_chan(chans);
588 return; 672 return;
589 } 673 }
590 else { 674 else close_one_chan(chan, 1);
591 if(chan->ops->close != NULL)
592 chan->ops->close(chan->fd, chan->data);
593 free_one_chan(chan);
594 }
595 } 675 }
596 } 676 }
597 out: 677 out:
598 if(tty) tty_flip_buffer_push(tty); 678 if(tty) tty_flip_buffer_push(tty);
599} 679}
600
601/*
602 * Overrides for Emacs so that we follow Linus's tabbing style.
603 * Emacs will notice this stuff at the end of the file and automatically
604 * adjust the settings for this buffer only. This must remain at the end
605 * of the file.
606 * ---------------------------------------------------------------------------
607 * Local variables:
608 * c-file-style: "linux"
609 * End:
610 */
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index e0fdffa2d542..46ceb25a9959 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,8 +23,9 @@
23 23
24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
25{ 25{
26 struct tty_struct *tty = data; 26 struct chan *chan = data;
27 struct line *line = tty->driver_data; 27 struct line *line = chan->line;
28 struct tty_struct *tty = line->tty;
28 29
29 if (line) 30 if (line)
30 chan_interrupt(&line->chan_list, &line->task, tty, irq); 31 chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,11 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
33 34
34static void line_timer_cb(void *arg) 35static void line_timer_cb(void *arg)
35{ 36{
36 struct tty_struct *tty = arg; 37 struct line *line = arg;
37 struct line *line = tty->driver_data;
38 38
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 if(!line->throttled)
40 chan_interrupt(&line->chan_list, &line->task, line->tty,
41 line->driver->read_irq);
40} 42}
41 43
42/* Returns the free space inside the ring buffer of this line. 44/* Returns the free space inside the ring buffer of this line.
@@ -124,7 +126,8 @@ static int buffer_data(struct line *line, const char *buf, int len)
124 if (len < end){ 126 if (len < end){
125 memcpy(line->tail, buf, len); 127 memcpy(line->tail, buf, len);
126 line->tail += len; 128 line->tail += len;
127 } else { 129 }
130 else {
128 /* The circular buffer is wrapping */ 131 /* The circular buffer is wrapping */
129 memcpy(line->tail, buf, end); 132 memcpy(line->tail, buf, end);
130 buf += end; 133 buf += end;
@@ -170,7 +173,7 @@ static int flush_buffer(struct line *line)
170 } 173 }
171 174
172 count = line->tail - line->head; 175 count = line->tail - line->head;
173 n = write_chan(&line->chan_list, line->head, count, 176 n = write_chan(&line->chan_list, line->head, count,
174 line->driver->write_irq); 177 line->driver->write_irq);
175 178
176 if(n < 0) 179 if(n < 0)
@@ -227,7 +230,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
227 if (err <= 0 && (err != -EAGAIN || !ret)) 230 if (err <= 0 && (err != -EAGAIN || !ret))
228 ret = err; 231 ret = err;
229 } else { 232 } else {
230 n = write_chan(&line->chan_list, buf, len, 233 n = write_chan(&line->chan_list, buf, len,
231 line->driver->write_irq); 234 line->driver->write_irq);
232 if (n < 0) { 235 if (n < 0) {
233 ret = n; 236 ret = n;
@@ -338,11 +341,36 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
338 return ret; 341 return ret;
339} 342}
340 343
344void line_throttle(struct tty_struct *tty)
345{
346 struct line *line = tty->driver_data;
347
348 deactivate_chan(&line->chan_list, line->driver->read_irq);
349 line->throttled = 1;
350}
351
352void line_unthrottle(struct tty_struct *tty)
353{
354 struct line *line = tty->driver_data;
355
356 line->throttled = 0;
357 chan_interrupt(&line->chan_list, &line->task, tty,
358 line->driver->read_irq);
359
360 /* Maybe there is enough stuff pending that calling the interrupt
361 * throttles us again. In this case, line->throttled will be 1
362 * again and we shouldn't turn the interrupt back on.
363 */
364 if(!line->throttled)
365 reactivate_chan(&line->chan_list, line->driver->read_irq);
366}
367
341static irqreturn_t line_write_interrupt(int irq, void *data, 368static irqreturn_t line_write_interrupt(int irq, void *data,
342 struct pt_regs *unused) 369 struct pt_regs *unused)
343{ 370{
344 struct tty_struct *tty = data; 371 struct chan *chan = data;
345 struct line *line = tty->driver_data; 372 struct line *line = chan->line;
373 struct tty_struct *tty = line->tty;
346 int err; 374 int err;
347 375
348 /* Interrupts are enabled here because we registered the interrupt with 376 /* Interrupts are enabled here because we registered the interrupt with
@@ -364,7 +392,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
364 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 392 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
365 (tty->ldisc.write_wakeup != NULL)) 393 (tty->ldisc.write_wakeup != NULL))
366 (tty->ldisc.write_wakeup)(tty); 394 (tty->ldisc.write_wakeup)(tty);
367 395
368 /* BLOCKING mode 396 /* BLOCKING mode
369 * In blocking mode, everything sleeps on tty->write_wait. 397 * In blocking mode, everything sleeps on tty->write_wait.
370 * Sleeping in the console driver would break non-blocking 398 * Sleeping in the console driver would break non-blocking
@@ -376,53 +404,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
376 return IRQ_HANDLED; 404 return IRQ_HANDLED;
377} 405}
378 406
379int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 407int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
380{ 408{
381 struct line *line = tty->driver_data;
382 struct line_driver *driver = line->driver; 409 struct line_driver *driver = line->driver;
383 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 410 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
384 411
385 if (input) 412 if (input)
386 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 413 err = um_request_irq(driver->read_irq, fd, IRQ_READ,
387 line_interrupt, flags, 414 line_interrupt, flags,
388 driver->read_irq_name, tty); 415 driver->read_irq_name, data);
389 if (err) 416 if (err)
390 return err; 417 return err;
391 if (output) 418 if (output)
392 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 419 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
393 line_write_interrupt, flags, 420 line_write_interrupt, flags,
394 driver->write_irq_name, tty); 421 driver->write_irq_name, data);
395 line->have_irq = 1; 422 line->have_irq = 1;
396 return err; 423 return err;
397} 424}
398 425
399void line_disable(struct tty_struct *tty, int current_irq) 426int line_open(struct line *lines, struct tty_struct *tty)
400{
401 struct line *line = tty->driver_data;
402
403 if(!line->have_irq)
404 return;
405
406 if(line->driver->read_irq == current_irq)
407 free_irq_later(line->driver->read_irq, tty);
408 else {
409 free_irq(line->driver->read_irq, tty);
410 }
411
412 if(line->driver->write_irq == current_irq)
413 free_irq_later(line->driver->write_irq, tty);
414 else {
415 free_irq(line->driver->write_irq, tty);
416 }
417
418 line->have_irq = 0;
419}
420
421int line_open(struct line *lines, struct tty_struct *tty,
422 struct chan_opts *opts)
423{ 427{
424 struct line *line; 428 struct line *line;
425 int err = 0; 429 int err = -ENODEV;
426 430
427 line = &lines[tty->index]; 431 line = &lines[tty->index];
428 tty->driver_data = line; 432 tty->driver_data = line;
@@ -430,31 +434,29 @@ int line_open(struct line *lines, struct tty_struct *tty,
430 /* The IRQ which takes this lock is not yet enabled and won't be run 434 /* The IRQ which takes this lock is not yet enabled and won't be run
431 * before the end, so we don't need to use spin_lock_irq.*/ 435 * before the end, so we don't need to use spin_lock_irq.*/
432 spin_lock(&line->lock); 436 spin_lock(&line->lock);
433 if (tty->count == 1) { 437
434 if (!line->valid) { 438 tty->driver_data = line;
435 err = -ENODEV; 439 line->tty = tty;
436 goto out; 440 if(!line->valid)
437 } 441 goto out;
438 if (list_empty(&line->chan_list)) { 442
439 err = parse_chan_pair(line->init_str, &line->chan_list, 443 if(tty->count == 1){
440 line->init_pri, tty->index, opts); 444 /* Here the device is opened, if necessary, and interrupt
441 if(err) goto out; 445 * is registered.
442 err = open_chan(&line->chan_list); 446 */
443 if(err) goto out; 447 enable_chan(line);
448 INIT_WORK(&line->task, line_timer_cb, line);
449
450 if(!line->sigio){
451 chan_enable_winch(&line->chan_list, tty);
452 line->sigio = 1;
444 } 453 }
445 /* Here the interrupt is registered.*/
446 enable_chan(&line->chan_list, tty);
447 INIT_WORK(&line->task, line_timer_cb, tty);
448 }
449 454
450 if(!line->sigio){ 455 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
451 chan_enable_winch(&line->chan_list, tty); 456 &tty->winsize.ws_col);
452 line->sigio = 1;
453 } 457 }
454 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
455 &tty->winsize.ws_col);
456 line->count++;
457 458
459 err = 0;
458out: 460out:
459 spin_unlock(&line->lock); 461 spin_unlock(&line->lock);
460 return err; 462 return err;
@@ -474,15 +476,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
474 /* We ignore the error anyway! */ 476 /* We ignore the error anyway! */
475 flush_buffer(line); 477 flush_buffer(line);
476 478
477 line->count--; 479 if(tty->count == 1){
478 if (tty->count == 1) { 480 line->tty = NULL;
479 line_disable(tty, -1);
480 tty->driver_data = NULL; 481 tty->driver_data = NULL;
481 }
482 482
483 if((line->count == 0) && line->sigio){ 483 if(line->sigio){
484 unregister_winch(tty); 484 unregister_winch(tty);
485 line->sigio = 0; 485 line->sigio = 0;
486 }
486 } 487 }
487 488
488 spin_unlock_irq(&line->lock); 489 spin_unlock_irq(&line->lock);
@@ -493,17 +494,15 @@ void close_lines(struct line *lines, int nlines)
493 int i; 494 int i;
494 495
495 for(i = 0; i < nlines; i++) 496 for(i = 0; i < nlines; i++)
496 close_chan(&lines[i].chan_list); 497 close_chan(&lines[i].chan_list, 0);
497} 498}
498 499
499/* Common setup code for both startup command line and mconsole initialization. 500/* Common setup code for both startup command line and mconsole initialization.
500 * @lines contains the the array (of size @num) to modify; 501 * @lines contains the the array (of size @num) to modify;
501 * @init is the setup string; 502 * @init is the setup string;
502 * @all_allowed is a boolean saying if we can setup the whole @lines 503 */
503 * at once. For instance, it will be usually true for startup init. (where we
504 * can use con=xterm) and false for mconsole.*/
505 504
506int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed) 505int line_setup(struct line *lines, unsigned int num, char *init)
507{ 506{
508 int i, n; 507 int i, n;
509 char *end; 508 char *end;
@@ -512,10 +511,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
512 /* We said con=/ssl= instead of con#=, so we are configuring all 511 /* We said con=/ssl= instead of con#=, so we are configuring all
513 * consoles at once.*/ 512 * consoles at once.*/
514 n = -1; 513 n = -1;
515 } else { 514 }
515 else {
516 n = simple_strtoul(init, &end, 0); 516 n = simple_strtoul(init, &end, 0);
517 if(*end != '='){ 517 if(*end != '='){
518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
519 init); 519 init);
520 return 0; 520 return 0;
521 } 521 }
@@ -527,8 +527,9 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
528 n, num - 1); 528 n, num - 1);
529 return 0; 529 return 0;
530 } else if (n >= 0){ 530 }
531 if (lines[n].count > 0) { 531 else if (n >= 0){
532 if (lines[n].tty != NULL) {
532 printk("line_setup - device %d is open\n", n); 533 printk("line_setup - device %d is open\n", n);
533 return 0; 534 return 0;
534 } 535 }
@@ -539,13 +540,10 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
539 else { 540 else {
540 lines[n].init_str = init; 541 lines[n].init_str = init;
541 lines[n].valid = 1; 542 lines[n].valid = 1;
542 } 543 }
543 } 544 }
544 } else if(!all_allowed){ 545 }
545 printk("line_setup - can't configure all devices from " 546 else {
546 "mconsole\n");
547 return 0;
548 } else {
549 for(i = 0; i < num; i++){ 547 for(i = 0; i < num; i++){
550 if(lines[i].init_pri <= INIT_ALL){ 548 if(lines[i].init_pri <= INIT_ALL){
551 lines[i].init_pri = INIT_ALL; 549 lines[i].init_pri = INIT_ALL;
@@ -557,18 +555,33 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
557 } 555 }
558 } 556 }
559 } 557 }
560 return 1; 558 return n == -1 ? num : n;
561} 559}
562 560
563int line_config(struct line *lines, unsigned int num, char *str) 561int line_config(struct line *lines, unsigned int num, char *str,
562 struct chan_opts *opts)
564{ 563{
565 char *new = uml_strdup(str); 564 struct line *line;
565 char *new;
566 int n;
566 567
568 if(*str == '='){
569 printk("line_config - can't configure all devices from "
570 "mconsole\n");
571 return 1;
572 }
573
574 new = kstrdup(str, GFP_KERNEL);
567 if(new == NULL){ 575 if(new == NULL){
568 printk("line_config - uml_strdup failed\n"); 576 printk("line_config - kstrdup failed\n");
569 return -ENOMEM; 577 return 1;
570 } 578 }
571 return !line_setup(lines, num, new, 0); 579 n = line_setup(lines, num, new);
580 if(n < 0)
581 return 1;
582
583 line = &lines[n];
584 return parse_chan_pair(line->init_str, line, n, opts);
572} 585}
573 586
574int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 587int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -594,7 +607,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
594 spin_lock(&line->lock); 607 spin_lock(&line->lock);
595 if(!line->valid) 608 if(!line->valid)
596 CONFIG_CHUNK(str, size, n, "none", 1); 609 CONFIG_CHUNK(str, size, n, "none", 1);
597 else if(line->count == 0) 610 else if(line->tty == NULL)
598 CONFIG_CHUNK(str, size, n, line->init_str, 1); 611 CONFIG_CHUNK(str, size, n, line->init_str, 1);
599 else n = chan_config_string(&line->chan_list, str, size, error_out); 612 else n = chan_config_string(&line->chan_list, str, size, error_out);
600 spin_unlock(&line->lock); 613 spin_unlock(&line->lock);
@@ -619,14 +632,18 @@ int line_id(char **str, int *start_out, int *end_out)
619 632
620int line_remove(struct line *lines, unsigned int num, int n) 633int line_remove(struct line *lines, unsigned int num, int n)
621{ 634{
635 int err;
622 char config[sizeof("conxxxx=none\0")]; 636 char config[sizeof("conxxxx=none\0")];
623 637
624 sprintf(config, "%d=none", n); 638 sprintf(config, "%d=none", n);
625 return !line_setup(lines, num, config, 0); 639 err = line_setup(lines, num, config);
640 if(err >= 0)
641 err = 0;
642 return err;
626} 643}
627 644
628struct tty_driver *line_register_devfs(struct lines *set, 645struct tty_driver *line_register_devfs(struct lines *set,
629 struct line_driver *line_driver, 646 struct line_driver *line_driver,
630 struct tty_operations *ops, struct line *lines, 647 struct tty_operations *ops, struct line *lines,
631 int nlines) 648 int nlines)
632{ 649{
@@ -655,7 +672,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
655 } 672 }
656 673
657 for(i = 0; i < nlines; i++){ 674 for(i = 0; i < nlines; i++){
658 if(!lines[i].valid) 675 if(!lines[i].valid)
659 tty_unregister_device(driver, i); 676 tty_unregister_device(driver, i);
660 } 677 }
661 678
@@ -663,24 +680,28 @@ struct tty_driver *line_register_devfs(struct lines *set,
663 return driver; 680 return driver;
664} 681}
665 682
666static spinlock_t winch_handler_lock; 683static DEFINE_SPINLOCK(winch_handler_lock);
667LIST_HEAD(winch_handlers); 684static LIST_HEAD(winch_handlers);
668 685
669void lines_init(struct line *lines, int nlines) 686void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
670{ 687{
671 struct line *line; 688 struct line *line;
672 int i; 689 int i;
673 690
674 spin_lock_init(&winch_handler_lock);
675 for(i = 0; i < nlines; i++){ 691 for(i = 0; i < nlines; i++){
676 line = &lines[i]; 692 line = &lines[i];
677 INIT_LIST_HEAD(&line->chan_list); 693 INIT_LIST_HEAD(&line->chan_list);
678 spin_lock_init(&line->lock); 694
679 if(line->init_str != NULL){ 695 if(line->init_str == NULL)
680 line->init_str = uml_strdup(line->init_str); 696 continue;
681 if(line->init_str == NULL) 697
682 printk("lines_init - uml_strdup returned " 698 line->init_str = kstrdup(line->init_str, GFP_KERNEL);
683 "NULL\n"); 699 if(line->init_str == NULL)
700 printk("lines_init - kstrdup returned NULL\n");
701
702 if(parse_chan_pair(line->init_str, line, i, opts)){
703 printk("parse_chan_pair failed for device %d\n", i);
704 line->valid = 0;
684 } 705 }
685 } 706 }
686} 707}
@@ -717,8 +738,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
717 tty = winch->tty; 738 tty = winch->tty;
718 if (tty != NULL) { 739 if (tty != NULL) {
719 line = tty->driver_data; 740 line = tty->driver_data;
720 chan_window_size(&line->chan_list, 741 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
721 &tty->winsize.ws_row,
722 &tty->winsize.ws_col); 742 &tty->winsize.ws_col);
723 kill_pg(tty->pgrp, SIGWINCH, 1); 743 kill_pg(tty->pgrp, SIGWINCH, 1);
724 } 744 }
@@ -749,60 +769,54 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
749 spin_unlock(&winch_handler_lock); 769 spin_unlock(&winch_handler_lock);
750 770
751 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 771 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
752 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 772 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
753 "winch", winch) < 0) 773 "winch", winch) < 0)
754 printk("register_winch_irq - failed to register IRQ\n"); 774 printk("register_winch_irq - failed to register IRQ\n");
755} 775}
756 776
777static void free_winch(struct winch *winch)
778{
779 list_del(&winch->list);
780
781 if(winch->pid != -1)
782 os_kill_process(winch->pid, 1);
783 if(winch->fd != -1)
784 os_close_file(winch->fd);
785
786 free_irq(WINCH_IRQ, winch);
787 kfree(winch);
788}
789
757static void unregister_winch(struct tty_struct *tty) 790static void unregister_winch(struct tty_struct *tty)
758{ 791{
759 struct list_head *ele; 792 struct list_head *ele;
760 struct winch *winch, *found = NULL; 793 struct winch *winch;
761 794
762 spin_lock(&winch_handler_lock); 795 spin_lock(&winch_handler_lock);
796
763 list_for_each(ele, &winch_handlers){ 797 list_for_each(ele, &winch_handlers){
764 winch = list_entry(ele, struct winch, list); 798 winch = list_entry(ele, struct winch, list);
765 if(winch->tty == tty){ 799 if(winch->tty == tty){
766 found = winch; 800 free_winch(winch);
767 break; 801 break;
768 } 802 }
769 } 803 }
770 if(found == NULL)
771 goto err;
772
773 list_del(&winch->list);
774 spin_unlock(&winch_handler_lock);
775
776 if(winch->pid != -1)
777 os_kill_process(winch->pid, 1);
778
779 free_irq(WINCH_IRQ, winch);
780 kfree(winch);
781
782 return;
783err:
784 spin_unlock(&winch_handler_lock); 804 spin_unlock(&winch_handler_lock);
785} 805}
786 806
787/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
788 * order... are we sure that nothing else is done on the list? */
789static void winch_cleanup(void) 807static void winch_cleanup(void)
790{ 808{
791 struct list_head *ele; 809 struct list_head *ele, *next;
792 struct winch *winch; 810 struct winch *winch;
793 811
794 list_for_each(ele, &winch_handlers){ 812 spin_lock(&winch_handler_lock);
813
814 list_for_each_safe(ele, next, &winch_handlers){
795 winch = list_entry(ele, struct winch, list); 815 winch = list_entry(ele, struct winch, list);
796 if(winch->fd != -1){ 816 free_winch(winch);
797 /* Why is this different from the above free_irq(),
798 * which deactivates SIGIO? This searches the FD
799 * somewhere else and removes it from the list... */
800 deactivate_fd(winch->fd, WINCH_IRQ);
801 os_close_file(winch->fd);
802 }
803 if(winch->pid != -1)
804 os_kill_process(winch->pid, 1);
805 } 817 }
818
819 spin_unlock(&winch_handler_lock);
806} 820}
807__uml_exitcall(winch_cleanup); 821__uml_exitcall(winch_cleanup);
808 822
@@ -811,10 +825,10 @@ char *add_xterm_umid(char *base)
811 char *umid, *title; 825 char *umid, *title;
812 int len; 826 int len;
813 827
814 umid = get_umid(1); 828 umid = get_umid();
815 if(umid == NULL) 829 if(*umid == '\0')
816 return base; 830 return base;
817 831
818 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 832 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
819 title = kmalloc(len, GFP_KERNEL); 833 title = kmalloc(len, GFP_KERNEL);
820 if(title == NULL){ 834 if(title == NULL){
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 12c95368124a..be610125429f 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -20,6 +20,7 @@
20#include "linux/namei.h" 20#include "linux/namei.h"
21#include "linux/proc_fs.h" 21#include "linux/proc_fs.h"
22#include "linux/syscalls.h" 22#include "linux/syscalls.h"
23#include "linux/console.h"
23#include "asm/irq.h" 24#include "asm/irq.h"
24#include "asm/uaccess.h" 25#include "asm/uaccess.h"
25#include "user_util.h" 26#include "user_util.h"
@@ -34,7 +35,7 @@
34#include "irq_kern.h" 35#include "irq_kern.h"
35#include "choose-mode.h" 36#include "choose-mode.h"
36 37
37static int do_unlink_socket(struct notifier_block *notifier, 38static int do_unlink_socket(struct notifier_block *notifier,
38 unsigned long what, void *data) 39 unsigned long what, void *data)
39{ 40{
40 return(mconsole_unlink_socket()); 41 return(mconsole_unlink_socket());
@@ -46,12 +47,12 @@ static struct notifier_block reboot_notifier = {
46 .priority = 0, 47 .priority = 0,
47}; 48};
48 49
49/* Safe without explicit locking for now. Tasklets provide their own 50/* Safe without explicit locking for now. Tasklets provide their own
50 * locking, and the interrupt handler is safe because it can't interrupt 51 * locking, and the interrupt handler is safe because it can't interrupt
51 * itself and it can only happen on CPU 0. 52 * itself and it can only happen on CPU 0.
52 */ 53 */
53 54
54LIST_HEAD(mc_requests); 55static LIST_HEAD(mc_requests);
55 56
56static void mc_work_proc(void *unused) 57static void mc_work_proc(void *unused)
57{ 58{
@@ -60,7 +61,7 @@ static void mc_work_proc(void *unused)
60 61
61 while(!list_empty(&mc_requests)){ 62 while(!list_empty(&mc_requests)){
62 local_save_flags(flags); 63 local_save_flags(flags);
63 req = list_entry(mc_requests.next, struct mconsole_entry, 64 req = list_entry(mc_requests.next, struct mconsole_entry,
64 list); 65 list);
65 list_del(&req->list); 66 list_del(&req->list);
66 local_irq_restore(flags); 67 local_irq_restore(flags);
@@ -69,7 +70,7 @@ static void mc_work_proc(void *unused)
69 } 70 }
70} 71}
71 72
72DECLARE_WORK(mconsole_work, mc_work_proc, NULL); 73static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
73 74
74static irqreturn_t mconsole_interrupt(int irq, void *dev_id, 75static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
75 struct pt_regs *regs) 76 struct pt_regs *regs)
@@ -103,8 +104,8 @@ void mconsole_version(struct mc_request *req)
103{ 104{
104 char version[256]; 105 char version[256];
105 106
106 sprintf(version, "%s %s %s %s %s", system_utsname.sysname, 107 sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
107 system_utsname.nodename, system_utsname.release, 108 system_utsname.nodename, system_utsname.release,
108 system_utsname.version, system_utsname.machine); 109 system_utsname.version, system_utsname.machine);
109 mconsole_reply(req, version, 0, 0); 110 mconsole_reply(req, version, 0, 0);
110} 111}
@@ -348,7 +349,7 @@ static struct mc_device *mconsole_find_dev(char *name)
348 349
349#define CONFIG_BUF_SIZE 64 350#define CONFIG_BUF_SIZE 64
350 351
351static void mconsole_get_config(int (*get_config)(char *, char *, int, 352static void mconsole_get_config(int (*get_config)(char *, char *, int,
352 char **), 353 char **),
353 struct mc_request *req, char *name) 354 struct mc_request *req, char *name)
354{ 355{
@@ -389,7 +390,6 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
389 out: 390 out:
390 if(buf != default_buf) 391 if(buf != default_buf)
391 kfree(buf); 392 kfree(buf);
392
393} 393}
394 394
395void mconsole_config(struct mc_request *req) 395void mconsole_config(struct mc_request *req)
@@ -420,9 +420,9 @@ void mconsole_config(struct mc_request *req)
420 420
421void mconsole_remove(struct mc_request *req) 421void mconsole_remove(struct mc_request *req)
422{ 422{
423 struct mc_device *dev; 423 struct mc_device *dev;
424 char *ptr = req->request.data, *err_msg = ""; 424 char *ptr = req->request.data, *err_msg = "";
425 char error[256]; 425 char error[256];
426 int err, start, end, n; 426 int err, start, end, n;
427 427
428 ptr += strlen("remove"); 428 ptr += strlen("remove");
@@ -433,37 +433,112 @@ void mconsole_remove(struct mc_request *req)
433 return; 433 return;
434 } 434 }
435 435
436 ptr = &ptr[strlen(dev->name)]; 436 ptr = &ptr[strlen(dev->name)];
437 437
438 err = 1; 438 err = 1;
439 n = (*dev->id)(&ptr, &start, &end); 439 n = (*dev->id)(&ptr, &start, &end);
440 if(n < 0){ 440 if(n < 0){
441 err_msg = "Couldn't parse device number"; 441 err_msg = "Couldn't parse device number";
442 goto out; 442 goto out;
443 } 443 }
444 else if((n < start) || (n > end)){ 444 else if((n < start) || (n > end)){
445 sprintf(error, "Invalid device number - must be between " 445 sprintf(error, "Invalid device number - must be between "
446 "%d and %d", start, end); 446 "%d and %d", start, end);
447 err_msg = error; 447 err_msg = error;
448 goto out; 448 goto out;
449 } 449 }
450 450
451 err = (*dev->remove)(n); 451 err = (*dev->remove)(n);
452 switch(err){ 452 switch(err){
453 case -ENODEV: 453 case -ENODEV:
454 err_msg = "Device doesn't exist"; 454 err_msg = "Device doesn't exist";
455 break; 455 break;
456 case -EBUSY: 456 case -EBUSY:
457 err_msg = "Device is currently open"; 457 err_msg = "Device is currently open";
458 break; 458 break;
459 default: 459 default:
460 break; 460 break;
461 } 461 }
462 out: 462out:
463 mconsole_reply(req, err_msg, err, 0); 463 mconsole_reply(req, err_msg, err, 0);
464} 464}
465 465
466static DEFINE_SPINLOCK(console_lock);
467static LIST_HEAD(clients);
468static char console_buf[MCONSOLE_MAX_DATA];
469static int console_index = 0;
470
471static void console_write(struct console *console, const char *string,
472 unsigned len)
473{
474 struct list_head *ele;
475 int n;
476
477 if(list_empty(&clients))
478 return;
479
480 while(1){
481 n = min(len, ARRAY_SIZE(console_buf) - console_index);
482 strncpy(&console_buf[console_index], string, n);
483 console_index += n;
484 string += n;
485 len -= n;
486 if(len == 0)
487 return;
488
489 list_for_each(ele, &clients){
490 struct mconsole_entry *entry;
491
492 entry = list_entry(ele, struct mconsole_entry, list);
493 mconsole_reply_len(&entry->request, console_buf,
494 console_index, 0, 1);
495 }
496
497 console_index = 0;
498 }
499}
500
501static struct console mc_console = { .name = "mc",
502 .write = console_write,
503 .flags = CON_PRINTBUFFER | CON_ENABLED,
504 .index = -1 };
505
506static int mc_add_console(void)
507{
508 register_console(&mc_console);
509 return 0;
510}
511
512late_initcall(mc_add_console);
513
514static void with_console(struct mc_request *req, void (*proc)(void *),
515 void *arg)
516{
517 struct mconsole_entry entry;
518 unsigned long flags;
519
520 INIT_LIST_HEAD(&entry.list);
521 entry.request = *req;
522 list_add(&entry.list, &clients);
523 spin_lock_irqsave(&console_lock, flags);
524
525 (*proc)(arg);
526
527 mconsole_reply_len(req, console_buf, console_index, 0, 0);
528 console_index = 0;
529
530 spin_unlock_irqrestore(&console_lock, flags);
531 list_del(&entry.list);
532}
533
466#ifdef CONFIG_MAGIC_SYSRQ 534#ifdef CONFIG_MAGIC_SYSRQ
535static void sysrq_proc(void *arg)
536{
537 char *op = arg;
538
539 handle_sysrq(*op, &current->thread.regs, NULL);
540}
541
467void mconsole_sysrq(struct mc_request *req) 542void mconsole_sysrq(struct mc_request *req)
468{ 543{
469 char *ptr = req->request.data; 544 char *ptr = req->request.data;
@@ -471,8 +546,13 @@ void mconsole_sysrq(struct mc_request *req)
471 ptr += strlen("sysrq"); 546 ptr += strlen("sysrq");
472 while(isspace(*ptr)) ptr++; 547 while(isspace(*ptr)) ptr++;
473 548
474 mconsole_reply(req, "", 0, 0); 549 /* With 'b', the system will shut down without a chance to reply,
475 handle_sysrq(*ptr, &current->thread.regs, NULL); 550 * so in this case, we reply first.
551 */
552 if(*ptr == 'b')
553 mconsole_reply(req, "", 0, 0);
554
555 with_console(req, sysrq_proc, ptr);
476} 556}
477#else 557#else
478void mconsole_sysrq(struct mc_request *req) 558void mconsole_sysrq(struct mc_request *req)
@@ -481,6 +561,14 @@ void mconsole_sysrq(struct mc_request *req)
481} 561}
482#endif 562#endif
483 563
564static void stack_proc(void *arg)
565{
566 struct task_struct *from = current, *to = arg;
567
568 to->thread.saved_task = from;
569 switch_to(from, to, from);
570}
571
484/* Mconsole stack trace 572/* Mconsole stack trace
485 * Added by Allan Graves, Jeff Dike 573 * Added by Allan Graves, Jeff Dike
486 * Dumps a stacks registers to the linux console. 574 * Dumps a stacks registers to the linux console.
@@ -488,37 +576,34 @@ void mconsole_sysrq(struct mc_request *req)
488 */ 576 */
489void do_stack(struct mc_request *req) 577void do_stack(struct mc_request *req)
490{ 578{
491 char *ptr = req->request.data; 579 char *ptr = req->request.data;
492 int pid_requested= -1; 580 int pid_requested= -1;
493 struct task_struct *from = NULL; 581 struct task_struct *from = NULL;
494 struct task_struct *to = NULL; 582 struct task_struct *to = NULL;
495 583
496 /* Would be nice: 584 /* Would be nice:
497 * 1) Send showregs output to mconsole. 585 * 1) Send showregs output to mconsole.
498 * 2) Add a way to stack dump all pids. 586 * 2) Add a way to stack dump all pids.
499 */ 587 */
500 588
501 ptr += strlen("stack"); 589 ptr += strlen("stack");
502 while(isspace(*ptr)) ptr++; 590 while(isspace(*ptr)) ptr++;
503
504 /* Should really check for multiple pids or reject bad args here */
505 /* What do the arguments in mconsole_reply mean? */
506 if(sscanf(ptr, "%d", &pid_requested) == 0){
507 mconsole_reply(req, "Please specify a pid", 1, 0);
508 return;
509 }
510 591
511 from = current; 592 /* Should really check for multiple pids or reject bad args here */
512 to = find_task_by_pid(pid_requested); 593 /* What do the arguments in mconsole_reply mean? */
594 if(sscanf(ptr, "%d", &pid_requested) == 0){
595 mconsole_reply(req, "Please specify a pid", 1, 0);
596 return;
597 }
513 598
514 if((to == NULL) || (pid_requested == 0)) { 599 from = current;
515 mconsole_reply(req, "Couldn't find that pid", 1, 0);
516 return;
517 }
518 to->thread.saved_task = current;
519 600
520 switch_to(from, to, from); 601 to = find_task_by_pid(pid_requested);
521 mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); 602 if((to == NULL) || (pid_requested == 0)) {
603 mconsole_reply(req, "Couldn't find that pid", 1, 0);
604 return;
605 }
606 with_console(req, stack_proc, to);
522} 607}
523 608
524void mconsole_stack(struct mc_request *req) 609void mconsole_stack(struct mc_request *req)
@@ -534,9 +619,9 @@ void mconsole_stack(struct mc_request *req)
534/* Changed by mconsole_setup, which is __setup, and called before SMP is 619/* Changed by mconsole_setup, which is __setup, and called before SMP is
535 * active. 620 * active.
536 */ 621 */
537static char *notify_socket = NULL; 622static char *notify_socket = NULL;
538 623
539int mconsole_init(void) 624static int mconsole_init(void)
540{ 625{
541 /* long to avoid size mismatch warnings from gcc */ 626 /* long to avoid size mismatch warnings from gcc */
542 long sock; 627 long sock;
@@ -563,16 +648,16 @@ int mconsole_init(void)
563 } 648 }
564 649
565 if(notify_socket != NULL){ 650 if(notify_socket != NULL){
566 notify_socket = uml_strdup(notify_socket); 651 notify_socket = kstrdup(notify_socket, GFP_KERNEL);
567 if(notify_socket != NULL) 652 if(notify_socket != NULL)
568 mconsole_notify(notify_socket, MCONSOLE_SOCKET, 653 mconsole_notify(notify_socket, MCONSOLE_SOCKET,
569 mconsole_socket_name, 654 mconsole_socket_name,
570 strlen(mconsole_socket_name) + 1); 655 strlen(mconsole_socket_name) + 1);
571 else printk(KERN_ERR "mconsole_setup failed to strdup " 656 else printk(KERN_ERR "mconsole_setup failed to strdup "
572 "string\n"); 657 "string\n");
573 } 658 }
574 659
575 printk("mconsole (version %d) initialized on %s\n", 660 printk("mconsole (version %d) initialized on %s\n",
576 MCONSOLE_VERSION, mconsole_socket_name); 661 MCONSOLE_VERSION, mconsole_socket_name);
577 return(0); 662 return(0);
578} 663}
@@ -585,7 +670,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
585 char *buf; 670 char *buf;
586 671
587 buf = kmalloc(count + 1, GFP_KERNEL); 672 buf = kmalloc(count + 1, GFP_KERNEL);
588 if(buf == NULL) 673 if(buf == NULL)
589 return(-ENOMEM); 674 return(-ENOMEM);
590 675
591 if(copy_from_user(buf, buffer, count)){ 676 if(copy_from_user(buf, buffer, count)){
@@ -661,7 +746,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
661 746
662 if(notify_socket == NULL) return(0); 747 if(notify_socket == NULL) return(0);
663 748
664 mconsole_notify(notify_socket, MCONSOLE_PANIC, message, 749 mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
665 strlen(message) + 1); 750 strlen(message) + 1);
666 return(0); 751 return(0);
667} 752}
@@ -686,14 +771,3 @@ char *mconsole_notify_socket(void)
686} 771}
687 772
688EXPORT_SYMBOL(mconsole_notify_socket); 773EXPORT_SYMBOL(mconsole_notify_socket);
689
690/*
691 * Overrides for Emacs so that we follow Linus's tabbing style.
692 * Emacs will notice this stuff at the end of the file and automatically
693 * adjust the settings for this buffer only. This must remain at the end
694 * of the file.
695 * ---------------------------------------------------------------------------
696 * Local variables:
697 * c-file-style: "linux"
698 * End:
699 */
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 310c1f823f26..4b109fe7fff8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req)
122 return(1); 122 return(1);
123} 123}
124 124
125int mconsole_reply(struct mc_request *req, char *str, int err, int more) 125int mconsole_reply_len(struct mc_request *req, const char *str, int total,
126 int err, int more)
126{ 127{
127 struct mconsole_reply reply; 128 struct mconsole_reply reply;
128 int total, len, n; 129 int len, n;
129 130
130 total = strlen(str);
131 do { 131 do {
132 reply.err = err; 132 reply.err = err;
133 133
@@ -155,6 +155,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
155 return(0); 155 return(0);
156} 156}
157 157
158int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
159{
160 return mconsole_reply_len(req, str, strlen(str), err, more);
161}
162
163
158int mconsole_unlink_socket(void) 164int mconsole_unlink_socket(void)
159{ 165{
160 unlink(mconsole_socket_name); 166 unlink(mconsole_socket_name);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 84c73a300acb..fb1f9fb9b871 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -34,7 +34,7 @@
34#define DRIVER_NAME "uml-netdev" 34#define DRIVER_NAME "uml-netdev"
35 35
36static DEFINE_SPINLOCK(opened_lock); 36static DEFINE_SPINLOCK(opened_lock);
37LIST_HEAD(opened); 37static LIST_HEAD(opened);
38 38
39static int uml_net_rx(struct net_device *dev) 39static int uml_net_rx(struct net_device *dev)
40{ 40{
@@ -150,6 +150,7 @@ static int uml_net_close(struct net_device *dev)
150 if(lp->close != NULL) 150 if(lp->close != NULL)
151 (*lp->close)(lp->fd, &lp->user); 151 (*lp->close)(lp->fd, &lp->user);
152 lp->fd = -1; 152 lp->fd = -1;
153 list_del(&lp->list);
153 154
154 spin_unlock(&lp->lock); 155 spin_unlock(&lp->lock);
155 return 0; 156 return 0;
@@ -266,7 +267,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
266} 267}
267 268
268static DEFINE_SPINLOCK(devices_lock); 269static DEFINE_SPINLOCK(devices_lock);
269static struct list_head devices = LIST_HEAD_INIT(devices); 270static LIST_HEAD(devices);
270 271
271static struct platform_driver uml_net_driver = { 272static struct platform_driver uml_net_driver = {
272 .driver = { 273 .driver = {
@@ -586,7 +587,7 @@ static int net_config(char *str)
586 err = eth_parse(str, &n, &str); 587 err = eth_parse(str, &n, &str);
587 if(err) return(err); 588 if(err) return(err);
588 589
589 str = uml_strdup(str); 590 str = kstrdup(str, GFP_KERNEL);
590 if(str == NULL){ 591 if(str == NULL){
591 printk(KERN_ERR "net_config failed to strdup string\n"); 592 printk(KERN_ERR "net_config failed to strdup string\n");
592 return(-1); 593 return(-1);
@@ -715,6 +716,7 @@ static void close_devices(void)
715 716
716 list_for_each(ele, &opened){ 717 list_for_each(ele, &opened){
717 lp = list_entry(ele, struct uml_net_private, list); 718 lp = list_entry(ele, struct uml_net_private, list);
719 free_irq(lp->dev->irq, lp->dev);
718 if((lp->close != NULL) && (lp->fd >= 0)) 720 if((lp->close != NULL) && (lp->fd >= 0))
719 (*lp->close)(lp->fd, &lp->user); 721 (*lp->close)(lp->fd, &lp->user);
720 if(lp->remove != NULL) (*lp->remove)(&lp->user); 722 if(lp->remove != NULL) (*lp->remove)(&lp->user);
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 62e04ecfada8..a32ef55cb244 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -69,7 +69,7 @@ static struct line_driver driver = {
69 .name = "ssl", 69 .name = "ssl",
70 .config = ssl_config, 70 .config = ssl_config,
71 .get_config = ssl_get_config, 71 .get_config = ssl_get_config,
72 .id = line_id, 72 .id = line_id,
73 .remove = ssl_remove, 73 .remove = ssl_remove,
74 }, 74 },
75}; 75};
@@ -84,26 +84,23 @@ static struct lines lines = LINES_INIT(NR_PORTS);
84 84
85static int ssl_config(char *str) 85static int ssl_config(char *str)
86{ 86{
87 return(line_config(serial_lines, 87 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts);
88 sizeof(serial_lines)/sizeof(serial_lines[0]), str));
89} 88}
90 89
91static int ssl_get_config(char *dev, char *str, int size, char **error_out) 90static int ssl_get_config(char *dev, char *str, int size, char **error_out)
92{ 91{
93 return(line_get_config(dev, serial_lines, 92 return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str,
94 sizeof(serial_lines)/sizeof(serial_lines[0]), 93 size, error_out);
95 str, size, error_out));
96} 94}
97 95
98static int ssl_remove(int n) 96static int ssl_remove(int n)
99{ 97{
100 return line_remove(serial_lines, 98 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
101 sizeof(serial_lines)/sizeof(serial_lines[0]), n);
102} 99}
103 100
104int ssl_open(struct tty_struct *tty, struct file *filp) 101int ssl_open(struct tty_struct *tty, struct file *filp)
105{ 102{
106 return line_open(serial_lines, tty, &opts); 103 return line_open(serial_lines, tty);
107} 104}
108 105
109#if 0 106#if 0
@@ -112,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty)
112 return; 109 return;
113} 110}
114 111
115static void ssl_throttle(struct tty_struct * tty)
116{
117 printk(KERN_ERR "Someone should implement ssl_throttle\n");
118}
119
120static void ssl_unthrottle(struct tty_struct * tty)
121{
122 printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
123}
124
125static void ssl_stop(struct tty_struct *tty) 112static void ssl_stop(struct tty_struct *tty)
126{ 113{
127 printk(KERN_ERR "Someone should implement ssl_stop\n"); 114 printk(KERN_ERR "Someone should implement ssl_stop\n");
@@ -148,9 +135,9 @@ static struct tty_operations ssl_ops = {
148 .flush_chars = line_flush_chars, 135 .flush_chars = line_flush_chars,
149 .set_termios = line_set_termios, 136 .set_termios = line_set_termios,
150 .ioctl = line_ioctl, 137 .ioctl = line_ioctl,
138 .throttle = line_throttle,
139 .unthrottle = line_unthrottle,
151#if 0 140#if 0
152 .throttle = ssl_throttle,
153 .unthrottle = ssl_unthrottle,
154 .stop = ssl_stop, 141 .stop = ssl_stop,
155 .start = ssl_start, 142 .start = ssl_start,
156 .hangup = ssl_hangup, 143 .hangup = ssl_hangup,
@@ -183,7 +170,7 @@ static int ssl_console_setup(struct console *co, char *options)
183{ 170{
184 struct line *line = &serial_lines[co->index]; 171 struct line *line = &serial_lines[co->index];
185 172
186 return console_open_chan(line,co,&opts); 173 return console_open_chan(line, co, &opts);
187} 174}
188 175
189static struct console ssl_cons = { 176static struct console ssl_cons = {
@@ -199,12 +186,13 @@ int ssl_init(void)
199{ 186{
200 char *new_title; 187 char *new_title;
201 188
202 printk(KERN_INFO "Initializing software serial port version %d\n", 189 printk(KERN_INFO "Initializing software serial port version %d\n",
203 ssl_version); 190 ssl_version);
204 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, 191 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
205 serial_lines, ARRAY_SIZE(serial_lines)); 192 serial_lines,
193 ARRAY_SIZE(serial_lines));
206 194
207 lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); 195 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
208 196
209 new_title = add_xterm_umid(opts.xterm_title); 197 new_title = add_xterm_umid(opts.xterm_title);
210 if (new_title != NULL) 198 if (new_title != NULL)
@@ -212,7 +200,7 @@ int ssl_init(void)
212 200
213 ssl_init_done = 1; 201 ssl_init_done = 1;
214 register_console(&ssl_cons); 202 register_console(&ssl_cons);
215 return(0); 203 return 0;
216} 204}
217late_initcall(ssl_init); 205late_initcall(ssl_init);
218 206
@@ -220,16 +208,13 @@ static void ssl_exit(void)
220{ 208{
221 if (!ssl_init_done) 209 if (!ssl_init_done)
222 return; 210 return;
223 close_lines(serial_lines, 211 close_lines(serial_lines, ARRAY_SIZE(serial_lines));
224 sizeof(serial_lines)/sizeof(serial_lines[0]));
225} 212}
226__uml_exitcall(ssl_exit); 213__uml_exitcall(ssl_exit);
227 214
228static int ssl_chan_setup(char *str) 215static int ssl_chan_setup(char *str)
229{ 216{
230 return(line_setup(serial_lines, 217 return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str);
231 sizeof(serial_lines)/sizeof(serial_lines[0]),
232 str, 1));
233} 218}
234 219
235__setup("ssl", ssl_chan_setup); 220__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 005aa6333b6e..61db8b2fc83f 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -75,7 +75,7 @@ static struct line_driver driver = {
75 .name = "con", 75 .name = "con",
76 .config = con_config, 76 .config = con_config,
77 .get_config = con_get_config, 77 .get_config = con_get_config,
78 .id = line_id, 78 .id = line_id,
79 .remove = con_remove, 79 .remove = con_remove,
80 }, 80 },
81}; 81};
@@ -86,28 +86,27 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS);
86 * individual elements are protected by individual semaphores. 86 * individual elements are protected by individual semaphores.
87 */ 87 */
88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), 88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
89 [ 1 ... MAX_TTYS - 1 ] = 89 [ 1 ... MAX_TTYS - 1 ] =
90 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 90 LINE_INIT(CONFIG_CON_CHAN, &driver) };
91 91
92static int con_config(char *str) 92static int con_config(char *str)
93{ 93{
94 return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); 94 return line_config(vts, ARRAY_SIZE(vts), str, &opts);
95} 95}
96 96
97static int con_get_config(char *dev, char *str, int size, char **error_out) 97static int con_get_config(char *dev, char *str, int size, char **error_out)
98{ 98{
99 return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, 99 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
100 size, error_out));
101} 100}
102 101
103static int con_remove(int n) 102static int con_remove(int n)
104{ 103{
105 return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); 104 return line_remove(vts, ARRAY_SIZE(vts), n);
106} 105}
107 106
108static int con_open(struct tty_struct *tty, struct file *filp) 107static int con_open(struct tty_struct *tty, struct file *filp)
109{ 108{
110 return line_open(vts, tty, &opts); 109 return line_open(vts, tty);
111} 110}
112 111
113static int con_init_done = 0; 112static int con_init_done = 0;
@@ -117,16 +116,18 @@ static struct tty_operations console_ops = {
117 .close = line_close, 116 .close = line_close,
118 .write = line_write, 117 .write = line_write,
119 .put_char = line_put_char, 118 .put_char = line_put_char,
120 .write_room = line_write_room, 119 .write_room = line_write_room,
121 .chars_in_buffer = line_chars_in_buffer, 120 .chars_in_buffer = line_chars_in_buffer,
122 .flush_buffer = line_flush_buffer, 121 .flush_buffer = line_flush_buffer,
123 .flush_chars = line_flush_chars, 122 .flush_chars = line_flush_chars,
124 .set_termios = line_set_termios, 123 .set_termios = line_set_termios,
125 .ioctl = line_ioctl, 124 .ioctl = line_ioctl,
125 .throttle = line_throttle,
126 .unthrottle = line_unthrottle,
126}; 127};
127 128
128static void uml_console_write(struct console *console, const char *string, 129static void uml_console_write(struct console *console, const char *string,
129 unsigned len) 130 unsigned len)
130{ 131{
131 struct line *line = &vts[console->index]; 132 struct line *line = &vts[console->index];
132 unsigned long flags; 133 unsigned long flags;
@@ -146,7 +147,7 @@ static int uml_console_setup(struct console *co, char *options)
146{ 147{
147 struct line *line = &vts[co->index]; 148 struct line *line = &vts[co->index];
148 149
149 return console_open_chan(line,co,&opts); 150 return console_open_chan(line, co, &opts);
150} 151}
151 152
152static struct console stdiocons = { 153static struct console stdiocons = {
@@ -156,7 +157,7 @@ static struct console stdiocons = {
156 .setup = uml_console_setup, 157 .setup = uml_console_setup,
157 .flags = CON_PRINTBUFFER, 158 .flags = CON_PRINTBUFFER,
158 .index = -1, 159 .index = -1,
159 .data = &vts, 160 .data = &vts,
160}; 161};
161 162
162int stdio_init(void) 163int stdio_init(void)
@@ -166,11 +167,11 @@ int stdio_init(void)
166 console_driver = line_register_devfs(&console_lines, &driver, 167 console_driver = line_register_devfs(&console_lines, &driver,
167 &console_ops, vts, 168 &console_ops, vts,
168 ARRAY_SIZE(vts)); 169 ARRAY_SIZE(vts));
169 if (NULL == console_driver) 170 if (console_driver == NULL)
170 return -1; 171 return -1;
171 printk(KERN_INFO "Initialized stdio console driver\n"); 172 printk(KERN_INFO "Initialized stdio console driver\n");
172 173
173 lines_init(vts, sizeof(vts)/sizeof(vts[0])); 174 lines_init(vts, ARRAY_SIZE(vts), &opts);
174 175
175 new_title = add_xterm_umid(opts.xterm_title); 176 new_title = add_xterm_umid(opts.xterm_title);
176 if(new_title != NULL) 177 if(new_title != NULL)
@@ -178,7 +179,7 @@ int stdio_init(void)
178 179
179 con_init_done = 1; 180 con_init_done = 1;
180 register_console(&stdiocons); 181 register_console(&stdiocons);
181 return(0); 182 return 0;
182} 183}
183late_initcall(stdio_init); 184late_initcall(stdio_init);
184 185
@@ -186,13 +187,13 @@ static void console_exit(void)
186{ 187{
187 if (!con_init_done) 188 if (!con_init_done)
188 return; 189 return;
189 close_lines(vts, sizeof(vts)/sizeof(vts[0])); 190 close_lines(vts, ARRAY_SIZE(vts));
190} 191}
191__uml_exitcall(console_exit); 192__uml_exitcall(console_exit);
192 193
193static int console_chan_setup(char *str) 194static int console_chan_setup(char *str)
194{ 195{
195 return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); 196 return line_setup(vts, ARRAY_SIZE(vts), str);
196} 197}
197__setup("con", console_chan_setup); 198__setup("con", console_chan_setup);
198__channel_help(console_chan_setup, "con"); 199__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 93898917cbe5..73f9652b2ee9 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -706,7 +706,7 @@ static int ubd_config(char *str)
706{ 706{
707 int n, err; 707 int n, err;
708 708
709 str = uml_strdup(str); 709 str = kstrdup(str, GFP_KERNEL);
710 if(str == NULL){ 710 if(str == NULL){
711 printk(KERN_ERR "ubd_config failed to strdup string\n"); 711 printk(KERN_ERR "ubd_config failed to strdup string\n");
712 return(1); 712 return(1);
@@ -1387,15 +1387,6 @@ int io_thread(void *arg)
1387 printk("io_thread - write failed, fd = %d, err = %d\n", 1387 printk("io_thread - write failed, fd = %d, err = %d\n",
1388 kernel_fd, -n); 1388 kernel_fd, -n);
1389 } 1389 }
1390}
1391 1390
1392/* 1391 return 0;
1393 * Overrides for Emacs so that we follow Linus's tabbing style. 1392}
1394 * Emacs will notice this stuff at the end of the file and automatically
1395 * adjust the settings for this buffer only. This must remain at the end
1396 * of the file.
1397 * ---------------------------------------------------------------------------
1398 * Local variables:
1399 * c-file-style: "linux"
1400 * End:
1401 */
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index da9a6717e7a4..1bb5e9d94270 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -14,21 +14,23 @@
14 14
15struct chan { 15struct chan {
16 struct list_head list; 16 struct list_head list;
17 struct list_head free_list;
18 struct line *line;
17 char *dev; 19 char *dev;
18 unsigned int primary:1; 20 unsigned int primary:1;
19 unsigned int input:1; 21 unsigned int input:1;
20 unsigned int output:1; 22 unsigned int output:1;
21 unsigned int opened:1; 23 unsigned int opened:1;
24 unsigned int enabled:1;
22 int fd; 25 int fd;
23 enum chan_init_pri pri;
24 struct chan_ops *ops; 26 struct chan_ops *ops;
25 void *data; 27 void *data;
26}; 28};
27 29
28extern void chan_interrupt(struct list_head *chans, struct work_struct *task, 30extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
29 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
30extern int parse_chan_pair(char *str, struct list_head *chans, int pri, 32extern int parse_chan_pair(char *str, struct line *line, int device,
31 int device, struct chan_opts *opts); 33 struct chan_opts *opts);
32extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
33extern 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,
34 int write_irq); 36 int write_irq);
@@ -36,9 +38,11 @@ extern int console_write_chan(struct list_head *chans, const char *buf,
36 int len); 38 int len);
37extern int console_open_chan(struct line *line, struct console *co, 39extern int console_open_chan(struct line *line, struct console *co,
38 struct chan_opts *opts); 40 struct chan_opts *opts);
39extern void close_chan(struct list_head *chans); 41extern void deactivate_chan(struct list_head *chans, int irq);
42extern void reactivate_chan(struct list_head *chans, int irq);
40extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 43extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
41extern void enable_chan(struct list_head *chans, struct tty_struct *tty); 44extern void enable_chan(struct line *line);
45extern void close_chan(struct list_head *chans, int delay_free_irq);
42extern int chan_window_size(struct list_head *chans, 46extern int chan_window_size(struct list_head *chans,
43 unsigned short *rows_out, 47 unsigned short *rows_out,
44 unsigned short *cols_out); 48 unsigned short *cols_out);
@@ -47,14 +51,3 @@ extern int chan_config_string(struct list_head *chans, char *str, int size,
47 char **error_out); 51 char **error_out);
48 52
49#endif 53#endif
50
51/*
52 * Overrides for Emacs so that we follow Linus's tabbing style.
53 * Emacs will notice this stuff at the end of the file and automatically
54 * adjust the settings for this buffer only. This must remain at the end
55 * of the file.
56 * ---------------------------------------------------------------------------
57 * Local variables:
58 * c-file-style: "linux"
59 * End:
60 */
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h
index f25fa83a5da6..b87b36a87d91 100644
--- a/arch/um/include/choose-mode.h
+++ b/arch/um/include/choose-mode.h
@@ -23,6 +23,9 @@ static inline void *__choose_mode(void *tt, void *skas) {
23 23
24#elif defined(UML_CONFIG_MODE_TT) 24#elif defined(UML_CONFIG_MODE_TT)
25#define CHOOSE_MODE(tt, skas) (tt) 25#define CHOOSE_MODE(tt, skas) (tt)
26
27#else
28#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled
26#endif 29#endif
27 30
28#define CHOOSE_MODE_PROC(tt, skas, args...) \ 31#define CHOOSE_MODE_PROC(tt, skas, args...) \
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index f724b717213f..b61deb8b362a 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -18,19 +18,8 @@ extern int deactivate_all_fds(void);
18extern void forward_interrupts(int pid); 18extern void forward_interrupts(int pid);
19extern void init_irq_signals(int on_sigstack); 19extern void init_irq_signals(int on_sigstack);
20extern void forward_ipi(int fd, int pid); 20extern void forward_ipi(int fd, int pid);
21extern void free_irq_later(int irq, void *dev_id);
22extern int activate_ipi(int fd, int pid); 21extern int activate_ipi(int fd, int pid);
23extern unsigned long irq_lock(void); 22extern unsigned long irq_lock(void);
24extern void irq_unlock(unsigned long flags); 23extern void irq_unlock(unsigned long flags);
25#endif
26 24
27/* 25#endif
28 * Overrides for Emacs so that we follow Linus's tabbing style.
29 * Emacs will notice this stuff at the end of the file and automatically
30 * adjust the settings for this buffer only. This must remain at the end
31 * of the file.
32 * ---------------------------------------------------------------------------
33 * Local variables:
34 * c-file-style: "linux"
35 * End:
36 */
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 1e3170768b5c..7d223beccbc0 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -17,7 +17,7 @@ extern int errno;
17 17
18extern int clone(int (*proc)(void *), void *sp, int flags, void *data); 18extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
19extern int sleep(int); 19extern int sleep(int);
20extern int printf(char *fmt, ...); 20extern int printf(const char *fmt, ...);
21extern char *strerror(int errnum); 21extern char *strerror(int errnum);
22extern char *ptsname(int __fd); 22extern char *ptsname(int __fd);
23extern int munmap(void *, int); 23extern int munmap(void *, int);
@@ -35,15 +35,6 @@ extern int read(unsigned int, char *, int);
35extern int pipe(int *); 35extern int pipe(int *);
36extern int sched_yield(void); 36extern int sched_yield(void);
37extern int ptrace(int op, int pid, long addr, long data); 37extern int ptrace(int op, int pid, long addr, long data);
38
38#endif 39#endif
39 40
40/*
41 * Overrides for Emacs so that we follow Linus's tabbing style.
42 * Emacs will notice this stuff at the end of the file and automatically
43 * adjust the settings for this buffer only. This must remain at the end
44 * of the file.
45 * ---------------------------------------------------------------------------
46 * Local variables:
47 * c-file-style: "linux"
48 * End:
49 */
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 5323d22a6ca7..6f4d680dc1d4 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -32,11 +32,13 @@ struct line_driver {
32}; 32};
33 33
34struct line { 34struct line {
35 struct tty_struct *tty;
35 char *init_str; 36 char *init_str;
36 int init_pri; 37 int init_pri;
37 struct list_head chan_list; 38 struct list_head chan_list;
38 int valid; 39 int valid;
39 int count; 40 int count;
41 int throttled;
40 /*This lock is actually, mostly, local to*/ 42 /*This lock is actually, mostly, local to*/
41 spinlock_t lock; 43 spinlock_t lock;
42 44
@@ -58,14 +60,15 @@ struct line {
58#define LINE_INIT(str, d) \ 60#define LINE_INIT(str, d) \
59 { init_str : str, \ 61 { init_str : str, \
60 init_pri : INIT_STATIC, \ 62 init_pri : INIT_STATIC, \
61 chan_list : { }, \
62 valid : 1, \ 63 valid : 1, \
64 throttled : 0, \
65 lock : SPIN_LOCK_UNLOCKED, \
63 buffer : NULL, \ 66 buffer : NULL, \
64 head : NULL, \ 67 head : NULL, \
65 tail : NULL, \ 68 tail : NULL, \
66 sigio : 0, \ 69 sigio : 0, \
67 driver : d, \ 70 driver : d, \
68 have_irq : 0 } 71 have_irq : 0 }
69 72
70struct lines { 73struct lines {
71 int num; 74 int num;
@@ -74,11 +77,11 @@ struct lines {
74#define LINES_INIT(n) { num : n } 77#define LINES_INIT(n) { num : n }
75 78
76extern void line_close(struct tty_struct *tty, struct file * filp); 79extern void line_close(struct tty_struct *tty, struct file * filp);
77extern int line_open(struct line *lines, struct tty_struct *tty, 80extern int line_open(struct line *lines, struct tty_struct *tty);
78 struct chan_opts *opts); 81extern int line_setup(struct line *lines, unsigned int sizeof_lines,
79extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, 82 char *init);
80 int all_allowed); 83extern int line_write(struct tty_struct *tty, const unsigned char *buf,
81extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); 84 int len);
82extern void line_put_char(struct tty_struct *tty, unsigned char ch); 85extern void line_put_char(struct tty_struct *tty, unsigned char ch);
83extern void line_set_termios(struct tty_struct *tty, struct termios * old); 86extern void line_set_termios(struct tty_struct *tty, struct termios * old);
84extern int line_chars_in_buffer(struct tty_struct *tty); 87extern int line_chars_in_buffer(struct tty_struct *tty);
@@ -87,23 +90,27 @@ extern void line_flush_chars(struct tty_struct *tty);
87extern int line_write_room(struct tty_struct *tty); 90extern int line_write_room(struct tty_struct *tty);
88extern int line_ioctl(struct tty_struct *tty, struct file * file, 91extern int line_ioctl(struct tty_struct *tty, struct file * file,
89 unsigned int cmd, unsigned long arg); 92 unsigned int cmd, unsigned long arg);
93extern void line_throttle(struct tty_struct *tty);
94extern void line_unthrottle(struct tty_struct *tty);
90 95
91extern char *add_xterm_umid(char *base); 96extern char *add_xterm_umid(char *base);
92extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty); 97extern int line_setup_irq(int fd, int input, int output, struct line *line,
98 void *data);
93extern void line_close_chan(struct line *line); 99extern void line_close_chan(struct line *line);
94extern void line_disable(struct tty_struct *tty, int current_irq); 100extern struct tty_driver * line_register_devfs(struct lines *set,
95extern struct tty_driver * line_register_devfs(struct lines *set, 101 struct line_driver *line_driver,
96 struct line_driver *line_driver,
97 struct tty_operations *driver, 102 struct tty_operations *driver,
98 struct line *lines, 103 struct line *lines,
99 int nlines); 104 int nlines);
100extern void lines_init(struct line *lines, int nlines); 105extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
101extern void close_lines(struct line *lines, int nlines); 106extern void close_lines(struct line *lines, int nlines);
102 107
103extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str); 108extern int line_config(struct line *lines, unsigned int sizeof_lines,
109 char *str, struct chan_opts *opts);
104extern int line_id(char **str, int *start_out, int *end_out); 110extern int line_id(char **str, int *start_out, int *end_out);
105extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 111extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
106extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, 112extern int line_get_config(char *dev, struct line *lines,
113 unsigned int sizeof_lines, char *str,
107 int size, char **error_out); 114 int size, char **error_out);
108 115
109#endif 116#endif
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index b1b512f47035..58f67d391105 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -32,7 +32,7 @@ struct mconsole_reply {
32 32
33struct mconsole_notify { 33struct mconsole_notify {
34 u32 magic; 34 u32 magic;
35 u32 version; 35 u32 version;
36 enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, 36 enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
37 MCONSOLE_USER_NOTIFY } type; 37 MCONSOLE_USER_NOTIFY } type;
38 u32 len; 38 u32 len;
@@ -66,7 +66,9 @@ struct mc_request
66extern char mconsole_socket_name[]; 66extern char mconsole_socket_name[];
67 67
68extern int mconsole_unlink_socket(void); 68extern int mconsole_unlink_socket(void);
69extern int mconsole_reply(struct mc_request *req, char *reply, int err, 69extern int mconsole_reply_len(struct mc_request *req, const char *reply,
70 int len, int err, int more);
71extern int mconsole_reply(struct mc_request *req, const char *str, int err,
70 int more); 72 int more);
71 73
72extern void mconsole_version(struct mc_request *req); 74extern void mconsole_version(struct mc_request *req);
@@ -84,7 +86,7 @@ extern void mconsole_proc(struct mc_request *req);
84extern void mconsole_stack(struct mc_request *req); 86extern void mconsole_stack(struct mc_request *req);
85 87
86extern int mconsole_get_request(int fd, struct mc_request *req); 88extern int mconsole_get_request(int fd, struct mc_request *req);
87extern int mconsole_notify(char *sock_name, int type, const void *data, 89extern int mconsole_notify(char *sock_name, int type, const void *data,
88 int len); 90 int len);
89extern char *mconsole_notify_socket(void); 91extern char *mconsole_notify_socket(void);
90extern void lock_notify(void); 92extern void lock_notify(void);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2cccfa5b8ab5..c279ee6d89e4 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -213,15 +213,10 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
213 int stack_order); 213 int stack_order);
214extern int helper_wait(int pid); 214extern int helper_wait(int pid);
215 215
216#endif 216/* umid.c */
217 217
218/* 218extern int umid_file_name(char *name, char *buf, int len);
219 * Overrides for Emacs so that we follow Linus's tabbing style. 219extern int set_umid(char *name);
220 * Emacs will notice this stuff at the end of the file and automatically 220extern char *get_umid(void);
221 * adjust the settings for this buffer only. This must remain at the end 221
222 * of the file. 222#endif
223 * ---------------------------------------------------------------------------
224 * Local variables:
225 * c-file-style: "linux"
226 * End:
227 */
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index bb505e01d994..b9984003e603 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -64,7 +64,6 @@ extern void setup_machinename(char *machine_out);
64extern void setup_hostinfo(void); 64extern void setup_hostinfo(void);
65extern void do_exec(int old_pid, int new_pid); 65extern void do_exec(int old_pid, int new_pid);
66extern void tracer_panic(char *msg, ...); 66extern void tracer_panic(char *msg, ...);
67extern char *get_umid(int only_if_set);
68extern void do_longjmp(void *p, int val); 67extern void do_longjmp(void *p, int val);
69extern int detach(int pid, int sig); 68extern int detach(int pid, int sig);
70extern int attach(int pid); 69extern int attach(int pid);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 3de9d21e36bf..6f7700593a6f 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -10,8 +10,8 @@ obj-y = config.o exec_kern.o exitcode.o \
10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ 12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ 13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o umid.o \
14 umid.o user_util.o 14 user_util.o
15 15
16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
17obj-$(CONFIG_GPROF) += gprof_syms.o 17obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,7 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
24 24
25user-objs-$(CONFIG_TTY_LOG) += tty_log.o 25user-objs-$(CONFIG_TTY_LOG) += tty_log.o
26 26
27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o 27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o
28 28
29include arch/um/scripts/Makefile.rules 29include arch/um/scripts/Makefile.rules
30 30
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3e0..50a2aa35cda9 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -29,7 +29,6 @@ struct irq_fd {
29 int pid; 29 int pid;
30 int events; 30 int events;
31 int current_events; 31 int current_events;
32 int freed;
33}; 32};
34 33
35static struct irq_fd *active_fds = NULL; 34static struct irq_fd *active_fds = NULL;
@@ -41,9 +40,11 @@ static int pollfds_size = 0;
41 40
42extern int io_count, intr_count; 41extern int io_count, intr_count;
43 42
43extern void free_irqs(void);
44
44void sigio_handler(int sig, union uml_pt_regs *regs) 45void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 46{
46 struct irq_fd *irq_fd, *next; 47 struct irq_fd *irq_fd;
47 int i, n; 48 int i, n;
48 49
49 if(smp_sigio_handler()) return; 50 if(smp_sigio_handler()) return;
@@ -66,29 +67,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 67 irq_fd = irq_fd->next;
67 } 68 }
68 69
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 70 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
70 next = irq_fd->next;
71 if(irq_fd->current_events != 0){ 71 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 72 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 73 do_IRQ(irq_fd->irq, regs);
74
75 /* This is here because the next irq may be
76 * freed in the handler. If a console goes
77 * away, both the read and write irqs will be
78 * freed. After do_IRQ, ->next will point to
79 * a good IRQ.
80 * Irqs can't be freed inside their handlers,
81 * so the next best thing is to have them
82 * marked as needing freeing, so that they
83 * can be freed here.
84 */
85 next = irq_fd->next;
86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id);
88 }
89 } 74 }
90 } 75 }
91 } 76 }
77
78 free_irqs();
92} 79}
93 80
94int activate_ipi(int fd, int pid) 81int activate_ipi(int fd, int pid)
@@ -136,8 +123,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 123 .irq = irq,
137 .pid = pid, 124 .pid = pid,
138 .events = events, 125 .events = events,
139 .current_events = 0, 126 .current_events = 0 } );
140 .freed = 0 } );
141 127
142 /* Critical section - locked by a spinlock because this stuff can 128 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 129 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +299,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 299 return(irq);
314} 300}
315 301
316void free_irq_later(int irq, void *dev_id)
317{
318 struct irq_fd *irq_fd;
319 unsigned long flags;
320
321 flags = irq_lock();
322 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
323 if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
324 break;
325 }
326 if(irq_fd == NULL){
327 printk("free_irq_later found no irq, irq = %d, "
328 "dev_id = 0x%p\n", irq, dev_id);
329 goto out;
330 }
331 irq_fd->freed = 1;
332 out:
333 irq_unlock(flags);
334}
335
336void reactivate_fd(int fd, int irqnum) 302void reactivate_fd(int fd, int irqnum)
337{ 303{
338 struct irq_fd *irq; 304 struct irq_fd *irq;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 34b54a3e2132..651abf255bc5 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -324,10 +324,6 @@ int user_context(unsigned long sp)
324 return(stack != (unsigned long) current_thread); 324 return(stack != (unsigned long) current_thread);
325} 325}
326 326
327extern void remove_umid_dir(void);
328
329__uml_exitcall(remove_umid_dir);
330
331extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 327extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
332 328
333void do_uml_exitcalls(void) 329void do_uml_exitcalls(void)
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 48b1f644b9a6..62e5cfdf2188 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused)
216 "err = %d\n", -n); 216 "err = %d\n", -n);
217 } 217 }
218 } 218 }
219
220 return 0;
219} 221}
220 222
221static int need_poll(int n) 223static int need_poll(int n)
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 142a9493912b..26626b2b9172 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -146,8 +146,8 @@ void set_cmdline(char *cmd)
146 146
147 if(CHOOSE_MODE(honeypot, 0)) return; 147 if(CHOOSE_MODE(honeypot, 0)) return;
148 148
149 umid = get_umid(1); 149 umid = get_umid();
150 if(umid != NULL){ 150 if(*umid != '\0'){
151 snprintf(argv1_begin, 151 snprintf(argv1_begin,
152 (argv1_end - argv1_begin) * sizeof(*ptr), 152 (argv1_end - argv1_begin) * sizeof(*ptr),
153 "(%s) ", umid); 153 "(%s) ", umid);
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 0b21d59ba0cd..4eaee823bfd2 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -3,61 +3,30 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdio.h> 6#include "asm/errno.h"
7#include <unistd.h>
8#include <errno.h>
9#include <string.h>
10#include <stdlib.h>
11#include <dirent.h>
12#include <signal.h>
13#include <sys/stat.h>
14#include <sys/param.h>
15#include "user.h"
16#include "umid.h"
17#include "init.h" 7#include "init.h"
18#include "os.h" 8#include "os.h"
19#include "user_util.h" 9#include "kern.h"
20#include "choose-mode.h" 10#include "linux/kernel.h"
21 11
22#define UMID_LEN 64 12/* Changed by set_umid_arg */
23#define UML_DIR "~/.uml/"
24
25/* Changed by set_umid and make_umid, which are run early in boot */
26static char umid[UMID_LEN] = { 0 };
27
28/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
29static char *uml_dir = UML_DIR;
30
31/* Changed by set_umid */
32static int umid_is_random = 1;
33static int umid_inited = 0; 13static int umid_inited = 0;
34/* Have we created the files? Should we remove them? */
35static int umid_owned = 0;
36 14
37static int make_umid(int (*printer)(const char *fmt, ...)); 15static int __init set_umid_arg(char *name, int *add)
38
39static int __init set_umid(char *name, int is_random,
40 int (*printer)(const char *fmt, ...))
41{ 16{
42 if(umid_inited){ 17 int err;
43 (*printer)("Unique machine name can't be set twice\n");
44 return(-1);
45 }
46 18
47 if(strlen(name) > UMID_LEN - 1) 19 if(umid_inited)
48 (*printer)("Unique machine name is being truncated to %d " 20 return 0;
49 "characters\n", UMID_LEN);
50 strlcpy(umid, name, sizeof(umid));
51 21
52 umid_is_random = is_random;
53 umid_inited = 1;
54 return 0;
55}
56
57static int __init set_umid_arg(char *name, int *add)
58{
59 *add = 0; 22 *add = 0;
60 return(set_umid(name, 0, printf)); 23 err = set_umid(name);
24 if(err == -EEXIST)
25 printf("umid '%s' already in use\n", name);
26 else if(!err)
27 umid_inited = 1;
28
29 return 0;
61} 30}
62 31
63__uml_setup("umid=", set_umid_arg, 32__uml_setup("umid=", set_umid_arg,
@@ -66,265 +35,3 @@ __uml_setup("umid=", set_umid_arg,
66" is used for naming the pid file and management console socket.\n\n" 35" is used for naming the pid file and management console socket.\n\n"
67); 36);
68 37
69int __init umid_file_name(char *name, char *buf, int len)
70{
71 int n;
72
73 if(!umid_inited && make_umid(printk)) return(-1);
74
75 n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
76 if(n > len){
77 printk("umid_file_name : buffer too short\n");
78 return(-1);
79 }
80
81 sprintf(buf, "%s%s/%s", uml_dir, umid, name);
82 return(0);
83}
84
85extern int tracing_pid;
86
87static void __init create_pid_file(void)
88{
89 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
90 char pid[sizeof("nnnnn\0")];
91 int fd, n;
92
93 if(umid_file_name("pid", file, sizeof(file)))
94 return;
95
96 fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
97 0644);
98 if(fd < 0){
99 printf("Open of machine pid file \"%s\" failed: %s\n",
100 file, strerror(-fd));
101 return;
102 }
103
104 sprintf(pid, "%d\n", os_getpid());
105 n = os_write_file(fd, pid, strlen(pid));
106 if(n != strlen(pid))
107 printf("Write of pid file failed - err = %d\n", -n);
108 os_close_file(fd);
109}
110
111static int actually_do_remove(char *dir)
112{
113 DIR *directory;
114 struct dirent *ent;
115 int len;
116 char file[256];
117
118 directory = opendir(dir);
119 if(directory == NULL){
120 printk("actually_do_remove : couldn't open directory '%s', "
121 "errno = %d\n", dir, errno);
122 return(1);
123 }
124 while((ent = readdir(directory)) != NULL){
125 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
126 continue;
127 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
128 if(len > sizeof(file)){
129 printk("Not deleting '%s' from '%s' - name too long\n",
130 ent->d_name, dir);
131 continue;
132 }
133 sprintf(file, "%s/%s", dir, ent->d_name);
134 if(unlink(file) < 0){
135 printk("actually_do_remove : couldn't remove '%s' "
136 "from '%s', errno = %d\n", ent->d_name, dir,
137 errno);
138 return(1);
139 }
140 }
141 if(rmdir(dir) < 0){
142 printk("actually_do_remove : couldn't rmdir '%s', "
143 "errno = %d\n", dir, errno);
144 return(1);
145 }
146 return(0);
147}
148
149void remove_umid_dir(void)
150{
151 char dir[strlen(uml_dir) + UMID_LEN + 1];
152 if (!umid_owned)
153 return;
154
155 sprintf(dir, "%s%s", uml_dir, umid);
156 actually_do_remove(dir);
157}
158
159char *get_umid(int only_if_set)
160{
161 if(only_if_set && umid_is_random)
162 return NULL;
163 return umid;
164}
165
166static int not_dead_yet(char *dir)
167{
168 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
169 char pid[sizeof("nnnnn\0")], *end;
170 int dead, fd, p, n;
171
172 sprintf(file, "%s/pid", dir);
173 dead = 0;
174 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
175 if(fd < 0){
176 if(fd != -ENOENT){
177 printk("not_dead_yet : couldn't open pid file '%s', "
178 "err = %d\n", file, -fd);
179 return(1);
180 }
181 dead = 1;
182 }
183 if(fd > 0){
184 n = os_read_file(fd, pid, sizeof(pid));
185 if(n < 0){
186 printk("not_dead_yet : couldn't read pid file '%s', "
187 "err = %d\n", file, -n);
188 return(1);
189 }
190 p = strtoul(pid, &end, 0);
191 if(end == pid){
192 printk("not_dead_yet : couldn't parse pid file '%s', "
193 "errno = %d\n", file, errno);
194 dead = 1;
195 }
196 if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
197 (p == CHOOSE_MODE(tracing_pid, os_getpid())))
198 dead = 1;
199 }
200 if(!dead)
201 return(1);
202 return(actually_do_remove(dir));
203}
204
205static int __init set_uml_dir(char *name, int *add)
206{
207 if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
208 uml_dir = malloc(strlen(name) + 2);
209 if(uml_dir == NULL){
210 printf("Failed to malloc uml_dir - error = %d\n",
211 errno);
212 uml_dir = name;
213 /* Return 0 here because do_initcalls doesn't look at
214 * the return value.
215 */
216 return(0);
217 }
218 sprintf(uml_dir, "%s/", name);
219 }
220 else uml_dir = name;
221 return(0);
222}
223
224static int __init make_uml_dir(void)
225{
226 char dir[MAXPATHLEN + 1] = { '\0' };
227 int len;
228
229 if(*uml_dir == '~'){
230 char *home = getenv("HOME");
231
232 if(home == NULL){
233 printf("make_uml_dir : no value in environment for "
234 "$HOME\n");
235 exit(1);
236 }
237 strlcpy(dir, home, sizeof(dir));
238 uml_dir++;
239 }
240 strlcat(dir, uml_dir, sizeof(dir));
241 len = strlen(dir);
242 if (len > 0 && dir[len - 1] != '/')
243 strlcat(dir, "/", sizeof(dir));
244
245 uml_dir = malloc(strlen(dir) + 1);
246 if (uml_dir == NULL) {
247 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
248 exit(1);
249 }
250 strcpy(uml_dir, dir);
251
252 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
253 printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno));
254 return(-1);
255 }
256 return 0;
257}
258
259static int __init make_umid(int (*printer)(const char *fmt, ...))
260{
261 int fd, err;
262 char tmp[strlen(uml_dir) + UMID_LEN + 1];
263
264 strlcpy(tmp, uml_dir, sizeof(tmp));
265
266 if(!umid_inited){
267 strcat(tmp, "XXXXXX");
268 fd = mkstemp(tmp);
269 if(fd < 0){
270 (*printer)("make_umid - mkstemp(%s) failed: %s\n",
271 tmp,strerror(errno));
272 return(1);
273 }
274
275 os_close_file(fd);
276 /* There's a nice tiny little race between this unlink and
277 * the mkdir below. It'd be nice if there were a mkstemp
278 * for directories.
279 */
280 unlink(tmp);
281 set_umid(&tmp[strlen(uml_dir)], 1, printer);
282 }
283
284 sprintf(tmp, "%s%s", uml_dir, umid);
285
286 err = mkdir(tmp, 0777);
287 if(err < 0){
288 if(errno == EEXIST){
289 if(not_dead_yet(tmp)){
290 (*printer)("umid '%s' is in use\n", umid);
291 umid_owned = 0;
292 return(-1);
293 }
294 err = mkdir(tmp, 0777);
295 }
296 }
297 if(err < 0){
298 (*printer)("Failed to create %s - errno = %d\n", umid, errno);
299 return(-1);
300 }
301
302 umid_owned = 1;
303 return 0;
304}
305
306__uml_setup("uml_dir=", set_uml_dir,
307"uml_dir=<directory>\n"
308" The location to place the pid and umid files.\n\n"
309);
310
311static int __init make_umid_setup(void)
312{
313 /* one function with the ordering we need ... */
314 make_uml_dir();
315 make_umid(printf);
316 create_pid_file();
317 return 0;
318}
319__uml_postsetup(make_umid_setup);
320
321/*
322 * Overrides for Emacs so that we follow Linus's tabbing style.
323 * Emacs will notice this stuff at the end of the file and automatically
324 * adjust the settings for this buffer only. This must remain at the end
325 * of the file.
326 * ---------------------------------------------------------------------------
327 * Local variables:
328 * c-file-style: "linux"
329 * End:
330 */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b83ac8e21c35..11e30b13e318 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,11 +4,11 @@
4# 4#
5 5
6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
7 start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \ 7 start_up.o time.o tt.o tty.o uaccess.o umid.o user_syms.o drivers/ \
8 sys-$(SUBARCH)/ 8 sys-$(SUBARCH)/
9 9
10USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 10USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
11 start_up.o time.o tt.o tty.o uaccess.o 11 start_up.o time.o tt.o tty.o uaccess.o umid.o
12 12
13elf_aux.o: $(ARCH_DIR)/kernel-offsets.h 13elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
14CFLAGS_elf_aux.o += -I$(objtree)/arch/um 14CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index ffa759addd3c..f897140cc4ae 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -16,12 +16,12 @@
16#include "mode.h" 16#include "mode.h"
17 17
18struct aio_thread_req { 18struct aio_thread_req {
19 enum aio_type type; 19 enum aio_type type;
20 int io_fd; 20 int io_fd;
21 unsigned long long offset; 21 unsigned long long offset;
22 char *buf; 22 char *buf;
23 int len; 23 int len;
24 struct aio_context *aio; 24 struct aio_context *aio;
25}; 25};
26 26
27static int aio_req_fd_r = -1; 27static int aio_req_fd_r = -1;
@@ -38,18 +38,18 @@ static int aio_req_fd_w = -1;
38 38
39static long io_setup(int n, aio_context_t *ctxp) 39static long io_setup(int n, aio_context_t *ctxp)
40{ 40{
41 return syscall(__NR_io_setup, n, ctxp); 41 return syscall(__NR_io_setup, n, ctxp);
42} 42}
43 43
44static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) 44static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
45{ 45{
46 return syscall(__NR_io_submit, ctx, nr, iocbpp); 46 return syscall(__NR_io_submit, ctx, nr, iocbpp);
47} 47}
48 48
49static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, 49static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
50 struct io_event *events, struct timespec *timeout) 50 struct io_event *events, struct timespec *timeout)
51{ 51{
52 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); 52 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
53} 53}
54 54
55#endif 55#endif
@@ -66,243 +66,245 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
66 */ 66 */
67 67
68static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, 68static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
69 int len, unsigned long long offset, struct aio_context *aio) 69 int len, unsigned long long offset, struct aio_context *aio)
70{ 70{
71 struct iocb iocb, *iocbp = &iocb; 71 struct iocb iocb, *iocbp = &iocb;
72 char c; 72 char c;
73 int err; 73 int err;
74 74
75 iocb = ((struct iocb) { .aio_data = (unsigned long) aio, 75 iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
76 .aio_reqprio = 0, 76 .aio_reqprio = 0,
77 .aio_fildes = fd, 77 .aio_fildes = fd,
78 .aio_buf = (unsigned long) buf, 78 .aio_buf = (unsigned long) buf,
79 .aio_nbytes = len, 79 .aio_nbytes = len,
80 .aio_offset = offset, 80 .aio_offset = offset,
81 .aio_reserved1 = 0, 81 .aio_reserved1 = 0,
82 .aio_reserved2 = 0, 82 .aio_reserved2 = 0,
83 .aio_reserved3 = 0 }); 83 .aio_reserved3 = 0 });
84 84
85 switch(type){ 85 switch(type){
86 case AIO_READ: 86 case AIO_READ:
87 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 87 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
88 err = io_submit(ctx, 1, &iocbp); 88 err = io_submit(ctx, 1, &iocbp);
89 break; 89 break;
90 case AIO_WRITE: 90 case AIO_WRITE:
91 iocb.aio_lio_opcode = IOCB_CMD_PWRITE; 91 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
92 err = io_submit(ctx, 1, &iocbp); 92 err = io_submit(ctx, 1, &iocbp);
93 break; 93 break;
94 case AIO_MMAP: 94 case AIO_MMAP:
95 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 95 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
96 iocb.aio_buf = (unsigned long) &c; 96 iocb.aio_buf = (unsigned long) &c;
97 iocb.aio_nbytes = sizeof(c); 97 iocb.aio_nbytes = sizeof(c);
98 err = io_submit(ctx, 1, &iocbp); 98 err = io_submit(ctx, 1, &iocbp);
99 break; 99 break;
100 default: 100 default:
101 printk("Bogus op in do_aio - %d\n", type); 101 printk("Bogus op in do_aio - %d\n", type);
102 err = -EINVAL; 102 err = -EINVAL;
103 break; 103 break;
104 } 104 }
105 105
106 if(err > 0) 106 if(err > 0)
107 err = 0; 107 err = 0;
108 else 108 else
109 err = -errno; 109 err = -errno;
110 110
111 return err; 111 return err;
112} 112}
113 113
114static aio_context_t ctx = 0; 114static aio_context_t ctx = 0;
115 115
116static int aio_thread(void *arg) 116static int aio_thread(void *arg)
117{ 117{
118 struct aio_thread_reply reply; 118 struct aio_thread_reply reply;
119 struct io_event event; 119 struct io_event event;
120 int err, n, reply_fd; 120 int err, n, reply_fd;
121 121
122 signal(SIGWINCH, SIG_IGN); 122 signal(SIGWINCH, SIG_IGN);
123 123
124 while(1){ 124 while(1){
125 n = io_getevents(ctx, 1, 1, &event, NULL); 125 n = io_getevents(ctx, 1, 1, &event, NULL);
126 if(n < 0){ 126 if(n < 0){
127 if(errno == EINTR) 127 if(errno == EINTR)
128 continue; 128 continue;
129 printk("aio_thread - io_getevents failed, " 129 printk("aio_thread - io_getevents failed, "
130 "errno = %d\n", errno); 130 "errno = %d\n", errno);
131 } 131 }
132 else { 132 else {
133 reply = ((struct aio_thread_reply) 133 reply = ((struct aio_thread_reply)
134 { .data = (void *) (long) event.data, 134 { .data = (void *) (long) event.data,
135 .err = event.res }); 135 .err = event.res });
136 reply_fd = ((struct aio_context *) reply.data)->reply_fd; 136 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
137 err = os_write_file(reply_fd, &reply, sizeof(reply)); 137 err = os_write_file(reply_fd, &reply, sizeof(reply));
138 if(err != sizeof(reply)) 138 if(err != sizeof(reply))
139 printk("aio_thread - write failed, fd = %d, " 139 printk("aio_thread - write failed, fd = %d, "
140 "err = %d\n", aio_req_fd_r, -err); 140 "err = %d\n", aio_req_fd_r, -err);
141 } 141 }
142 } 142 }
143 return 0; 143 return 0;
144} 144}
145 145
146#endif 146#endif
147 147
148static int do_not_aio(struct aio_thread_req *req) 148static int do_not_aio(struct aio_thread_req *req)
149{ 149{
150 char c; 150 char c;
151 int err; 151 int err;
152 152
153 switch(req->type){ 153 switch(req->type){
154 case AIO_READ: 154 case AIO_READ:
155 err = os_seek_file(req->io_fd, req->offset); 155 err = os_seek_file(req->io_fd, req->offset);
156 if(err) 156 if(err)
157 goto out; 157 goto out;
158 158
159 err = os_read_file(req->io_fd, req->buf, req->len); 159 err = os_read_file(req->io_fd, req->buf, req->len);
160 break; 160 break;
161 case AIO_WRITE: 161 case AIO_WRITE:
162 err = os_seek_file(req->io_fd, req->offset); 162 err = os_seek_file(req->io_fd, req->offset);
163 if(err) 163 if(err)
164 goto out; 164 goto out;
165 165
166 err = os_write_file(req->io_fd, req->buf, req->len); 166 err = os_write_file(req->io_fd, req->buf, req->len);
167 break; 167 break;
168 case AIO_MMAP: 168 case AIO_MMAP:
169 err = os_seek_file(req->io_fd, req->offset); 169 err = os_seek_file(req->io_fd, req->offset);
170 if(err) 170 if(err)
171 goto out; 171 goto out;
172 172
173 err = os_read_file(req->io_fd, &c, sizeof(c)); 173 err = os_read_file(req->io_fd, &c, sizeof(c));
174 break; 174 break;
175 default: 175 default:
176 printk("do_not_aio - bad request type : %d\n", req->type); 176 printk("do_not_aio - bad request type : %d\n", req->type);
177 err = -EINVAL; 177 err = -EINVAL;
178 break; 178 break;
179 } 179 }
180 180
181 out: 181out:
182 return err; 182 return err;
183} 183}
184 184
185static int not_aio_thread(void *arg) 185static int not_aio_thread(void *arg)
186{ 186{
187 struct aio_thread_req req; 187 struct aio_thread_req req;
188 struct aio_thread_reply reply; 188 struct aio_thread_reply reply;
189 int err; 189 int err;
190 190
191 signal(SIGWINCH, SIG_IGN); 191 signal(SIGWINCH, SIG_IGN);
192 while(1){ 192 while(1){
193 err = os_read_file(aio_req_fd_r, &req, sizeof(req)); 193 err = os_read_file(aio_req_fd_r, &req, sizeof(req));
194 if(err != sizeof(req)){ 194 if(err != sizeof(req)){
195 if(err < 0) 195 if(err < 0)
196 printk("not_aio_thread - read failed, " 196 printk("not_aio_thread - read failed, "
197 "fd = %d, err = %d\n", aio_req_fd_r, 197 "fd = %d, err = %d\n", aio_req_fd_r,
198 -err); 198 -err);
199 else { 199 else {
200 printk("not_aio_thread - short read, fd = %d, " 200 printk("not_aio_thread - short read, fd = %d, "
201 "length = %d\n", aio_req_fd_r, err); 201 "length = %d\n", aio_req_fd_r, err);
202 } 202 }
203 continue; 203 continue;
204 } 204 }
205 err = do_not_aio(&req); 205 err = do_not_aio(&req);
206 reply = ((struct aio_thread_reply) { .data = req.aio, 206 reply = ((struct aio_thread_reply) { .data = req.aio,
207 .err = err }); 207 .err = err });
208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); 208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
209 if(err != sizeof(reply)) 209 if(err != sizeof(reply))
210 printk("not_aio_thread - write failed, fd = %d, " 210 printk("not_aio_thread - write failed, fd = %d, "
211 "err = %d\n", aio_req_fd_r, -err); 211 "err = %d\n", aio_req_fd_r, -err);
212 } 212 }
213
214 return 0;
213} 215}
214 216
215static int aio_pid = -1; 217static int aio_pid = -1;
216 218
217static int init_aio_24(void) 219static int init_aio_24(void)
218{ 220{
219 unsigned long stack; 221 unsigned long stack;
220 int fds[2], err; 222 int fds[2], err;
221 223
222 err = os_pipe(fds, 1, 1); 224 err = os_pipe(fds, 1, 1);
223 if(err) 225 if(err)
224 goto out; 226 goto out;
225 227
226 aio_req_fd_w = fds[0]; 228 aio_req_fd_w = fds[0];
227 aio_req_fd_r = fds[1]; 229 aio_req_fd_r = fds[1];
228 err = run_helper_thread(not_aio_thread, NULL, 230 err = run_helper_thread(not_aio_thread, NULL,
229 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 231 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
230 if(err < 0) 232 if(err < 0)
231 goto out_close_pipe; 233 goto out_close_pipe;
232 234
233 aio_pid = err; 235 aio_pid = err;
234 goto out; 236 goto out;
235 237
236 out_close_pipe: 238out_close_pipe:
237 os_close_file(fds[0]); 239 os_close_file(fds[0]);
238 os_close_file(fds[1]); 240 os_close_file(fds[1]);
239 aio_req_fd_w = -1; 241 aio_req_fd_w = -1;
240 aio_req_fd_r = -1; 242 aio_req_fd_r = -1;
241 out: 243out:
242#ifndef HAVE_AIO_ABI 244#ifndef HAVE_AIO_ABI
243 printk("/usr/include/linux/aio_abi.h not present during build\n"); 245 printk("/usr/include/linux/aio_abi.h not present during build\n");
244#endif 246#endif
245 printk("2.6 host AIO support not used - falling back to I/O " 247 printk("2.6 host AIO support not used - falling back to I/O "
246 "thread\n"); 248 "thread\n");
247 return 0; 249 return 0;
248} 250}
249 251
250#ifdef HAVE_AIO_ABI 252#ifdef HAVE_AIO_ABI
251#define DEFAULT_24_AIO 0 253#define DEFAULT_24_AIO 0
252static int init_aio_26(void) 254static int init_aio_26(void)
253{ 255{
254 unsigned long stack; 256 unsigned long stack;
255 int err; 257 int err;
256 258
257 if(io_setup(256, &ctx)){ 259 if(io_setup(256, &ctx)){
258 err = -errno; 260 err = -errno;
259 printk("aio_thread failed to initialize context, err = %d\n", 261 printk("aio_thread failed to initialize context, err = %d\n",
260 errno); 262 errno);
261 return err; 263 return err;
262 } 264 }
263 265
264 err = run_helper_thread(aio_thread, NULL, 266 err = run_helper_thread(aio_thread, NULL,
265 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 267 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
266 if(err < 0) 268 if(err < 0)
267 return err; 269 return err;
268 270
269 aio_pid = err; 271 aio_pid = err;
270 272
271 printk("Using 2.6 host AIO\n"); 273 printk("Using 2.6 host AIO\n");
272 return 0; 274 return 0;
273} 275}
274 276
275static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, 277static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
276 unsigned long long offset, struct aio_context *aio) 278 unsigned long long offset, struct aio_context *aio)
277{ 279{
278 struct aio_thread_reply reply; 280 struct aio_thread_reply reply;
279 int err; 281 int err;
280 282
281 err = do_aio(ctx, type, io_fd, buf, len, offset, aio); 283 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
282 if(err){ 284 if(err){
283 reply = ((struct aio_thread_reply) { .data = aio, 285 reply = ((struct aio_thread_reply) { .data = aio,
284 .err = err }); 286 .err = err });
285 err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); 287 err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
286 if(err != sizeof(reply)) 288 if(err != sizeof(reply))
287 printk("submit_aio_26 - write failed, " 289 printk("submit_aio_26 - write failed, "
288 "fd = %d, err = %d\n", aio->reply_fd, -err); 290 "fd = %d, err = %d\n", aio->reply_fd, -err);
289 else err = 0; 291 else err = 0;
290 } 292 }
291 293
292 return err; 294 return err;
293} 295}
294 296
295#else 297#else
296#define DEFAULT_24_AIO 1 298#define DEFAULT_24_AIO 1
297static int init_aio_26(void) 299static int init_aio_26(void)
298{ 300{
299 return -ENOSYS; 301 return -ENOSYS;
300} 302}
301 303
302static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, 304static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
303 unsigned long long offset, struct aio_context *aio) 305 unsigned long long offset, struct aio_context *aio)
304{ 306{
305 return -ENOSYS; 307 return -ENOSYS;
306} 308}
307#endif 309#endif
308 310
@@ -310,8 +312,8 @@ static int aio_24 = DEFAULT_24_AIO;
310 312
311static int __init set_aio_24(char *name, int *add) 313static int __init set_aio_24(char *name, int *add)
312{ 314{
313 aio_24 = 1; 315 aio_24 = 1;
314 return 0; 316 return 0;
315} 317}
316 318
317__uml_setup("aio=2.4", set_aio_24, 319__uml_setup("aio=2.4", set_aio_24,
@@ -328,28 +330,27 @@ __uml_setup("aio=2.4", set_aio_24,
328 330
329static int init_aio(void) 331static int init_aio(void)
330{ 332{
331 int err; 333 int err;
332 334
333 CHOOSE_MODE(({ 335 CHOOSE_MODE(({ if(!aio_24){
334 if(!aio_24){ 336 printk("Disabling 2.6 AIO in tt mode\n");
335 printk("Disabling 2.6 AIO in tt mode\n"); 337 aio_24 = 1;
336 aio_24 = 1; 338 } }), (void) 0);
337 } }), (void) 0); 339
338 340 if(!aio_24){
339 if(!aio_24){ 341 err = init_aio_26();
340 err = init_aio_26(); 342 if(err && (errno == ENOSYS)){
341 if(err && (errno == ENOSYS)){ 343 printk("2.6 AIO not supported on the host - "
342 printk("2.6 AIO not supported on the host - " 344 "reverting to 2.4 AIO\n");
343 "reverting to 2.4 AIO\n"); 345 aio_24 = 1;
344 aio_24 = 1; 346 }
345 } 347 else return err;
346 else return err; 348 }
347 } 349
348 350 if(aio_24)
349 if(aio_24) 351 return init_aio_24();
350 return init_aio_24(); 352
351 353 return 0;
352 return 0;
353} 354}
354 355
355/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio 356/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
@@ -362,8 +363,8 @@ __initcall(init_aio);
362 363
363static void exit_aio(void) 364static void exit_aio(void)
364{ 365{
365 if(aio_pid != -1) 366 if(aio_pid != -1)
366 os_kill_process(aio_pid, 1); 367 os_kill_process(aio_pid, 1);
367} 368}
368 369
369__uml_exitcall(exit_aio); 370__uml_exitcall(exit_aio);
@@ -371,30 +372,30 @@ __uml_exitcall(exit_aio);
371static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, 372static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
372 unsigned long long offset, struct aio_context *aio) 373 unsigned long long offset, struct aio_context *aio)
373{ 374{
374 struct aio_thread_req req = { .type = type, 375 struct aio_thread_req req = { .type = type,
375 .io_fd = io_fd, 376 .io_fd = io_fd,
376 .offset = offset, 377 .offset = offset,
377 .buf = buf, 378 .buf = buf,
378 .len = len, 379 .len = len,
379 .aio = aio, 380 .aio = aio,
380 }; 381 };
381 int err; 382 int err;
382 383
383 err = os_write_file(aio_req_fd_w, &req, sizeof(req)); 384 err = os_write_file(aio_req_fd_w, &req, sizeof(req));
384 if(err == sizeof(req)) 385 if(err == sizeof(req))
385 err = 0; 386 err = 0;
386 387
387 return err; 388 return err;
388} 389}
389 390
390int submit_aio(enum aio_type type, int io_fd, char *buf, int len, 391int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
391 unsigned long long offset, int reply_fd, 392 unsigned long long offset, int reply_fd,
392 struct aio_context *aio) 393 struct aio_context *aio)
393{ 394{
394 aio->reply_fd = reply_fd; 395 aio->reply_fd = reply_fd;
395 if(aio_24) 396 if(aio_24)
396 return submit_aio_24(type, io_fd, buf, len, offset, aio); 397 return submit_aio_24(type, io_fd, buf, len, offset, aio);
397 else { 398 else {
398 return submit_aio_26(type, io_fd, buf, len, offset, aio); 399 return submit_aio_26(type, io_fd, buf, len, offset, aio);
399 } 400 }
400} 401}
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
new file mode 100644
index 000000000000..ecf107ae5ac8
--- /dev/null
+++ b/arch/um/os-Linux/umid.c
@@ -0,0 +1,335 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <string.h>
5#include <errno.h>
6#include <signal.h>
7#include <dirent.h>
8#include <sys/fcntl.h>
9#include <sys/stat.h>
10#include <sys/param.h>
11#include "init.h"
12#include "os.h"
13#include "user.h"
14#include "mode.h"
15
16#define UML_DIR "~/.uml/"
17
18#define UMID_LEN 64
19
20/* Changed by set_umid, which is run early in boot */
21char umid[UMID_LEN] = { 0 };
22
23/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
24static char *uml_dir = UML_DIR;
25
26static int __init make_uml_dir(void)
27{
28 char dir[512] = { '\0' };
29 int len, err;
30
31 if(*uml_dir == '~'){
32 char *home = getenv("HOME");
33
34 err = -ENOENT;
35 if(home == NULL){
36 printk("make_uml_dir : no value in environment for "
37 "$HOME\n");
38 goto err;
39 }
40 strlcpy(dir, home, sizeof(dir));
41 uml_dir++;
42 }
43 strlcat(dir, uml_dir, sizeof(dir));
44 len = strlen(dir);
45 if (len > 0 && dir[len - 1] != '/')
46 strlcat(dir, "/", sizeof(dir));
47
48 err = -ENOMEM;
49 uml_dir = malloc(strlen(dir) + 1);
50 if (uml_dir == NULL) {
51 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
52 goto err;
53 }
54 strcpy(uml_dir, dir);
55
56 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
57 printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno));
58 err = -errno;
59 goto err_free;
60 }
61 return 0;
62
63err_free:
64 free(uml_dir);
65err:
66 uml_dir = NULL;
67 return err;
68}
69
70static int actually_do_remove(char *dir)
71{
72 DIR *directory;
73 struct dirent *ent;
74 int len;
75 char file[256];
76
77 directory = opendir(dir);
78 if(directory == NULL)
79 return -errno;
80
81 while((ent = readdir(directory)) != NULL){
82 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
83 continue;
84 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
85 if(len > sizeof(file))
86 return -E2BIG;
87
88 sprintf(file, "%s/%s", dir, ent->d_name);
89 if(unlink(file) < 0)
90 return -errno;
91 }
92 if(rmdir(dir) < 0)
93 return -errno;
94
95 return 0;
96}
97
98/* This says that there isn't already a user of the specified directory even if
99 * there are errors during the checking. This is because if these errors
100 * happen, the directory is unusable by the pre-existing UML, so we might as
101 * well take it over. This could happen either by
102 * the existing UML somehow corrupting its umid directory
103 * something other than UML sticking stuff in the directory
104 * this boot racing with a shutdown of the other UML
105 * In any of these cases, the directory isn't useful for anything else.
106 */
107
108static int not_dead_yet(char *dir)
109{
110 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
111 char pid[sizeof("nnnnn\0")], *end;
112 int dead, fd, p, n, err;
113
114 n = snprintf(file, sizeof(file), "%s/pid", dir);
115 if(n >= sizeof(file)){
116 printk("not_dead_yet - pid filename too long\n");
117 err = -E2BIG;
118 goto out;
119 }
120
121 dead = 0;
122 fd = open(file, O_RDONLY);
123 if(fd < 0){
124 if(fd != -ENOENT){
125 printk("not_dead_yet : couldn't open pid file '%s', "
126 "err = %d\n", file, -fd);
127 }
128 goto out;
129 }
130
131 err = 0;
132 n = read(fd, pid, sizeof(pid));
133 if(n <= 0){
134 printk("not_dead_yet : couldn't read pid file '%s', "
135 "err = %d\n", file, -n);
136 goto out_close;
137 }
138
139 p = strtoul(pid, &end, 0);
140 if(end == pid){
141 printk("not_dead_yet : couldn't parse pid file '%s', "
142 "errno = %d\n", file, errno);
143 goto out_close;
144 }
145
146 if((kill(p, 0) == 0) || (errno != ESRCH))
147 return 1;
148
149 err = actually_do_remove(dir);
150 if(err)
151 printk("not_dead_yet - actually_do_remove failed with "
152 "err = %d\n", err);
153
154 return err;
155
156 out_close:
157 close(fd);
158 out:
159 return 0;
160}
161
162static void __init create_pid_file(void)
163{
164 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
165 char pid[sizeof("nnnnn\0")];
166 int fd, n;
167
168 if(umid_file_name("pid", file, sizeof(file)))
169 return;
170
171 fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
172 if(fd < 0){
173 printk("Open of machine pid file \"%s\" failed: %s\n",
174 file, strerror(-fd));
175 return;
176 }
177
178 snprintf(pid, sizeof(pid), "%d\n", getpid());
179 n = write(fd, pid, strlen(pid));
180 if(n != strlen(pid))
181 printk("Write of pid file failed - err = %d\n", -n);
182
183 close(fd);
184}
185
186int __init set_umid(char *name)
187{
188 if(strlen(name) > UMID_LEN - 1)
189 return -E2BIG;
190
191 strlcpy(umid, name, sizeof(umid));
192
193 return 0;
194}
195
196static int umid_setup = 0;
197
198int __init make_umid(void)
199{
200 int fd, err;
201 char tmp[256];
202
203 if(umid_setup)
204 return 0;
205
206 make_uml_dir();
207
208 if(*umid == '\0'){
209 strlcpy(tmp, uml_dir, sizeof(tmp));
210 strlcat(tmp, "XXXXXX", sizeof(tmp));
211 fd = mkstemp(tmp);
212 if(fd < 0){
213 printk("make_umid - mkstemp(%s) failed: %s\n",
214 tmp, strerror(errno));
215 err = -errno;
216 goto err;
217 }
218
219 close(fd);
220
221 set_umid(&tmp[strlen(uml_dir)]);
222
223 /* There's a nice tiny little race between this unlink and
224 * the mkdir below. It'd be nice if there were a mkstemp
225 * for directories.
226 */
227 if(unlink(tmp)){
228 err = -errno;
229 goto err;
230 }
231 }
232
233 snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid);
234 err = mkdir(tmp, 0777);
235 if(err < 0){
236 err = -errno;
237 if(errno != EEXIST)
238 goto err;
239
240 if(not_dead_yet(tmp) < 0)
241 goto err;
242
243 err = mkdir(tmp, 0777);
244 }
245 if(err < 0){
246 printk("Failed to create '%s' - err = %d\n", umid, err);
247 goto err_rmdir;
248 }
249
250 umid_setup = 1;
251
252 create_pid_file();
253
254 return 0;
255
256 err_rmdir:
257 rmdir(tmp);
258 err:
259 return err;
260}
261
262static int __init make_umid_init(void)
263{
264 make_umid();
265
266 return 0;
267}
268
269__initcall(make_umid_init);
270
271int __init umid_file_name(char *name, char *buf, int len)
272{
273 int n, err;
274
275 err = make_umid();
276 if(err)
277 return err;
278
279 n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
280 if(n >= len){
281 printk("umid_file_name : buffer too short\n");
282 return -E2BIG;
283 }
284
285 return 0;
286}
287
288char *get_umid(void)
289{
290 return umid;
291}
292
293static int __init set_uml_dir(char *name, int *add)
294{
295 if(*name == '\0'){
296 printf("uml_dir can't be an empty string\n");
297 return 0;
298 }
299
300 if(name[strlen(name) - 1] == '/'){
301 uml_dir = name;
302 return 0;
303 }
304
305 uml_dir = malloc(strlen(name) + 2);
306 if(uml_dir == NULL){
307 printf("Failed to malloc uml_dir - error = %d\n", errno);
308
309 /* Return 0 here because do_initcalls doesn't look at
310 * the return value.
311 */
312 return 0;
313 }
314 sprintf(uml_dir, "%s/", name);
315
316 return 0;
317}
318
319__uml_setup("uml_dir=", set_uml_dir,
320"uml_dir=<directory>\n"
321" The location to place the pid and umid files.\n\n"
322);
323
324static void remove_umid_dir(void)
325{
326 char dir[strlen(uml_dir) + UMID_LEN + 1], err;
327
328 sprintf(dir, "%s%s", uml_dir, umid);
329 err = actually_do_remove(dir);
330 if(err)
331 printf("remove_umid_dir - actually_do_remove failed with "
332 "err = %d\n", err);
333}
334
335__uml_exitcall(remove_umid_dir);