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

[xen staging] tools/xenstore: add support for delaying execution of a xenstore request



commit c5ca1404b47edef53a6b1245574ee9712404c5d4
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Thu Jan 14 12:41:32 2021 +0100
Commit:     Juergen Gross <jgross@xxxxxxxx>
CommitDate: Thu Jan 21 17:30:58 2021 +0100

    tools/xenstore: add support for delaying execution of a xenstore request
    
    Today a Xenstore request is processed as soon as it is seen by
    xenstored. Add the framework for being able to delay processing of a
    request if the right conditions aren't met.
    
    Any delayed requests are executed at the end of the main processing
    loop in xenstored. They can either delay themselves again or just do
    their job. In order to enable the possibility of a timeout, the main
    loop will be paused for max one second if any requests are delayed.
    
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
    Acked-by: Wei Liu <wl@xxxxxxx>
---
 tools/xenstore/xenstored_core.c | 62 ++++++++++++++++++++++++++++++++++++++++-
 tools/xenstore/xenstored_core.h | 21 ++++++++++++++
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 0dddf24327..6f556d49ef 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -69,6 +69,7 @@ static int xce_pollfd_idx = -1;
 static struct pollfd *fds;
 static unsigned int current_array_size;
 static unsigned int nr_fds;
+static unsigned int delayed_requests;
 
 static int sock = -1;
 
@@ -255,6 +256,53 @@ static bool write_messages(struct connection *conn)
        return true;
 }
 
+static int undelay_request(void *_req)
+{
+       struct delayed_request *req = _req;
+
+       list_del(&req->list);
+       delayed_requests--;
+
+       return 0;
+}
+
+static void call_delayed(struct connection *conn, struct delayed_request *req)
+{
+       assert(conn->in == NULL);
+       conn->in = req->in;
+
+       if (req->func(req)) {
+               undelay_request(req);
+               talloc_set_destructor(req, NULL);
+       }
+
+       conn->in = NULL;
+}
+
+int delay_request(struct connection *conn, struct buffered_data *in,
+                 bool (*func)(struct delayed_request *), void *data)
+{
+       struct delayed_request *req;
+
+       req = talloc(in, struct delayed_request);
+       if (!req)
+               return ENOMEM;
+
+       /* For the case of connection being closed. */
+       talloc_set_destructor(req, undelay_request);
+
+       req->in = in;
+       req->func = func;
+       req->data = data;
+
+       delayed_requests++;
+       list_add(&req->list, &conn->delayed);
+
+       conn->in = NULL;
+
+       return 0;
+}
+
 static int destroy_conn(void *_conn)
 {
        struct connection *conn = _conn;
@@ -321,7 +369,8 @@ static void initialize_fds(int *p_sock_pollfd_idx, int 
*ptimeout)
                memset(fds, 0, sizeof(struct pollfd) * current_array_size);
        nr_fds = 0;
 
-       *ptimeout = -1;
+       /* In case of delayed requests pause for max 1 second. */
+       *ptimeout = delayed_requests ? 1000 : -1;
 
        if (sock != -1)
                *p_sock_pollfd_idx = set_fd(sock, POLLIN|POLLPRI);
@@ -1524,6 +1573,7 @@ struct connection *new_connection(connwritefn_t *write, 
connreadfn_t *read)
        INIT_LIST_HEAD(&new->out_list);
        INIT_LIST_HEAD(&new->watches);
        INIT_LIST_HEAD(&new->transaction_list);
+       INIT_LIST_HEAD(&new->delayed);
 
        list_add_tail(&new->list, &connections);
        talloc_set_destructor(new, destroy_conn);
@@ -2215,6 +2265,16 @@ int main(int argc, char *argv[])
                        }
                }
 
+               if (delayed_requests) {
+                       list_for_each_entry(conn, &connections, list) {
+                               struct delayed_request *req, *tmp;
+
+                               list_for_each_entry_safe(req, tmp,
+                                                        &conn->delayed, list)
+                                       call_delayed(conn, req);
+                       }
+               }
+
                initialize_fds(&sock_pollfd_idx, &timeout);
        }
 }
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index 27826c125c..d5cdf17160 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -61,6 +61,20 @@ struct buffered_data
        char default_buffer[DEFAULT_BUFFER_SIZE];
 };
 
+struct delayed_request {
+       /* Next delayed request. */
+       struct list_head list;
+
+       /* The delayed request. */
+       struct buffered_data *in;
+
+       /* Function to call. */
+       bool (*func)(struct delayed_request *req);
+
+       /* Further data. */
+       void *data;
+};
+
 struct connection;
 typedef int connwritefn_t(struct connection *, const void *, unsigned int);
 typedef int connreadfn_t(struct connection *, void *, unsigned int);
@@ -94,6 +108,9 @@ struct connection
        uint32_t next_transaction_id;
        unsigned int transaction_started;
 
+       /* List of delayed requests. */
+       struct list_head delayed;
+
        /* The domain I'm associated with, if any. */
        struct domain *domain;
 
@@ -177,6 +194,10 @@ bool is_valid_nodename(const char *node);
 /* Get name of parent node. */
 char *get_parent(const void *ctx, const char *node);
 
+/* Delay a request. */
+int delay_request(struct connection *conn, struct buffered_data *in,
+                 bool (*func)(struct delayed_request *), void *data);
+
 /* Tracing infrastructure. */
 void trace_create(const void *data, const char *type);
 void trace_destroy(const void *data, const char *type);
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

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