aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/lguest
diff options
context:
space:
mode:
authorBalaji Rao <balajirrao@gmail.com>2007-12-28 03:56:24 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-01-30 06:50:04 -0500
commitec04b13f67be3c90b38c625f4b8bdfea54c1ff60 (patch)
tree7819de21361fdd65487ef75ea9f2b774e4203f83 /Documentation/lguest
parent5c55841d16dbf7c759fa6fb2ecc5e615b86d17db (diff)
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>
Diffstat (limited to 'Documentation/lguest')
-rw-r--r--Documentation/lguest/lguest.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 9b0e322118b..86cac3e622a 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -153,6 +153,9 @@ struct virtqueue
153 void (*handle_output)(int fd, struct virtqueue *me); 153 void (*handle_output)(int fd, struct virtqueue *me);
154}; 154};
155 155
156/* Remember the arguments to the program so we can "reboot" */
157static char **main_args;
158
156/* Since guest is UP and we don't run at the same time, we don't need barriers. 159/* Since guest is UP and we don't run at the same time, we don't need barriers.
157 * But I include them in the code in case others copy it. */ 160 * But I include them in the code in case others copy it. */
158#define wmb() 161#define wmb()
@@ -1489,7 +1492,9 @@ static void setup_block_file(const char *filename)
1489 1492
1490 /* Create stack for thread and run it */ 1493 /* Create stack for thread and run it */
1491 stack = malloc(32768); 1494 stack = malloc(32768);
1492 if (clone(io_thread, stack + 32768, CLONE_VM, dev) == -1) 1495 /* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from
1496 * becoming a zombie. */
1497 if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1)
1493 err(1, "Creating clone"); 1498 err(1, "Creating clone");
1494 1499
1495 /* We don't need to keep the I/O thread's end of the pipes open. */ 1500 /* 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)
1499 verbose("device %u: virtblock %llu sectors\n", 1504 verbose("device %u: virtblock %llu sectors\n",
1500 devices.device_num, cap); 1505 devices.device_num, cap);
1501} 1506}
1502/* That's the end of device setup. */ 1507/* That's the end of device setup. :*/
1508
1509/* Reboot */
1510static void __attribute__((noreturn)) restart_guest(void)
1511{
1512 unsigned int i;
1513
1514 /* Closing pipes causes the waker thread and io_threads to die, and
1515 * closing /dev/lguest cleans up the Guest. Since we don't track all
1516 * open fds, we simply close everything beyond stderr. */
1517 for (i = 3; i < FD_SETSIZE; i++)
1518 close(i);
1519 execv(main_args[0], main_args);
1520 err(1, "Could not exec %s", main_args[0]);
1521}
1503 1522
1504/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves 1523/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves
1505 * its input and output, and finally, lays it to rest. */ 1524 * its input and output, and finally, lays it to rest. */
@@ -1523,6 +1542,9 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
1523 char reason[1024] = { 0 }; 1542 char reason[1024] = { 0 };
1524 read(lguest_fd, reason, sizeof(reason)-1); 1543 read(lguest_fd, reason, sizeof(reason)-1);
1525 errx(1, "%s", reason); 1544 errx(1, "%s", reason);
1545 /* ERESTART means that we need to reboot the guest */
1546 } else if (errno == ERESTART) {
1547 restart_guest();
1526 /* EAGAIN means the Waker wanted us to look at some input. 1548 /* EAGAIN means the Waker wanted us to look at some input.
1527 * Anything else means a bug or incompatible change. */ 1549 * Anything else means a bug or incompatible change. */
1528 } else if (errno != EAGAIN) 1550 } else if (errno != EAGAIN)
@@ -1571,6 +1593,12 @@ int main(int argc, char *argv[])
1571 /* If they specify an initrd file to load. */ 1593 /* If they specify an initrd file to load. */
1572 const char *initrd_name = NULL; 1594 const char *initrd_name = NULL;
1573 1595
1596 /* Save the args: we "reboot" by execing ourselves again. */
1597 main_args = argv;
1598 /* We don't "wait" for the children, so prevent them from becoming
1599 * zombies. */
1600 signal(SIGCHLD, SIG_IGN);
1601
1574 /* First we initialize the device list. Since console and network 1602 /* First we initialize the device list. Since console and network
1575 * device receive input from a file descriptor, we keep an fdset 1603 * device receive input from a file descriptor, we keep an fdset
1576 * (infds) and the maximum fd number (max_infd) with the head of the 1604 * (infds) and the maximum fd number (max_infd) with the head of the