diff options
Diffstat (limited to 'Documentation/lguest/lguest.c')
-rw-r--r-- | Documentation/lguest/lguest.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 9b0e322118b5..86cac3e622ab 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" */ | ||
157 | static 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 */ | ||
1510 | static 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 |