#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "utils.h"
return 0;
}
+struct quota {
+ const char *name;
+ int *quota;
+ const char *descr;
+};
+
+static const struct quota hard_quotas[] = {
+ { "nodes", "a_nb_entry_per_domain, "Nodes per domain" },
+ { "watches", "a_nb_watch_per_domain, "Watches per domain" },
+ { "transactions", "a_max_transaction, "Transactions per domain" },
+ { "outstanding", "a_req_outstanding,
+ "Outstanding requests per domain" },
+ { "transaction-nodes", "a_trans_nodes,
+ "Max. number of accessed nodes per transaction" },
+ { "memory", "a_memory_per_domain_hard,
+ "Total Xenstore memory per domain (error level)" },
+ { "node-size", "a_max_entry_size, "Max. size of a node" },
+ { "permissions", "a_nb_perms_per_node,
+ "Max. number of permissions per node" },
+ { NULL, NULL, NULL }
+};
+
+static const struct quota soft_quotas[] = {
+ { "memory", "a_memory_per_domain_soft,
+ "Total Xenstore memory per domain (warning level)" },
+ { NULL, NULL, NULL }
+};
+
+static int quota_show_current(const void *ctx, struct connection *conn,
+ const struct quota *quotas)
+{
+ char *resp;
+ unsigned int i;
+
+ resp = talloc_strdup(ctx, "Quota settings:\n");
+ if (!resp)
+ return ENOMEM;
+
+ for (i = 0; quotas[i].quota; i++) {
+ resp = talloc_asprintf_append(resp, "%-17s: %8d %s\n",
+ quotas[i].name, *quotas[i].quota,
+ quotas[i].descr);
+ if (!resp)
+ return ENOMEM;
+ }
+
+ send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1);
+
+ return 0;
+}
+
+static int quota_set(const void *ctx, struct connection *conn,
+ char **vec, int num, const struct quota *quotas)
+{
+ unsigned int i;
+ int val;
+
+ if (num != 2)
+ return EINVAL;
+
+ val = atoi(vec[1]);
+ if (val < 1)
+ return EINVAL;
+
+ for (i = 0; quotas[i].quota; i++) {
+ if (!strcmp(vec[0], quotas[i].name)) {
+ *quotas[i].quota = val;
+ send_ack(conn, XS_CONTROL);
+ return 0;
+ }
+ }
+
+ return EINVAL;
+}
+
+static int quota_get(const void *ctx, struct connection *conn,
+ char **vec, int num)
+{
+ if (num != 1)
+ return EINVAL;
+
+ return domain_get_quota(ctx, conn, atoi(vec[0]));
+}
+
+static int do_control_quota(void *ctx, struct connection *conn,
+ char **vec, int num)
+{
+ if (num == 0)
+ return quota_show_current(ctx, conn, hard_quotas);
+
+ if (!strcmp(vec[0], "set"))
+ return quota_set(ctx, conn, vec + 1, num - 1, hard_quotas);
+
+ return quota_get(ctx, conn, vec, num);
+}
+
+static int do_control_quota_s(void *ctx, struct connection *conn,
+ char **vec, int num)
+{
+ if (num == 0)
+ return quota_show_current(ctx, conn, soft_quotas);
+
+ if (!strcmp(vec[0], "set"))
+ return quota_set(ctx, conn, vec + 1, num - 1, soft_quotas);
+
+ return EINVAL;
+}
+
static int do_control_memreport(void *ctx, struct connection *conn,
char **vec, int num)
{
{ "logfile", do_control_logfile, "<file>" },
{ "memreport", do_control_memreport, "[<file>]" },
{ "print", do_control_print, "<string>" },
+ { "quota", do_control_quota, "[set <name> <val>|<domid>]" },
+ { "quota-soft", do_control_quota_s, "[set <name> <val>]" },
{ "help", do_control_help, "" },
};
#include "xenstored_domain.h"
#include "xenstored_transaction.h"
#include "xenstored_watch.h"
+#include "xenstored_control.h"
#include <xenevtchn.h>
#include <xenctrl.h>
return NULL;
}
+int domain_get_quota(const void *ctx, struct connection *conn,
+ unsigned int domid)
+{
+ struct domain *d = find_domain_struct(domid);
+ char *resp;
+ int ta;
+
+ if (!d)
+ return ENOENT;
+
+ ta = d->conn ? d->conn->transaction_started : 0;
+ resp = talloc_asprintf(ctx, "Domain %u:\n", domid);
+ if (!resp)
+ return ENOMEM;
+
+#define ent(t, e) \
+ resp = talloc_asprintf_append(resp, "%-16s: %8d\n", #t, e); \
+ if (!resp) return ENOMEM
+
+ ent(nodes, d->nbentry);
+ ent(watches, d->nbwatch);
+ ent(transactions, ta);
+ ent(outstanding, d->nboutstanding);
+ ent(memory, d->memory);
+
+#undef ent
+
+ send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1);
+
+ return 0;
+}
+
static struct domain *alloc_domain(void *context, unsigned int domid)
{
struct domain *domain;