[PATCH] uml: mconsole fixes

* when we have stop/sysrq/go, we get pt_regs of whatever executes
mc_work_proc(). Would be better to see what we had at the time of
interrupt that got us stop.

* stop/stop/stop..... will give stack overflow. Shouldn't allow stop
from mconsole_stop().

* stop/stop/go leaves us inside mconsole_stop() with
os_set_fd_block(req->originating_fd, 0);
reactivate_fd(req->originating_fd, MCONSOLE_IRQ);
just done by nested mconsole_stop(). Ditto.

* once we'd seen stop, there's a period when INTR commands are executed
out of order (as they should; we might have the things stuck badly
enough to never reach mconsole_stop(), but still not badly enough to
block mconsole_interrupt(); in that situation we _want_ things like
"cad" to be executed immediately). Once we enter monsole_stop(), all
INTR commands will be executed in order, mixed with PROC ones. We'd
better let user see that such change of behaviour has happened.
(Suggested by lennert).

* stack footprint of monsole_interrupt() is an atrocity; AFAICS we can
safely make struct mc_request req; static in function there.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Al Viro and committed by Linus Torvalds 3a51237d 6c504447

+19 -6
+17 -6
arch/um/drivers/mconsole_kern.c
··· 79 /* long to avoid size mismatch warnings from gcc */ 80 long fd; 81 struct mconsole_entry *new; 82 - struct mc_request req; 83 84 fd = (long) dev_id; 85 while (mconsole_get_request(fd, &req)){ ··· 91 mconsole_reply(&req, "Out of memory", 1, 0); 92 else { 93 new->request = req; 94 list_add(&new->list, &mc_requests); 95 } 96 } ··· 315 { 316 deactivate_fd(req->originating_fd, MCONSOLE_IRQ); 317 os_set_fd_block(req->originating_fd, 1); 318 - mconsole_reply(req, "", 0, 0); 319 - while(mconsole_get_request(req->originating_fd, req)){ 320 - if(req->cmd->handler == mconsole_go) break; 321 (*req->cmd->handler)(req); 322 } 323 os_set_fd_block(req->originating_fd, 0); ··· 686 static void sysrq_proc(void *arg) 687 { 688 char *op = arg; 689 - struct pt_regs *old_regs = set_irq_regs(&current->thread.regs); 690 handle_sysrq(*op, NULL); 691 - set_irq_regs(old_regs); 692 } 693 694 void mconsole_sysrq(struct mc_request *req)
··· 79 /* long to avoid size mismatch warnings from gcc */ 80 long fd; 81 struct mconsole_entry *new; 82 + static struct mc_request req; /* that's OK */ 83 84 fd = (long) dev_id; 85 while (mconsole_get_request(fd, &req)){ ··· 91 mconsole_reply(&req, "Out of memory", 1, 0); 92 else { 93 new->request = req; 94 + new->request.regs = get_irq_regs()->regs; 95 list_add(&new->list, &mc_requests); 96 } 97 } ··· 314 { 315 deactivate_fd(req->originating_fd, MCONSOLE_IRQ); 316 os_set_fd_block(req->originating_fd, 1); 317 + mconsole_reply(req, "stopped", 0, 0); 318 + while (mconsole_get_request(req->originating_fd, req)) { 319 + if (req->cmd->handler == mconsole_go) 320 + break; 321 + if (req->cmd->handler == mconsole_stop) { 322 + mconsole_reply(req, "Already stopped", 1, 0); 323 + continue; 324 + } 325 + if (req->cmd->handler == mconsole_sysrq) { 326 + struct pt_regs *old_regs; 327 + old_regs = set_irq_regs((struct pt_regs *)&req->regs); 328 + mconsole_sysrq(req); 329 + set_irq_regs(old_regs); 330 + continue; 331 + } 332 (*req->cmd->handler)(req); 333 } 334 os_set_fd_block(req->originating_fd, 0); ··· 673 static void sysrq_proc(void *arg) 674 { 675 char *op = arg; 676 handle_sysrq(*op, NULL); 677 } 678 679 void mconsole_sysrq(struct mc_request *req)
+1
arch/um/drivers/mconsole_user.c
··· 14 #include <sys/un.h> 15 #include <unistd.h> 16 #include "user.h" 17 #include "mconsole.h" 18 #include "umid.h" 19 #include "user_util.h"
··· 14 #include <sys/un.h> 15 #include <unistd.h> 16 #include "user.h" 17 + #include "sysdep/ptrace.h" 18 #include "mconsole.h" 19 #include "umid.h" 20 #include "user_util.h"
+1
arch/um/include/mconsole.h
··· 61 62 struct mconsole_request request; 63 struct mconsole_command *cmd; 64 }; 65 66 extern char mconsole_socket_name[];
··· 61 62 struct mconsole_request request; 63 struct mconsole_command *cmd; 64 + union uml_pt_regs regs; 65 }; 66 67 extern char mconsole_socket_name[];