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

[PATCH 03/12] tools/xenstore: add framework to commit accounting data on success only



Instead of modifying accounting data and undo those modifications in
case of an error during further processing, add a framework for
collecting the needed changes and commit them only when the whole
operation has succeeded.

This scheme can reuse large parts of the per transaction accounting.
The changed_domain handling can be reused, but the array size of the
accounting data should be possible to be different for both use cases.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 tools/xenstore/xenstored_core.c   |  5 +++
 tools/xenstore/xenstored_core.h   |  3 ++
 tools/xenstore/xenstored_domain.c | 61 ++++++++++++++++++++++++++++---
 tools/xenstore/xenstored_domain.h |  5 ++-
 4 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index ea0e6292d3..d437149622 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -1027,6 +1027,9 @@ static void send_error(struct connection *conn, int error)
                        break;
                }
        }
+
+       acc_drop(conn);
+
        send_reply(conn, XS_ERROR, xsd_errors[i].errstring,
                          strlen(xsd_errors[i].errstring) + 1);
 }
@@ -1064,6 +1067,7 @@ void send_reply(struct connection *conn, enum 
xsd_sockmsg_type type,
        }
 
        conn->in = NULL;
+       acc_commit(conn);
 
        /* Update relevant header fields and fill in the message body. */
        bdata->hdr.msg.type = type;
@@ -2186,6 +2190,7 @@ struct connection *new_connection(const struct 
interface_funcs *funcs)
        new->is_stalled = false;
        new->transaction_started = 0;
        INIT_LIST_HEAD(&new->out_list);
+       INIT_LIST_HEAD(&new->acc_list);
        INIT_LIST_HEAD(&new->ref_list);
        INIT_LIST_HEAD(&new->watches);
        INIT_LIST_HEAD(&new->transaction_list);
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index c85b15515c..8223a49354 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -139,6 +139,9 @@ struct connection
        struct list_head out_list;
        uint64_t timeout_msec;
 
+       /* Not yet committed accounting data (valid if in != NULL). */
+       struct list_head acc_list;
+
        /* Referenced requests no longer pending. */
        struct list_head ref_list;
 
diff --git a/tools/xenstore/xenstored_domain.c 
b/tools/xenstore/xenstored_domain.c
index 9591a19189..7988125f71 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -100,7 +100,7 @@ struct changed_domain
        unsigned int domid;
 
        /* Accounting data. */
-       int acc[ACC_TR_N];
+       int acc[];
 };
 
 static struct hashtable *domhash;
@@ -585,6 +585,7 @@ static struct changed_domain 
*acc_find_changed_domain(struct list_head *head,
 
 static struct changed_domain *acc_get_changed_domain(const void *ctx,
                                                     struct list_head *head,
+                                                    unsigned int acc_sz,
                                                     unsigned int domid)
 {
        struct changed_domain *cd;
@@ -593,7 +594,7 @@ static struct changed_domain *acc_get_changed_domain(const 
void *ctx,
        if (cd)
                return cd;
 
-       cd = talloc_zero(ctx, struct changed_domain);
+       cd = talloc_zero_size(ctx, sizeof(*cd) + acc_sz * sizeof(cd->acc[0]));
        if (!cd)
                return NULL;
 
@@ -604,11 +605,12 @@ static struct changed_domain 
*acc_get_changed_domain(const void *ctx,
 }
 
 static int acc_add_changed_dom(const void *ctx, struct list_head *head,
-                              unsigned int what, int val, unsigned int domid)
+                              unsigned int acc_sz, unsigned int what,
+                              int val, unsigned int domid)
 {
        struct changed_domain *cd;
 
-       cd = acc_get_changed_domain(ctx, head, domid);
+       cd = acc_get_changed_domain(ctx, head, acc_sz, domid);
        if (!cd)
                return 0;
 
@@ -1067,6 +1069,7 @@ static int domain_acc_add(struct connection *conn, 
unsigned int domid,
                          unsigned int what, int add, bool dom_exists)
 {
        struct domain *d;
+       struct changed_domain *cd;
        struct list_head *head;
        int ret;
 
@@ -1087,10 +1090,26 @@ static int domain_acc_add(struct connection *conn, 
unsigned int domid,
                }
        }
 
+       /* Temporary accounting data until final commit? */
+       if (conn && conn->in && what < ACC_REQ_N) {
+               /* Consider transaction local data. */
+               ret = 0;
+               if (conn->transaction && what < ACC_TR_N) {
+                       head = transaction_get_changed_domains(
+                               conn->transaction);
+                       cd = acc_find_changed_domain(head, domid);
+                       if (cd)
+                               ret = cd->acc[what];
+               }
+               ret += acc_add_changed_dom(conn->in, &conn->acc_list, ACC_REQ_N,
+                                         what, add, domid);
+               return errno ? -1 : domain_acc_add_chk(d, what, ret, domid);
+       }
+
        if (conn && conn->transaction && what < ACC_TR_N) {
                head = transaction_get_changed_domains(conn->transaction);
-               ret = acc_add_changed_dom(conn->transaction, head, what,
-                                         add, domid);
+               ret = acc_add_changed_dom(conn->transaction, head, ACC_TR_N,
+                                         what, add, domid);
                if (errno) {
                        fail_transaction(conn->transaction);
                        return -1;
@@ -1103,6 +1122,36 @@ static int domain_acc_add(struct connection *conn, 
unsigned int domid,
        return d->acc[what];
 }
 
+void acc_drop(struct connection *conn)
+{
+       struct changed_domain *cd;
+
+       while ((cd = list_top(&conn->acc_list, struct changed_domain, list))) {
+               list_del(&cd->list);
+               talloc_free(cd);
+       }
+}
+
+void acc_commit(struct connection *conn)
+{
+       struct changed_domain *cd;
+       struct buffered_data *in = conn->in;
+       unsigned int what;
+
+       conn->in = NULL; /* Avoid recursion. */
+       while ((cd = list_top(&conn->acc_list, struct changed_domain, list))) {
+               list_del(&cd->list);
+               for (what = 0; what < ACC_REQ_N; what++)
+                       if (cd->acc[what])
+                               domain_acc_add(conn, cd->domid, what,
+                                              cd->acc[what], true);
+
+               talloc_free(cd);
+       }
+
+       conn->in = in;
+}
+
 int domain_nbentry_inc(struct connection *conn, unsigned int domid)
 {
        return (domain_acc_add(conn, domid, ACC_NODES, 1, false) < 0)
diff --git a/tools/xenstore/xenstored_domain.h 
b/tools/xenstore/xenstored_domain.h
index d2563d33e7..9959b2f2e4 100644
--- a/tools/xenstore/xenstored_domain.h
+++ b/tools/xenstore/xenstored_domain.h
@@ -20,7 +20,8 @@
 #define _XENSTORED_DOMAIN_H
 
 enum {
-       ACC_NODES,
+       ACC_REQ_N,       /* Number of elements per request and domain. */
+       ACC_NODES = ACC_REQ_N,
        ACC_TR_N,        /* Number of elements per transaction and domain. */
        ACC_N = ACC_TR_N /* Number of elements per domain. */
 };
@@ -103,6 +104,8 @@ void domain_outstanding_domid_dec(unsigned int domid);
 int domain_get_quota(const void *ctx, struct connection *conn,
                     unsigned int domid);
 int acc_fix_domains(struct list_head *head, bool update);
+void acc_drop(struct connection *conn);
+void acc_commit(struct connection *conn);
 
 /* Write rate limiting */
 
-- 
2.35.3




 


Rackspace

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