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

[xen staging-4.14] tools/xenstore: split up send_reply()



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

    tools/xenstore: split up send_reply()
    
    Today send_reply() is used for both, normal request replies and watch
    events.
    
    Split it up into send_reply() and send_event(). This will be used to
    add some event specific handling.
    
    add_event() can be merged into send_event(), removing the need for an
    intermediate memory allocation.
    
    This is part of XSA-326.
    
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
    Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx>
    (cherry picked from commit 9bfde319dbac2a1321898d2f75a3f075c3eb7b32)
---
 tools/xenstore/xenstored_core.c  | 74 ++++++++++++++++++++++++----------------
 tools/xenstore/xenstored_core.h  |  1 +
 tools/xenstore/xenstored_watch.c | 42 +++++++----------------
 3 files changed, 58 insertions(+), 59 deletions(-)

diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 8e91b55498..e6776bae8f 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -674,49 +674,32 @@ static void send_error(struct connection *conn, int error)
 void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
                const void *data, unsigned int len)
 {
-       struct buffered_data *bdata;
+       struct buffered_data *bdata = conn->in;
+
+       assert(type != XS_WATCH_EVENT);
 
        if ( len > XENSTORE_PAYLOAD_MAX ) {
                send_error(conn, E2BIG);
                return;
        }
 
-       /* Replies reuse the request buffer, events need a new one. */
-       if (type != XS_WATCH_EVENT) {
-               bdata = conn->in;
-               /* Drop asynchronous responses, e.g. errors for watch events. */
-               if (!bdata)
-                       return;
-               bdata->inhdr = true;
-               bdata->used = 0;
-               conn->in = NULL;
-       } else {
-               /* Message is a child of the connection for auto-cleanup. */
-               bdata = new_buffer(conn);
+       if (!bdata)
+               return;
+       bdata->inhdr = true;
+       bdata->used = 0;
 
-               /*
-                * Allocation failure here is unfortunate: we have no way to
-                * tell anybody about it.
-                */
-               if (!bdata)
-                       return;
-       }
        if (len <= DEFAULT_BUFFER_SIZE)
                bdata->buffer = bdata->default_buffer;
-       else
+       else {
                bdata->buffer = talloc_array(bdata, char, len);
-       if (!bdata->buffer) {
-               if (type == XS_WATCH_EVENT) {
-                       /* Same as above: no way to tell someone. */
-                       talloc_free(bdata);
+               if (!bdata->buffer) {
+                       send_error(conn, ENOMEM);
                        return;
                }
-               /* re-establish request buffer for sending ENOMEM. */
-               conn->in = bdata;
-               send_error(conn, ENOMEM);
-               return;
        }
 
+       conn->in = NULL;
+
        /* Update relevant header fields and fill in the message body. */
        bdata->hdr.msg.type = type;
        bdata->hdr.msg.len = len;
@@ -724,8 +707,39 @@ void send_reply(struct connection *conn, enum 
xsd_sockmsg_type type,
 
        /* Queue for later transmission. */
        list_add_tail(&bdata->list, &conn->out_list);
+}
 
-       return;
+/*
+ * Send a watch event.
+ * As this is not directly related to the current command, errors can't be
+ * reported.
+ */
+void send_event(struct connection *conn, const char *path, const char *token)
+{
+       struct buffered_data *bdata;
+       unsigned int len;
+
+       len = strlen(path) + 1 + strlen(token) + 1;
+       /* Don't try to send over-long events. */
+       if (len > XENSTORE_PAYLOAD_MAX)
+               return;
+
+       bdata = new_buffer(conn);
+       if (!bdata)
+               return;
+
+       bdata->buffer = talloc_array(bdata, char, len);
+       if (!bdata->buffer) {
+               talloc_free(bdata);
+               return;
+       }
+       strcpy(bdata->buffer, path);
+       strcpy(bdata->buffer + strlen(path) + 1, token);
+       bdata->hdr.msg.type = XS_WATCH_EVENT;
+       bdata->hdr.msg.len = len;
+
+       /* Queue for later transmission. */
+       list_add_tail(&bdata->list, &conn->out_list);
 }
 
 /* Some routines (write, mkdir, etc) just need a non-error return */
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index 9369c4cbfd..2b0f796d9b 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -150,6 +150,7 @@ unsigned int get_strings(struct buffered_data *data,
 
 void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
                const void *data, unsigned int len);
+void send_event(struct connection *conn, const char *path, const char *token);
 
 /* Some routines (write, mkdir, etc) just need a non-error return */
 void send_ack(struct connection *conn, enum xsd_sockmsg_type type);
diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
index 9ff20690c0..6d8097376e 100644
--- a/tools/xenstore/xenstored_watch.c
+++ b/tools/xenstore/xenstored_watch.c
@@ -72,37 +72,17 @@ static bool is_child(const char *child, const char *parent)
        return child[len] == '/' || child[len] == '\0';
 }
 
-/*
- * Send a watch event.
- * Temporary memory allocations are done with ctx.
- */
-static void add_event(struct connection *conn,
-                     const void *ctx,
-                     struct watch *watch,
-                     const char *name)
+static const char *get_watch_path(const struct watch *watch, const char *name)
 {
-       /* Data to send (node\0token\0). */
-       unsigned int len;
-       char *data;
+       const char *path = name;
 
        if (watch->relative_path) {
-               name += strlen(watch->relative_path);
-               if (*name == '/') /* Could be "" */
-                       name++;
+               path += strlen(watch->relative_path);
+               if (*path == '/') /* Could be "" */
+                       path++;
        }
 
-       len = strlen(name) + 1 + strlen(watch->token) + 1;
-       /* Don't try to send over-long events. */
-       if (len > XENSTORE_PAYLOAD_MAX)
-               return;
-
-       data = talloc_array(ctx, char, len);
-       if (!data)
-               return;
-       strcpy(data, name);
-       strcpy(data + strlen(name) + 1, watch->token);
-       send_reply(conn, XS_WATCH_EVENT, data, len);
-       talloc_free(data);
+       return path;
 }
 
 /*
@@ -181,10 +161,14 @@ void fire_watches(struct connection *conn, const void 
*ctx, const char *name,
                list_for_each_entry(watch, &i->watches, list) {
                        if (exact) {
                                if (streq(name, watch->node))
-                                       add_event(i, ctx, watch, name);
+                                       send_event(i,
+                                                  get_watch_path(watch, name),
+                                                  watch->token);
                        } else {
                                if (is_child(name, watch->node))
-                                       add_event(i, ctx, watch, name);
+                                       send_event(i,
+                                                  get_watch_path(watch, name),
+                                                  watch->token);
                        }
                }
        }
@@ -252,7 +236,7 @@ int do_watch(struct connection *conn, struct buffered_data 
*in)
        send_ack(conn, XS_WATCH);
 
        /* We fire once up front: simplifies clients and restart. */
-       add_event(conn, in, watch, watch->node);
+       send_event(conn, get_watch_path(watch, watch->node), watch->token);
 
        return 0;
 }
--
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®.