@@ -91,6 +91,18 @@ struct domain
bool wrl_delay_logged;
};
+struct changed_domain
+{
+ /* List of all changed domains. */
+ struct list_head list;
+
+ /* Identifier of the changed domain. */
+ unsigned int domid;
+
+ /* Amount by which this domain's nbentry field has changed. */
+ int nbentry;
+};
+
static struct hashtable *domhash;
static bool check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
@@ -543,6 +555,72 @@ static struct domain *find_domain_by_domid(unsigned int domid)
return (d && d->introduced) ? d : NULL;
}
+int acc_fix_domains(struct list_head *head, bool update)
+{
+ struct changed_domain *cd;
+ int cnt;
+
+ list_for_each_entry(cd, head, list) {
+ cnt = domain_entry_fix(cd->domid, cd->nbentry, update);
+ if (!update) {
+ if (cnt >= quota_nb_entry_per_domain)
+ return ENOSPC;
+ if (cnt < 0)
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static struct changed_domain *acc_find_changed_domain(struct list_head *head,
+ unsigned int domid)
+{
+ struct changed_domain *cd;
+
+ list_for_each_entry(cd, head, list) {
+ if (cd->domid == domid)
+ return cd;
+ }
+
+ return NULL;
+}
+
+static struct changed_domain *acc_get_changed_domain(const void *ctx,
+ struct list_head *head,
+ unsigned int domid)
+{
+ struct changed_domain *cd;
+
+ cd = acc_find_changed_domain(head, domid);
+ if (cd)
+ return cd;
+
+ cd = talloc_zero(ctx, struct changed_domain);
+ if (!cd)
+ return NULL;
+
+ cd->domid = domid;
+ list_add_tail(&cd->list, head);
+
+ return cd;
+}
+
+int acc_add_dom_nbentry(const void *ctx, struct list_head *head, int val,
+ unsigned int domid)
+{
+ struct changed_domain *cd;
+
+ cd = acc_get_changed_domain(ctx, head, domid);
+ if (!cd)
+ return 0;
+
+ errno = 0;
+ cd->nbentry += val;
+
+ return cd->nbentry;
+}
+
static void domain_conn_reset(struct domain *domain)
{
struct connection *conn = domain->conn;
@@ -98,6 +98,9 @@ void domain_outstanding_dec(struct connection *conn);
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);
+int acc_add_dom_nbentry(const void *ctx, struct list_head *head, int val,
+ unsigned int domid);
/* Write rate limiting */
@@ -137,18 +137,6 @@ struct accessed_node
bool watch_exact;
};
-struct changed_domain
-{
- /* List of all changed domains in the context of this transaction. */
- struct list_head list;
-
- /* Identifier of the changed domain. */
- unsigned int domid;
-
- /* Amount by which this domain's nbentry field has changed. */
- int nbentry;
-};
-
struct transaction
{
/* List of all transactions active on this connection. */
@@ -514,24 +502,6 @@ int do_transaction_start(const void *ctx, struct connection *conn,
return 0;
}
-static int transaction_fix_domains(struct transaction *trans, bool update)
-{
- struct changed_domain *d;
- int cnt;
-
- list_for_each_entry(d, &trans->changed_domains, list) {
- cnt = domain_entry_fix(d->domid, d->nbentry, update);
- if (!update) {
- if (cnt >= quota_nb_entry_per_domain)
- return ENOSPC;
- if (cnt < 0)
- return ENOMEM;
- }
- }
-
- return 0;
-}
-
int do_transaction_end(const void *ctx, struct connection *conn,
struct buffered_data *in)
{
@@ -558,7 +528,7 @@ int do_transaction_end(const void *ctx, struct connection *conn,
if (streq(arg, "T")) {
if (trans->fail)
return ENOMEM;
- ret = transaction_fix_domains(trans, false);
+ ret = acc_fix_domains(&trans->changed_domains, false);
if (ret)
return ret;
ret = finalize_transaction(conn, trans, &is_corrupt);
@@ -568,7 +538,7 @@ int do_transaction_end(const void *ctx, struct connection *conn,
wrl_apply_debit_trans_commit(conn);
/* fix domain entry for each changed domain */
- transaction_fix_domains(trans, true);
+ acc_fix_domains(&trans->changed_domains, true);
if (is_corrupt)
corrupt(conn, "transaction inconsistency");
@@ -580,44 +550,18 @@ int do_transaction_end(const void *ctx, struct connection *conn,
void transaction_entry_inc(struct transaction *trans, unsigned int domid)
{
- struct changed_domain *d;
-
- list_for_each_entry(d, &trans->changed_domains, list)
- if (d->domid == domid) {
- d->nbentry++;
- return;
- }
-
- d = talloc(trans, struct changed_domain);
- if (!d) {
+ if (!acc_add_dom_nbentry(trans, &trans->changed_domains, 1, domid)) {
/* Let the transaction fail. */
trans->fail = true;
- return;
}
- d->domid = domid;
- d->nbentry = 1;
- list_add_tail(&d->list, &trans->changed_domains);
}
void transaction_entry_dec(struct transaction *trans, unsigned int domid)
{
- struct changed_domain *d;
-
- list_for_each_entry(d, &trans->changed_domains, list)
- if (d->domid == domid) {
- d->nbentry--;
- return;
- }
-
- d = talloc(trans, struct changed_domain);
- if (!d) {
+ if (!acc_add_dom_nbentry(trans, &trans->changed_domains, -1, domid)) {
/* Let the transaction fail. */
trans->fail = true;
- return;
}
- d->domid = domid;
- d->nbentry = -1;
- list_add_tail(&d->list, &trans->changed_domains);
}
void fail_transaction(struct transaction *trans)