mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
tools/xenstore: don't buffer multiple identical watch events
A guest not reading its Xenstore response buffer fast enough might pile up lots of Xenstore watch events buffered. Reduce the generated load by dropping new events which already have an identical copy pending. The special events "@..." are excluded from that handling as there are known use cases where the handler is relying on each event to be sent individually. This is part of XSA-326. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Julien Grall <jgrall@amazon.com>
This commit is contained in:
1 parent
36de433a27
commit
b5c0bdb96d
2 files changed
+22
-1
No files matched your search
@@ -912,6 +912,7 @@ void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
|
||||
bdata->inhdr = true;
|
||||
bdata->used = 0;
|
||||
bdata->timeout_msec = 0;
|
||||
bdata->watch_event = false;
|
||||
|
||||
if (len <= DEFAULT_BUFFER_SIZE)
|
||||
bdata->buffer = bdata->default_buffer;
|
||||
@@ -944,7 +945,7 @@ void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
|
||||
void send_event(struct buffered_data *req, struct connection *conn,
|
||||
const char *path, const char *token)
|
||||
{
|
||||
struct buffered_data *bdata;
|
||||
struct buffered_data *bdata, *bd;
|
||||
unsigned int len;
|
||||
|
||||
len = strlen(path) + 1 + strlen(token) + 1;
|
||||
@@ -966,12 +967,29 @@ void send_event(struct buffered_data *req, struct connection *conn,
|
||||
bdata->hdr.msg.type = XS_WATCH_EVENT;
|
||||
bdata->hdr.msg.len = len;
|
||||
|
||||
/*
|
||||
* Check whether an identical event is pending already.
|
||||
* Special events are excluded from that check.
|
||||
*/
|
||||
if (path[0] != '@') {
|
||||
list_for_each_entry(bd, &conn->out_list, list) {
|
||||
if (bd->watch_event && bd->hdr.msg.len == len &&
|
||||
!memcmp(bdata->buffer, bd->buffer, len)) {
|
||||
trace("dropping duplicate watch %s %s for domain %u\n",
|
||||
path, token, conn->id);
|
||||
talloc_free(bdata);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout_watch_event_msec && domain_is_unprivileged(conn)) {
|
||||
bdata->timeout_msec = get_now_msec() + timeout_watch_event_msec;
|
||||
if (!conn->timeout_msec)
|
||||
conn->timeout_msec = bdata->timeout_msec;
|
||||
}
|
||||
|
||||
bdata->watch_event = true;
|
||||
bdata->pend.req = req;
|
||||
if (req)
|
||||
req->pend.ref.event_cnt++;
|
||||
|
||||
@@ -62,6 +62,9 @@ struct buffered_data
|
||||
/* Are we still doing the header? */
|
||||
bool inhdr;
|
||||
|
||||
/* Is this a watch event? */
|
||||
bool watch_event;
|
||||
|
||||
/* How far are we? */
|
||||
unsigned int used;
|
||||
|
||||
|
||||