lguest: Reboot support
Reboot Implemented (Prevent fd leak, fix style and fix documentation --RR) Signed-off-by: Balaji Rao <balajirrao@gmail.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Rusty Russell
parent
5c55841d16
commit
ec04b13f67
@@ -153,6 +153,9 @@ struct virtqueue
|
||||
void (*handle_output)(int fd, struct virtqueue *me);
|
||||
};
|
||||
|
||||
/* Remember the arguments to the program so we can "reboot" */
|
||||
static char **main_args;
|
||||
|
||||
/* Since guest is UP and we don't run at the same time, we don't need barriers.
|
||||
* But I include them in the code in case others copy it. */
|
||||
#define wmb()
|
||||
@@ -1489,7 +1492,9 @@ static void setup_block_file(const char *filename)
|
||||
|
||||
/* Create stack for thread and run it */
|
||||
stack = malloc(32768);
|
||||
if (clone(io_thread, stack + 32768, CLONE_VM, dev) == -1)
|
||||
/* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from
|
||||
* becoming a zombie. */
|
||||
if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1)
|
||||
err(1, "Creating clone");
|
||||
|
||||
/* We don't need to keep the I/O thread's end of the pipes open. */
|
||||
@@ -1499,7 +1504,21 @@ static void setup_block_file(const char *filename)
|
||||
verbose("device %u: virtblock %llu sectors\n",
|
||||
devices.device_num, cap);
|
||||
}
|
||||
/* That's the end of device setup. */
|
||||
/* That's the end of device setup. :*/
|
||||
|
||||
/* Reboot */
|
||||
static void __attribute__((noreturn)) restart_guest(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Closing pipes causes the waker thread and io_threads to die, and
|
||||
* closing /dev/lguest cleans up the Guest. Since we don't track all
|
||||
* open fds, we simply close everything beyond stderr. */
|
||||
for (i = 3; i < FD_SETSIZE; i++)
|
||||
close(i);
|
||||
execv(main_args[0], main_args);
|
||||
err(1, "Could not exec %s", main_args[0]);
|
||||
}
|
||||
|
||||
/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves
|
||||
* its input and output, and finally, lays it to rest. */
|
||||
@@ -1523,6 +1542,9 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
|
||||
char reason[1024] = { 0 };
|
||||
read(lguest_fd, reason, sizeof(reason)-1);
|
||||
errx(1, "%s", reason);
|
||||
/* ERESTART means that we need to reboot the guest */
|
||||
} else if (errno == ERESTART) {
|
||||
restart_guest();
|
||||
/* EAGAIN means the Waker wanted us to look at some input.
|
||||
* Anything else means a bug or incompatible change. */
|
||||
} else if (errno != EAGAIN)
|
||||
@@ -1571,6 +1593,12 @@ int main(int argc, char *argv[])
|
||||
/* If they specify an initrd file to load. */
|
||||
const char *initrd_name = NULL;
|
||||
|
||||
/* Save the args: we "reboot" by execing ourselves again. */
|
||||
main_args = argv;
|
||||
/* We don't "wait" for the children, so prevent them from becoming
|
||||
* zombies. */
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
|
||||
/* First we initialize the device list. Since console and network
|
||||
* device receive input from a file descriptor, we keep an fdset
|
||||
* (infds) and the maximum fd number (max_infd) with the head of the
|
||||
|
||||
Reference in New Issue
Block a user