@@ -365,6 +365,39 @@ static int __init parse_extra_guest_irqs(const char *s)
}
custom_param("extra_guest_irqs", parse_extra_guest_irqs);
+static void _free_pirq_struct(struct rcu_head *head)
+{
+ xfree(container_of(head, struct pirq, rcu_head));
+}
+
+static void free_pirq_struct(void *ptr)
+{
+ struct pirq *pirq = ptr;
+
+ call_rcu(&pirq->rcu_head, _free_pirq_struct);
+}
+
+struct pirq *pirq_get_info(struct domain *d, int pirq)
+{
+ struct pirq *info = pirq_info(d, pirq);
+
+ if ( info )
+ return info;
+
+ info = alloc_pirq_struct(d);
+ if ( !info )
+ return NULL;
+
+ info->pirq = pirq;
+ if ( radix_tree_insert(&d->pirq_tree, pirq, info) == 0 )
+ return info; /* Success. */
+
+ /* Don't use call_rcu() to free a struct we failed to insert. */
+ _free_pirq_struct(&info->rcu_head);
+
+ return NULL;
+}
+
/*
* Release resources held by a domain. There may or may not be live
* references to the domain, and it may or may not be fully constructed.
@@ -1780,35 +1813,6 @@ long do_vm_assist(unsigned int cmd, unsigned int type)
}
#endif
-struct pirq *pirq_get_info(struct domain *d, int pirq)
-{
- struct pirq *info = pirq_info(d, pirq);
-
- if ( !info && (info = alloc_pirq_struct(d)) != NULL )
- {
- info->pirq = pirq;
- if ( radix_tree_insert(&d->pirq_tree, pirq, info) )
- {
- free_pirq_struct(info);
- info = NULL;
- }
- }
-
- return info;
-}
-
-static void _free_pirq_struct(struct rcu_head *head)
-{
- xfree(container_of(head, struct pirq, rcu_head));
-}
-
-void free_pirq_struct(void *ptr)
-{
- struct pirq *pirq = ptr;
-
- call_rcu(&pirq->rcu_head, _free_pirq_struct);
-}
-
struct migrate_info {
long (*func)(void *data);
void *data;
@@ -44,7 +44,6 @@ void free_vcpu_struct(struct vcpu *v);
#ifndef alloc_pirq_struct
struct pirq *alloc_pirq_struct(struct domain *);
#endif
-void free_pirq_struct(void *);
/*
* Initialise/destroy arch-specific details of a VCPU.
free_pirq_struct() has no external users, so shouldn't be exposed. Making it static necessistates moving the function as domain_destroy() uses it. Rework pirq_get_info() to have easier-to-follow logic. The one functional change is to the insertion failure path; we should not be using a full call_rcu() chain to free an otherwise local structure we failed to insert into the radix tree to begin with. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- v2: * Drop likely/unlikey --- xen/common/domain.c | 62 ++++++++++++++++++++++++++---------------------- xen/include/xen/domain.h | 1 - 2 files changed, 33 insertions(+), 30 deletions(-)