mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
[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>
This commit is contained in:
parent
6c50444723
commit
3a51237dc1
3 changed files with 19 additions and 6 deletions
|
@ -79,7 +79,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
|
|||
/* long to avoid size mismatch warnings from gcc */
|
||||
long fd;
|
||||
struct mconsole_entry *new;
|
||||
struct mc_request req;
|
||||
static struct mc_request req; /* that's OK */
|
||||
|
||||
fd = (long) dev_id;
|
||||
while (mconsole_get_request(fd, &req)){
|
||||
|
@ -91,6 +91,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
|
|||
mconsole_reply(&req, "Out of memory", 1, 0);
|
||||
else {
|
||||
new->request = req;
|
||||
new->request.regs = get_irq_regs()->regs;
|
||||
list_add(&new->list, &mc_requests);
|
||||
}
|
||||
}
|
||||
|
@ -314,9 +315,21 @@ void mconsole_stop(struct mc_request *req)
|
|||
{
|
||||
deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
|
||||
os_set_fd_block(req->originating_fd, 1);
|
||||
mconsole_reply(req, "", 0, 0);
|
||||
while(mconsole_get_request(req->originating_fd, req)){
|
||||
if(req->cmd->handler == mconsole_go) break;
|
||||
mconsole_reply(req, "stopped", 0, 0);
|
||||
while (mconsole_get_request(req->originating_fd, req)) {
|
||||
if (req->cmd->handler == mconsole_go)
|
||||
break;
|
||||
if (req->cmd->handler == mconsole_stop) {
|
||||
mconsole_reply(req, "Already stopped", 1, 0);
|
||||
continue;
|
||||
}
|
||||
if (req->cmd->handler == mconsole_sysrq) {
|
||||
struct pt_regs *old_regs;
|
||||
old_regs = set_irq_regs((struct pt_regs *)&req->regs);
|
||||
mconsole_sysrq(req);
|
||||
set_irq_regs(old_regs);
|
||||
continue;
|
||||
}
|
||||
(*req->cmd->handler)(req);
|
||||
}
|
||||
os_set_fd_block(req->originating_fd, 0);
|
||||
|
@ -673,9 +686,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
|
|||
static void sysrq_proc(void *arg)
|
||||
{
|
||||
char *op = arg;
|
||||
struct pt_regs *old_regs = set_irq_regs(¤t->thread.regs);
|
||||
handle_sysrq(*op, NULL);
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
void mconsole_sysrq(struct mc_request *req)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include "user.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
#include "mconsole.h"
|
||||
#include "umid.h"
|
||||
#include "user_util.h"
|
||||
|
|
|
@ -61,6 +61,7 @@ struct mc_request
|
|||
|
||||
struct mconsole_request request;
|
||||
struct mconsole_command *cmd;
|
||||
union uml_pt_regs regs;
|
||||
};
|
||||
|
||||
extern char mconsole_socket_name[];
|
||||
|
|
Loading…
Reference in a new issue