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

[PATCH 04/11] tools/xenstored: add GLOBAL_QUOTA_DATA record for live update



Communicate the global quota settings via the GLOBAL_QUOTA_DATA
record to the new Xenstore instance.

This avoids to lose global quota settings done via xenstore-control.

In theory it would be possible to drop any quota related command line
parameters in the live update case, but they don't do any harm, as
the record data is applied on top of the command line data.

For soft-quota just prepend "soft-" to the quota name.

Use sub-functions for building and analyzing the quota part of the
migration stream, as they will be reused for per-domain quotas.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 tools/xenstored/domain.c | 123 +++++++++++++++++++++++++++++++++++++++
 tools/xenstored/domain.h |   2 +
 tools/xenstored/lu.c     |   6 ++
 3 files changed, 131 insertions(+)

diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c
index acdcaa769e..694ae58973 100644
--- a/tools/xenstored/domain.c
+++ b/tools/xenstored/domain.c
@@ -1332,6 +1332,27 @@ int do_set_feature(const void *ctx, struct connection 
*conn,
        return 0;
 }
 
+static bool parse_quota_name(const char *name, unsigned int *qidx,
+                            unsigned int *idx)
+{
+       unsigned int q;
+
+       if (strncmp(name, "soft-", 5)) {
+               *idx = Q_IDX_HARD;
+       } else {
+               *idx = Q_IDX_SOFT;
+               name += 5;
+       }
+       for (q = 0; q < ACC_N; q++) {
+               if (quota_adm[q].name && !strcmp(quota_adm[q].name, name)) {
+                       *qidx = q;
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 static int close_xgt_handle(void *_handle)
 {
        xengnttab_close(*(xengnttab_handle **)_handle);
@@ -2001,6 +2022,61 @@ void read_state_connection(const void *ctx, const void 
*state)
        }
 }
 
+static unsigned int get_quota_size(struct quota *quota, unsigned int *len)
+{
+       unsigned int q;
+       unsigned int n = 0;
+
+       for (q = 0; q < ACC_N; q++) {
+               if (!quota_adm[q].name)
+                       continue;
+               if (quota[q].val[Q_IDX_HARD] != Q_VAL_DISABLED) {
+                       n++;
+                       *len += strlen(quota_adm[q].name) + 1;
+               }
+               if (quota[q].val[Q_IDX_SOFT] != Q_VAL_DISABLED) {
+                       n++;
+                       *len += strlen(quota_adm[q].name) + 5 + 1;
+               }
+       }
+
+       return n;
+}
+
+static void build_quota_data(struct quota *quota, uint32_t *val, char *name)
+{
+       unsigned int q;
+       unsigned int n = 0;
+
+       for (q = 0; q < ACC_N; q++) {
+               if (!quota_adm[q].name)
+                       continue;
+               if (quota[q].val[Q_IDX_HARD] != Q_VAL_DISABLED) {
+                       val[n++] = quota[q].val[Q_IDX_HARD];
+                       strcpy(name, quota_adm[q].name);
+                       name += strlen(name) + 1;
+               }
+               if (quota[q].val[Q_IDX_SOFT] != Q_VAL_DISABLED) {
+                       val[n++] = quota[q].val[Q_IDX_SOFT];
+                       strcpy(name, "soft-");
+                       strcpy(name + 5, quota_adm[q].name);
+                       name += strlen(name) + 1;
+               }
+       }
+}
+
+static void parse_quota_data(const uint32_t *val, const char *name,
+                            unsigned int n, struct quota *quota)
+{
+       unsigned int i, q, idx;
+
+       for (i = 0; i < n; i++) {
+               if (!parse_quota_name(name, &q, &idx))
+                       quota[q].val[idx] = val[i];
+               name += strlen(name) + 1;
+       }
+}
+
 static int dump_state_domain(const void *k, void *v, void *arg)
 {
        struct domain *domain = v;
@@ -2049,6 +2125,53 @@ void read_state_domain(const void *ctx, const void 
*state, unsigned int version)
                domain->features = sd->features;
 }
 
+const char *dump_state_glb_quota(FILE *fp)
+{
+       struct xs_state_record_header *head;
+       struct xs_state_glb_quota *glb;
+       void *record;
+       unsigned int n_quota;
+       unsigned int len = sizeof(*glb);
+       size_t ret;
+
+       n_quota = get_quota_size(quotas, &len);
+       len += n_quota * sizeof(glb->quota_val[0]);
+       len = ROUNDUP(len, 3);
+
+       record = talloc_size(NULL, len + sizeof(*head));
+       if (!record)
+               return "Dump global quota allocation error";
+
+       head = record;
+       head->type = XS_STATE_TYPE_GLB_QUOTA;
+       head->length = len;
+
+       glb = (struct xs_state_glb_quota *)(head + 1);
+       glb->n_dom_quota = n_quota;
+       glb->n_glob_quota = 0;
+
+       build_quota_data(quotas, glb->quota_val,
+                        (char *)(glb->quota_val + n_quota));
+
+       ret = fwrite(record, len + sizeof(*head), 1, fp);
+
+       talloc_free(record);
+
+       if (ret != 1 || dump_state_align(fp))
+               return "Dump global quota error";
+
+       return NULL;
+}
+
+void read_state_glb_quota(const void *ctx, const void *state)
+{
+       const struct xs_state_glb_quota *glb = state;
+       unsigned int n_quota = glb->n_dom_quota + glb->n_glob_quota;
+       const char *name = (const char *)(glb->quota_val + n_quota);
+
+       parse_quota_data(glb->quota_val, name, n_quota, quotas);
+}
+
 struct domain_acc {
        unsigned int domid;
        int nodes;
diff --git a/tools/xenstored/domain.h b/tools/xenstored/domain.h
index a6db358fdc..62ce3b3166 100644
--- a/tools/xenstored/domain.h
+++ b/tools/xenstored/domain.h
@@ -173,10 +173,12 @@ void wrl_apply_debit_trans_commit(struct connection 
*conn);
 
 const char *dump_state_connections(FILE *fp);
 const char *dump_state_domains(FILE *fp);
+const char *dump_state_glb_quota(FILE *fp);
 
 void read_state_connection(const void *ctx, const void *state);
 void read_state_domain(const void *ctx, const void *state,
                       unsigned int version);
+void read_state_glb_quota(const void *ctx, const void *state);
 
 struct hashtable *domain_check_acc_init(void);
 void domain_check_acc_add(const struct node *node, struct hashtable *domains);
diff --git a/tools/xenstored/lu.c b/tools/xenstored/lu.c
index fa8395eb1e..eaffdbc69e 100644
--- a/tools/xenstored/lu.c
+++ b/tools/xenstored/lu.c
@@ -192,6 +192,9 @@ void lu_read_state(void)
                case XS_STATE_TYPE_DOMAIN:
                        read_state_domain(ctx, state.buf, version);
                        break;
+               case XS_STATE_TYPE_GLB_QUOTA:
+                       read_state_glb_quota(ctx, state.buf);
+                       break;
                default:
                        xprintf("live-update: unknown state record %08x\n",
                                head.type);
@@ -319,6 +322,9 @@ static const char *lu_dump_state(const void *ctx, struct 
connection *conn)
        }
 
        ret = dump_state_global(fp);
+       if (ret)
+               goto out;
+       ret = dump_state_glb_quota(fp);
        if (ret)
                goto out;
        ret = dump_state_connections(fp);
-- 
2.53.0




 


Rackspace

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