aboutsummaryrefslogtreecommitdiffstats
path: root/tools/console
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-04-22 10:34:55 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-04-22 10:34:55 +0100
commitfd6c8de67e0d2199daf396005c1763d3bef4b1e5 (patch)
tree355a759975e36d6afdab6293bf3160cf1c7d0cc4 /tools/console
parent978e9bef8c3db26dc2bd502fbcde8be043748995 (diff)
downloadxen-fd6c8de67e0d2199daf396005c1763d3bef4b1e5.tar.gz
xen-fd6c8de67e0d2199daf396005c1763d3bef4b1e5.tar.bz2
xen-fd6c8de67e0d2199daf396005c1763d3bef4b1e5.zip
console: Provide option to stall the inter-domain console ring rather
than discard characters in the console daemon buffers. New option: -o, --overflow-data=discard|keep This option changes the behaviour when dealing with data that overflow the max capacity of the buffer. If overflow-data is set to discard (the default), the current behaviour is used: we discard some data in the middle of the buffer. If overflow-data is set to keep, we stop listening to the ring until we free some space in the buffer. This can cause the ring to fill up and the guest kernel internal buffer to fill up as well. When this happens the guest kernel stops reading characters from the console device so the application generating data hangs. When xenconsoled resumes reading from the ring, the guest kernel will be able to resume reading from the console device as well. At that point the guest application will be allowed to continue. The risk of making this behaviour the default is that existing kernel drivers may assume they can rely on timely ring updates by the console daemon and thus themselves block on the ring being emptied. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'tools/console')
-rw-r--r--tools/console/daemon/io.c18
-rw-r--r--tools/console/daemon/main.c13
2 files changed, 25 insertions, 6 deletions
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 5d4d7877bb..66db0f89cb 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -63,6 +63,7 @@ extern int log_hv;
extern int log_time_hv;
extern int log_time_guest;
extern char *log_dir;
+extern int discard_overflowed_data;
static int log_time_hv_needts = 1;
static int log_time_guest_needts = 1;
@@ -201,7 +202,7 @@ static void buffer_append(struct domain *dom)
dom->domid, errno, strerror(errno));
}
- if (buffer->max_capacity &&
+ if (discard_overflowed_data && buffer->max_capacity &&
buffer->size > buffer->max_capacity) {
/* Discard the middle of the data. */
@@ -228,6 +229,11 @@ static void buffer_advance(struct buffer *buffer, size_t len)
if (buffer->consumed == buffer->size) {
buffer->consumed = 0;
buffer->size = 0;
+ if (buffer->max_capacity &&
+ buffer->capacity > buffer->max_capacity) {
+ buffer->data = realloc(buffer->data, buffer->max_capacity);
+ buffer->capacity = buffer->max_capacity;
+ }
}
}
@@ -1005,9 +1011,13 @@ void handle_io(void)
d->next_period < next_timeout)
next_timeout = d->next_period;
} else if (d->xce_handle != -1) {
- int evtchn_fd = xc_evtchn_fd(d->xce_handle);
- FD_SET(evtchn_fd, &readfds);
- max_fd = MAX(evtchn_fd, max_fd);
+ if (discard_overflowed_data ||
+ !d->buffer.max_capacity ||
+ d->buffer.size < d->buffer.max_capacity) {
+ int evtchn_fd = xc_evtchn_fd(d->xce_handle);
+ FD_SET(evtchn_fd, &readfds);
+ max_fd = MAX(evtchn_fd, max_fd);
+ }
}
if (d->master_fd != -1) {
diff --git a/tools/console/daemon/main.c b/tools/console/daemon/main.c
index c66642ff46..c1529d0ac2 100644
--- a/tools/console/daemon/main.c
+++ b/tools/console/daemon/main.c
@@ -38,6 +38,7 @@ int log_hv = 0;
int log_time_hv = 0;
int log_time_guest = 0;
char *log_dir = NULL;
+int discard_overflowed_data = 1;
static void handle_hup(int sig)
{
@@ -46,7 +47,7 @@ static void handle_hup(int sig)
static void usage(char *name)
{
- printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH] [-t, --timestamp=none|guest|hv|all]\n", name);
+ printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH] [-t, --timestamp=none|guest|hv|all] [-o, --overflow-data=discard|keep]\n", name);
}
static void version(char *name)
@@ -56,7 +57,7 @@ static void version(char *name)
int main(int argc, char **argv)
{
- const char *sopts = "hVvit:";
+ const char *sopts = "hVvit:o:";
struct option lopts[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
@@ -66,6 +67,7 @@ int main(int argc, char **argv)
{ "log-dir", 1, 0, 'r' },
{ "pid-file", 1, 0, 'p' },
{ "timestamp", 1, 0, 't' },
+ { "overflow-data", 1, 0, 'o'},
{ 0 },
};
bool is_interactive = false;
@@ -119,6 +121,13 @@ int main(int argc, char **argv)
log_time_hv = 0;
}
break;
+ case 'o':
+ if (!strcmp(optarg, "keep")) {
+ discard_overflowed_data = 0;
+ } else if (!strcmp(optarg, "discard")) {
+ discard_overflowed_data = 1;
+ }
+ break;
case '?':
fprintf(stderr,
"Try `%s --help' for more information\n",