[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging-4.14] tools/xenstore: don't buffer multiple identical watch events



commit 83b9da9282488bfadaf322a592805b4421d9b60b
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Tue Sep 13 07:35:08 2022 +0200
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Nov 1 15:20:41 2022 +0000

    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@xxxxxxxx>
    Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx>
    (cherry picked from commit b5c0bdb96d33e18c324c13d8e33c08732d77eaa2)
---
 tools/xenstore/xenstored_core.c | 20 +++++++++++++++++++-
 tools/xenstore/xenstored_core.h |  3 +++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 2ed91d1329..c6f1d4189c 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -823,6 +823,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;
@@ -855,7 +856,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;
@@ -877,12 +878,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++;
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index edeaa96dd1..1eb6131fc8 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -51,6 +51,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;
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.14



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.