All of lore.kernel.org
 help / color / mirror / Atom feed
From: Juergen Gross <jgross@suse.com>
To: xen-devel@lists.xenproject.org
Cc: Juergen Gross <jgross@suse.com>, Wei Liu <wl@xen.org>,
	Julien Grall <julien@xen.org>,
	Anthony PERARD <anthony.perard@citrix.com>
Subject: [PATCH v2 06/19] tools/xenstore: add hashlist for finding struct domain by domid
Date: Tue, 13 Dec 2022 17:00:32 +0100	[thread overview]
Message-ID: <20221213160045.28170-7-jgross@suse.com> (raw)
In-Reply-To: <20221213160045.28170-1-jgross@suse.com>

Today finding a struct domain by its domain id requires to scan the
list of domains until finding the correct domid.

Add a hashlist for being able to speed this up. This allows to remove
the linking of struct domain in a list. Note that the list of changed
domains per transaction is kept as a list, as there are no known use
cases with more than 4 domains being touched in a single transaction
(this would be a device handled by a driver domain and being assigned
to a HVM domain with device model in a stubdom, plus the control
domain).

Some simple performance tests comparing the scanning and hashlist have
shown that the hashlist will win as soon as more than 6 entries need
to be scanned.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- add comment, fix return value of check_domain() (Julien Grall)
---
 tools/xenstore/xenstored_domain.c | 102 ++++++++++++++++++------------
 1 file changed, 60 insertions(+), 42 deletions(-)

diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
index e669c89e94..3ad1028edb 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -48,8 +48,6 @@ static struct node_perms dom_introduce_perms;
 
 struct domain
 {
-	struct list_head list;
-
 	/* The id of this domain */
 	unsigned int domid;
 
@@ -96,7 +94,7 @@ struct domain
 	bool wrl_delay_logged;
 };
 
-static LIST_HEAD(domains);
+static struct hashtable *domhash;
 
 static bool check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
 {
@@ -309,7 +307,7 @@ static int destroy_domain(void *_domain)
 
 	domain_tree_remove(domain);
 
-	list_del(&domain->list);
+	hashtable_remove(domhash, &domain->domid);
 
 	if (!domain->introduced)
 		return 0;
@@ -341,43 +339,50 @@ static bool get_domain_info(unsigned int domid, xc_dominfo_t *dominfo)
 	       dominfo->domid == domid;
 }
 
