@@ -69,8 +69,8 @@ struct domain
/* Has domain been officially introduced? */
bool introduced;
- /* number of entry from this domain in the store */
- int nbentry;
+ /* Accounting data for this domain. */
+ unsigned int acc[ACC_N];
/* Amount of memory allocated for this domain. */
int memory;
@@ -246,7 +246,7 @@ static int domain_tree_remove_sub(const void *ctx, struct connection *conn,
if (keep_orphans) {
set_tdb_key(node->name, &key);
- domain->nbentry--;
+ domain_nbentry_dec(NULL, domain->domid);
node->perms.p[0].id = priv_domid;
node->acc.memory = 0;
domain_nbentry_inc(NULL, priv_domid);
@@ -270,7 +270,7 @@ static int domain_tree_remove_sub(const void *ctx, struct connection *conn,
ret = WALK_TREE_SKIP_CHILDREN;
}
- return domain->nbentry > 0 ? ret : WALK_TREE_SUCCESS_STOP;
+ return domain->acc[ACC_NODES] ? ret : WALK_TREE_SUCCESS_STOP;
}
static void domain_tree_remove(struct domain *domain)
@@ -278,7 +278,7 @@ static void domain_tree_remove(struct domain *domain)
int ret;
struct walk_funcs walkfuncs = { .enter = domain_tree_remove_sub };
- if (domain->nbentry > 0) {
+ if (domain->acc[ACC_NODES]) {
ret = walk_node_tree(domain, NULL, "/", &walkfuncs, domain);
if (ret == WALK_TREE_ERROR_STOP)
syslog(LOG_ERR,
@@ -441,7 +441,7 @@ int domain_get_quota(const void *ctx, struct connection *conn,
resp = talloc_asprintf_append(resp, "%-16s: %8d\n", #t, e); \
if (!resp) return ENOMEM
- ent(nodes, d->nbentry);
+ ent(nodes, d->acc[ACC_NODES]);
ent(watches, d->nbwatch);
ent(transactions, ta);
ent(outstanding, d->nboutstanding);
@@ -1050,8 +1050,21 @@ int domain_adjust_node_perms(struct node *node)
return 0;
}
-static int domain_nbentry_add(struct connection *conn, unsigned int domid,
- int add, bool dom_exists)
+static int domain_acc_add_chk(struct domain *d, unsigned int what, int add,
+ unsigned int domid)
+{
+ if ((add < 0 && -add > d->acc[what]) ||
+ (d->acc[what] + add) > INT_MAX) {
+ syslog(LOG_ERR, "Accounting error: domain %u type %u val %u\n",
+ domid, what, d->acc[what] + add);
+ return (add < 0) ? 0 : INT_MAX;
+ }
+
+ return d->acc[what] + add;
+}
+
+static int domain_acc_add(struct connection *conn, unsigned int domid,
+ unsigned int what, int add, bool dom_exists)
{
struct domain *d;
struct list_head *head;
@@ -1074,47 +1087,49 @@ static int domain_nbentry_add(struct connection *conn, unsigned int domid,
}
}
- if (conn && conn->transaction) {
+ if (conn && conn->transaction && what < ACC_TR_N) {
head = transaction_get_changed_domains(conn->transaction);
- ret = acc_add_changed_dom(conn->transaction, head, ACC_NODES,
+ ret = acc_add_changed_dom(conn->transaction, head, what,
add, domid);
if (errno) {
fail_transaction(conn->transaction);
return -1;
}
- return d->nbentry + ret;
+ return domain_acc_add_chk(d, what, ret, domid);
}
- d->nbentry += add;
+ d->acc[what] = domain_acc_add_chk(d, what, add, domid);
- return d->nbentry;
+ return d->acc[what];
}
int domain_nbentry_inc(struct connection *conn, unsigned int domid)
{
- return (domain_nbentry_add(conn, domid, 1, false) < 0) ? errno : 0;
+ return (domain_acc_add(conn, domid, ACC_NODES, 1, false) < 0)
+ ? errno : 0;
}
int domain_nbentry_dec(struct connection *conn, unsigned int domid)
{
- return (domain_nbentry_add(conn, domid, -1, true) < 0) ? errno : 0;
+ return (domain_acc_add(conn, domid, ACC_NODES, -1, true) < 0)
+ ? errno : 0;
}
int domain_nbentry_fix(unsigned int domid, int num, bool update)
{
int ret;
- ret = domain_nbentry_add(NULL, domid, update ? num : 0, update);
+ ret = domain_acc_add(NULL, domid, ACC_NODES, update ? num : 0, update);
if (ret < 0 || update)
return ret;
return domid_is_unprivileged(domid) ? ret + num : 0;
}
-int domain_nbentry(struct connection *conn)
+unsigned int domain_nbentry(struct connection *conn)
{
return domain_is_unprivileged(conn)
- ? domain_nbentry_add(conn, conn->id, 0, true) : 0;
+ ? domain_acc_add(conn, conn->id, ACC_NODES, 0, true) : 0;
}
static bool domain_chk_quota(struct domain *domain, int mem)
@@ -1591,7 +1606,7 @@ static int domain_check_acc_init_sub(void *k, void *v, void *arg)
* If everything is correct incrementing the value for each node will
* result in dom->nodes being 0 at the end.
*/
- dom->nodes = -d->nbentry;
+ dom->nodes = -d->acc[ACC_NODES];
if (!hashtable_insert(domains, &dom->domid, dom)) {
talloc_free(dom);
@@ -1646,7 +1661,7 @@ static int domain_check_acc_sub(void *k, void *v, void *arg)
if (!d)
return 0;
- d->nbentry += dom->nodes;
+ d->acc[ACC_NODES] += dom->nodes;
return 0;
}
@@ -21,7 +21,8 @@
enum {
ACC_NODES,
- ACC_TR_N /* Number of elements per transaction and domain. */
+ ACC_TR_N, /* Number of elements per transaction and domain. */
+ ACC_N = ACC_TR_N /* Number of elements per domain. */
};
void handle_event(void);
@@ -72,7 +73,7 @@ int domain_alloc_permrefs(struct node_perms *perms);
int domain_nbentry_inc(struct connection *conn, unsigned int domid);
int domain_nbentry_dec(struct connection *conn, unsigned int domid);
int domain_nbentry_fix(unsigned int domid, int num, bool update);
-int domain_nbentry(struct connection *conn);
+unsigned int domain_nbentry(struct connection *conn);
int domain_memory_add(unsigned int domid, int mem, bool no_quota_check);
/*
Introduce the scheme of an accounting data array for per-domain accounting data and use it initially for the number of nodes owned by a domain. Make the accounting data type to be unsigned int, as no data is allowed to be negative at any time. Signed-off-by: Juergen Gross <jgross@suse.com> --- tools/xenstore/xenstored_domain.c | 55 ++++++++++++++++++++----------- tools/xenstore/xenstored_domain.h | 5 +-- 2 files changed, 38 insertions(+), 22 deletions(-)