# HG changeset patch
# User Roger Pau Monne <roger.pau@xxxxxxxxxxxxx>
# Date 1318503503 -7200
# Node ID 72ef13cb4609c97a26efd4931e65c9798fe22572
# Parent 64f17c7e6c33e5f1c22711ae9cbdcbe191c20062
libxl: reimplement buffer for bootloading and drop data if buffer is full.
Implement a buffer for the bootloading process that appends data to the end
until it's full. Drop output from bootloader if a timeout has occurred and the
buffer is full. Prevents the bootloader from getting stuck when using ptys with
small buffers.
Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxxxxx>
diff -r 64f17c7e6c33 -r 72ef13cb4609 tools/libxl/libxl_bootloader.c
--- a/tools/libxl/libxl_bootloader.c Tue Oct 11 10:26:32 2011 +0200
+++ b/tools/libxl/libxl_bootloader.c Thu Oct 13 12:58:23 2011 +0200
@@ -21,6 +21,7 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#include "libxl.h"
#include "libxl_internal.h"
@@ -28,7 +29,8 @@
#include "flexarray.h"
#define XENCONSOLED_BUF_SIZE 16
-#define BOOTLOADER_BUF_SIZE 1024
+#define BOOTLOADER_BUF_SIZE 4096
+#define BOOTLOADER_TIMEOUT 1
static char **make_bootloader_args(libxl__gc *gc,
libxl_domain_build_info *info,
@@ -165,10 +167,11 @@ static pid_t fork_exec_bootloader(int *m
*/
static char * bootloader_interact(libxl__gc *gc, int xenconsoled_fd, int
bootloader_fd, int fifo_fd)
{
- int ret;
+ int ret, read_ahead, timeout;
size_t nr_out = 0, size_out = 0;
char *output = NULL;
+ struct timeval wait;
/* input from xenconsole. read on xenconsoled_fd write to bootloader_fd */
int xenconsoled_prod = 0, xenconsoled_cons = 0;
@@ -181,39 +184,64 @@ static char * bootloader_interact(libxl_
fd_set wsel, rsel;
int nfds;
+ /* Set timeout to 1s before starting to discard data */
+ wait.tv_sec = BOOTLOADER_TIMEOUT;
+ wait.tv_usec = 0;
+
if (xenconsoled_prod == xenconsoled_cons)
xenconsoled_prod = xenconsoled_cons = 0;
if (bootloader_prod == bootloader_cons)
bootloader_prod = bootloader_cons = 0;
+ /* Move buffers around to drop already consumed data */
+ if (xenconsoled_cons > 0) {
+ xenconsoled_prod -= xenconsoled_cons;
+ memmove(xenconsoled_buf, &xenconsoled_buf[xenconsoled_cons],
xenconsoled_prod);
+ xenconsoled_cons = 0;
+ }
+ if (bootloader_cons > 0) {
+ bootloader_prod -= bootloader_cons;
+ memmove(bootloader_buf, &bootloader_buf[bootloader_cons],
bootloader_prod);
+ bootloader_cons = 0;
+ }
FD_ZERO(&rsel);
FD_SET(fifo_fd, &rsel);
nfds = fifo_fd + 1;
- if (xenconsoled_prod == 0 || (xenconsoled_prod < BOOTLOADER_BUF_SIZE
&& xenconsoled_cons == 0)) {
+ if (xenconsoled_prod < XENCONSOLED_BUF_SIZE) {
FD_SET(xenconsoled_fd, &rsel);
nfds = xenconsoled_fd + 1 > nfds ? xenconsoled_fd + 1 : nfds;
}
- if (bootloader_prod == 0 || (bootloader_prod < BOOTLOADER_BUF_SIZE &&
bootloader_cons == 0)) {
+ if (bootloader_prod < BOOTLOADER_BUF_SIZE) {
FD_SET(bootloader_fd, &rsel);
nfds = bootloader_fd + 1 > nfds ? bootloader_fd + 1 : nfds;
}
FD_ZERO(&wsel);
- if (bootloader_prod != bootloader_cons) {
+ if (bootloader_prod > 0) {
FD_SET(xenconsoled_fd, &wsel);
nfds = xenconsoled_fd + 1 > nfds ? xenconsoled_fd + 1 : nfds;
}
- if (xenconsoled_prod != xenconsoled_cons) {
+ if (xenconsoled_prod > 0) {
FD_SET(bootloader_fd, &wsel);
nfds = bootloader_fd + 1 > nfds ? bootloader_fd + 1 : nfds;
}
- ret = select(nfds, &rsel, &wsel, NULL, NULL);
+ ret = select(nfds, &rsel, &wsel, NULL, &wait);
if (ret < 0)
goto out_err;
+ timeout = ret == 0 ? 1 : 0;
/* Input from xenconsole, read xenconsoled_fd, write bootloader_fd */
- if (FD_ISSET(xenconsoled_fd, &rsel)) {
+ if (FD_ISSET(xenconsoled_fd, &rsel) || timeout) {
+ if (xenconsoled_prod == XENCONSOLED_BUF_SIZE) {
+ if (ioctl(xenconsoled_fd, FIONREAD, &read_ahead) < 0)
+ goto out_err;
+ if (read_ahead >= XENCONSOLED_BUF_SIZE) /* The whole buffer
will be overwritten */
+ read_ahead = XENCONSOLED_BUF_SIZE;
+ else
+ memmove(xenconsoled_buf, &xenconsoled_buf[read_ahead],
XENCONSOLED_BUF_SIZE - read_ahead);
+ xenconsoled_prod -= read_ahead;
+ }
ret = read(xenconsoled_fd, &xenconsoled_buf[xenconsoled_prod],
XENCONSOLED_BUF_SIZE - xenconsoled_prod);
if (ret < 0 && errno != EIO && errno != EAGAIN)
goto out_err;
@@ -229,7 +257,16 @@ static char * bootloader_interact(libxl_
}
/* Input from bootloader, read bootloader_fd, write xenconsoled_fd */
- if (FD_ISSET(bootloader_fd, &rsel)) {
+ if (FD_ISSET(bootloader_fd, &rsel) || timeout) {
+ if (bootloader_prod == BOOTLOADER_BUF_SIZE) {
+ if (ioctl(bootloader_fd, FIONREAD, &read_ahead) < 0)
+ goto out_err;
+ if (read_ahead >= BOOTLOADER_BUF_SIZE) /* The whole buffer
will be overwritten */
+ read_ahead = BOOTLOADER_BUF_SIZE;
+ else
+ memmove(bootloader_buf, &bootloader_buf[read_ahead],
BOOTLOADER_BUF_SIZE - read_ahead);
+ bootloader_prod -= read_ahead;
+ }
ret = read(bootloader_fd, &bootloader_buf[bootloader_prod],
BOOTLOADER_BUF_SIZE - bootloader_prod);
if (ret < 0 && errno != EIO && errno != EAGAIN)
goto out_err;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|