Avoid stale pointer when moving domain to another cpupool
authorJuergen Gross <juergen.gross@ts.fujitsu.com>
Thu, 28 Feb 2013 14:56:45 +0000 (14:56 +0000)
committerKeir Fraser <keir@xen.org>
Thu, 28 Feb 2013 14:56:45 +0000 (14:56 +0000)
When a domain is moved to another cpupool the scheduler private data pointers
in vcpu and domain structures must never point to an already freed memory
area.

While at it, simplify sched_init_vcpu() by using DOM2OP instead VCPU2OP.

Signed-off-by: Juergen Gross <juergen.gross@ts.fujitsu.com>
xen/common/schedule.c

index 9c58b12074fda348ac8e255b0e2ad7ad132c2c18..1fc9b7df6cd7554f1f72cd55502a28f4f1cc7c65 100644 (file)
@@ -220,7 +220,7 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor)
     if ( v->sched_priv == NULL )
         return 1;
 
-    SCHED_OP(VCPU2OP(v), insert_vcpu, v);
+    SCHED_OP(DOM2OP(d), insert_vcpu, v);
 
     return 0;
 }
@@ -231,6 +231,9 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
     unsigned int new_p;
     void **vcpu_priv;
     void *domdata;
+    void *vcpudata;
+    struct scheduler *old_ops;
+    void *old_domdata;
 
     domdata = SCHED_OP(c->sched, alloc_domdata, d);
     if ( domdata == NULL )
@@ -261,21 +264,22 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
 
     domain_pause(d);
 
+    old_ops = DOM2OP(d);
+    old_domdata = d->sched_priv;
+
     for_each_vcpu ( d, v )
     {
-        SCHED_OP(VCPU2OP(v), remove_vcpu, v);
-        SCHED_OP(VCPU2OP(v), free_vdata, v->sched_priv);
-        v->sched_priv = NULL;
+        SCHED_OP(old_ops, remove_vcpu, v);
     }
 
-    SCHED_OP(DOM2OP(d), free_domdata, d->sched_priv);
-
     d->cpupool = c;
     d->sched_priv = domdata;
 
     new_p = cpumask_first(c->cpu_valid);
     for_each_vcpu ( d, v )
     {
+        vcpudata = v->sched_priv;
+
         migrate_timer(&v->periodic_timer, new_p);
         migrate_timer(&v->singleshot_timer, new_p);
         migrate_timer(&v->poll_timer, new_p);
@@ -288,12 +292,16 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
         new_p = cpumask_cycle(new_p, c->cpu_valid);
 
         SCHED_OP(c->sched, insert_vcpu, v);
+
+        SCHED_OP(old_ops, free_vdata, vcpudata);
     }
 
     domain_update_node_affinity(d);
 
     domain_unpause(d);
 
+    SCHED_OP(old_ops, free_domdata, old_domdata);
+
     xfree(vcpu_priv);
 
     return 0;