-void check_domains(void)
+static int check_domain(const void *k, void *v, void *arg)
 {
 	xc_dominfo_t dominfo;
-	struct domain *domain;
 	struct connection *conn;
-	int notify = 0;
 	bool dom_valid;
+	struct domain *domain = v;
+	bool *notify = arg;
 
- again:
-	list_for_each_entry(domain, &domains, list) {
-		dom_valid = get_domain_info(domain->domid, &dominfo);
-		if (!domain->introduced) {
-			if (!dom_valid) {
-				talloc_free(domain);
-				goto again;
-			}
-			continue;
-		}
-		if (dom_valid) {
-			if ((dominfo.crashed || dominfo.shutdown)
-			    && !domain->shutdown) {
-				domain->shutdown = true;
-				notify = 1;
-			}
-			if (!dominfo.dying)
-				continue;
-		}
-		if (domain->conn) {
-			/* domain is a talloc child of domain->conn. */
-			conn = domain->conn;
-			domain->conn = NULL;
-			talloc_unlink(talloc_autofree_context(), conn);
-			notify = 0; /* destroy_domain() fires the watch */
-			goto again;
+	dom_valid = get_domain_info(domain->domid, &dominfo);
+	if (!domain->introduced) {
+		if (!dom_valid)
+			talloc_free(domain);
+		return 0;
+	}
+	if (dom_valid) {
+		if ((dominfo.crashed || dominfo.shutdown)
+		    && !domain->shutdown) {
+			domain->shutdown = true;
+			*notify = true;
 		}
+		if (!dominfo.dying)
+			return 0;
+	}
+	if (domain->conn) {
+		/* domain is a talloc child of domain->conn. */
+		conn = domain->conn;
+		domain->conn = NULL;
+		talloc_unlink(talloc_autofree_context(), conn);
+		*notify = false; /* destroy_domain() fires the watch */
+
+		/* Above unlink might result in 2 domains being freed! */
+		return 1;
 	}
 
+	return 0;
+}
+
+void check_domains(void)
+{
+	bool notify = false;
+
+	while (hashtable_iterate(domhash, check_domain, &notify))
+		;
+
 	if (notify)
 		fire_watches(NULL, NULL, "@releaseDomain", NULL, true, NULL);
 }
@@ -415,13 +420,7 @@ static char *talloc_domain_path(const void *context, unsigned int domid)
 
 static struct domain *find_domain_struct(unsigned int domid)
 {
-	struct domain *i;
-
-	list_for_each_entry(i, &domains, list) {
-		if (i->domid == domid)
-			return i;
-	}
-	return NULL;
+	return hashtable_search(domhash, &domid);
 }
 
 int domain_get_quota(const void *ctx, struct connection *conn,
@@ -470,9 +469,13 @@ static struct domain *alloc_domain(const void *context, unsigned int domid)
 	domain->generation = generation;
 	domain->introduced = false;
 
-	talloc_set_destructor(domain, destroy_domain);
+	if (!hashtable_insert(domhash, &domain->domid, domain)) {
+		talloc_free(domain);
+		errno = ENOMEM;
+		return NULL;
+	}
 
-	list_add(&domain->list, &domains);
+	talloc_set_destructor(domain, destroy_domain);
 
 	return domain;
 }
@@ -906,10 +909,25 @@ void dom0_init(void)
 	xenevtchn_notify(xce_handle, dom0->port);
 }
 
+static unsigned int domhash_fn(void *k)
+{
+	return *(unsigned int *)k;
+}
+
+static int domeq_fn(void *key1, void *key2)
+{
+	return *(unsigned int *)key1 == *(unsigned int *)key2;
+}
+
 void domain_init(int evtfd)
 {
 	int rc;
 
+	/* Start with a random rather low domain count for the hashtable. */
+	domhash = create_hashtable(8, domhash_fn, domeq_fn, 0);
+	if (!domhash)
+		barf_perror("Failed to allocate domain hashtable");
+
 	xc_handle = talloc(talloc_autofree_context(), xc_interface*);
 	if (!xc_handle)
 		barf_perror("Failed to allocate domain handle");
-- 
2.35.3



  parent reply	other threads:[~2022-12-13 16:05 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-13 16:00 [PATCH v2 00/19] tools/xenstore: do some cleanup and fixes Juergen Gross
2022-12-13 16:00 ` [PATCH v2 01/19] tools/xenstore: let talloc_free() preserve errno Juergen Gross
2022-12-14  9:54   ` Jan Beulich
2022-12-14 10:08     ` Juergen Gross
2022-12-13 16:00 ` [PATCH v2 02/19] tools/xenstore: let tdb_logger() " Juergen Gross
2022-12-13 16:00 ` [PATCH v2 03/19] tools/xenstore: preserve errno across corrupt() Juergen Gross
2022-12-13 16:00 ` [PATCH v2 04/19] tools/xenstore: remove all watches when a domain has stopped Juergen Gross
2022-12-20 19:01   ` Julien Grall
2023-01-11  6:36     ` Juergen Gross
2023-01-11 17:45       ` Julien Grall
2022-12-13 16:00 ` [PATCH v2 05/19] tools/xenstore: enhance hashtable implementation Juergen Gross
2022-12-13 16:00 ` Juergen Gross [this message]
2022-12-20 19:09   ` [PATCH v2 06/19] tools/xenstore: add hashlist for finding struct domain by domid Julien Grall
2022-12-13 16:00 ` [PATCH v2 07/19] tools/xenstore: introduce dummy nodes for special watch paths Juergen Gross
2022-12-20 19:39   ` Julien Grall
2023-01-11  6:41     ` Juergen Gross
2023-01-11 17:46       ` Julien Grall
2022-12-13 16:00 ` [PATCH v2 08/19] tools/xenstore: replace watch->relative_path with a prefix length Juergen Gross
2022-12-20 19:42   ` Julien Grall
2023-01-11  6:48     ` Juergen Gross
2022-12-13 16:00 ` [PATCH v2 09/19] tools/xenstore: move changed domain handling Juergen Gross
2022-12-20 19:49   ` Julien Grall
2022-12-13 16:00 ` [PATCH v2 10/19] tools/xenstore: change per-domain node accounting interface Juergen Gross
2022-12-20 20:15   ` Julien Grall
2023-01-11  8:59     ` Juergen Gross
2023-01-11 17:48       ` Julien Grall
2023-01-12  5:49         ` Juergen Gross
2023-01-13  9:53           ` Julien Grall
2023-01-13  9:57             ` Juergen Gross
2022-12-13 16:00 ` [PATCH v2 11/19] tools/xenstore: don't allow creating too many nodes in a transaction Juergen Gross
2022-12-20 20:18   ` Julien Grall
2023-01-11  9:07     ` Juergen Gross
2022-12-13 16:00 ` [PATCH v2 12/19] tools/xenstore: replace literal domid 0 with dom0_domid Juergen Gross
2022-12-13 16:00 ` [PATCH v2 13/19] tools/xenstore: make domain_is_unprivileged() an inline function Juergen Gross
2022-12-13 16:00 ` [PATCH v2 14/19] tools/xenstore: let chk_domain_generation() return a bool Juergen Gross
2022-12-13 16:00 ` [PATCH v2 15/19] tools/xenstore: switch hashtable to use the talloc framework Juergen Gross
2022-12-20 21:50   ` Julien Grall
2023-01-11  9:27     ` Juergen Gross
2023-01-11 17:50       ` Julien Grall
2022-12-13 16:00 ` [PATCH v2 16/19] tools/xenstore: make log macro globally available Juergen Gross
2022-12-13 16:00 ` [PATCH v2 17/19] tools/xenstore: introduce trace classes Juergen Gross
2022-12-13 16:00 ` [PATCH v2 18/19] tools/xenstore: let check_store() check the accounting data Juergen Gross
2022-12-13 16:00 ` [PATCH v2 19/19] tools/xenstore: make output of "xenstore-control help" more pretty Juergen Gross
2022-12-14 11:06 ` [PATCH v2 00/19] tools/xenstore: do some cleanup and fixes Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221213160045.28170-7-jgross@suse.com \
    --to=jgross@suse.com \
    --cc=anthony.perard@citrix.com \
    --cc=julien@xen.org \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.