int overloaded;
 };
 
+#ifdef CONFIG_SMP
+
+/*
+ * We add the notion of a root-domain which will be used to define per-domain
+ * variables.  Each exclusive cpuset essentially defines an island domain by
+ * fully partitioning the member cpus from any other cpuset.  Whenever a new
+ * exclusive cpuset is created, we also create and attach a new root-domain
+ * object.
+ *
+ * By default the system creates a single root-domain with all cpus as
+ * members (mimicking the global state we have today).
+ */
+struct root_domain {
+       atomic_t refcount;
+       cpumask_t span;
+       cpumask_t online;
+};
+
+static struct root_domain def_root_domain;
+
+#endif
+
 /*
  * This is the main, per-CPU runqueue data structure.
  *
        atomic_t nr_iowait;
 
 #ifdef CONFIG_SMP
+       struct root_domain  *rd;
        struct sched_domain *sd;
 
        /* For active balancing */
        case CPU_ONLINE_FROZEN:
                /* Strictly unnecessary, as first user will wake it. */
                wake_up_process(cpu_rq(cpu)->migration_thread);
+
+               /* Update our root-domain */
+               rq = cpu_rq(cpu);
+               spin_lock_irqsave(&rq->lock, flags);
+               if (rq->rd) {
+                       BUG_ON(!cpu_isset(cpu, rq->rd->span));
+                       cpu_set(cpu, rq->rd->online);
+               }
+               spin_unlock_irqrestore(&rq->lock, flags);
                break;
 
 #ifdef CONFIG_HOTPLUG_CPU
                }
                spin_unlock_irq(&rq->lock);
                break;
+
+       case CPU_DOWN_PREPARE:
+               /* Update our root-domain */
+               rq = cpu_rq(cpu);
+               spin_lock_irqsave(&rq->lock, flags);
+               if (rq->rd) {
+                       BUG_ON(!cpu_isset(cpu, rq->rd->span));
+                       cpu_clear(cpu, rq->rd->online);
+               }
+               spin_unlock_irqrestore(&rq->lock, flags);
+               break;
 #endif
        }
        return NOTIFY_OK;
        return 1;
 }
 
+static void rq_attach_root(struct rq *rq, struct root_domain *rd)
+{
+       unsigned long flags;
+       const struct sched_class *class;
+
+       spin_lock_irqsave(&rq->lock, flags);
+
+       if (rq->rd) {
+               struct root_domain *old_rd = rq->rd;
+
+               for (class = sched_class_highest; class; class = class->next)
+                       if (class->leave_domain)
+                               class->leave_domain(rq);
+
+               if (atomic_dec_and_test(&old_rd->refcount))
+                       kfree(old_rd);
+       }
+
+       atomic_inc(&rd->refcount);
+       rq->rd = rd;
+
+       for (class = sched_class_highest; class; class = class->next)
+               if (class->join_domain)
+                       class->join_domain(rq);
+
+       spin_unlock_irqrestore(&rq->lock, flags);
+}
+
+static void init_rootdomain(struct root_domain *rd, const cpumask_t *map)
+{
+       memset(rd, 0, sizeof(*rd));
+
+       rd->span = *map;
+       cpus_and(rd->online, rd->span, cpu_online_map);
+}
+
+static void init_defrootdomain(void)
+{
+       cpumask_t cpus = CPU_MASK_ALL;
+
+       init_rootdomain(&def_root_domain, &cpus);
+       atomic_set(&def_root_domain.refcount, 1);
+}
+
+static struct root_domain *alloc_rootdomain(const cpumask_t *map)
+{
+       struct root_domain *rd;
+
+       rd = kmalloc(sizeof(*rd), GFP_KERNEL);
+       if (!rd)
+               return NULL;
+
+       init_rootdomain(rd, map);
+
+       return rd;
+}
+
 /*
  * Attach the domain 'sd' to 'cpu' as its base domain.  Callers must
  * hold the hotplug lock.
  */
-static void cpu_attach_domain(struct sched_domain *sd, int cpu)
+static void cpu_attach_domain(struct sched_domain *sd,
+                             struct root_domain *rd, int cpu)
 {
        struct rq *rq = cpu_rq(cpu);
        struct sched_domain *tmp;
 
        sched_domain_debug(sd, cpu);
 
+       rq_attach_root(rq, rd);
        rcu_assign_pointer(rq->sd, sd);
 }
 
 static int build_sched_domains(const cpumask_t *cpu_map)
 {
        int i;
+       struct root_domain *rd;
 #ifdef CONFIG_NUMA
        struct sched_group **sched_group_nodes = NULL;
        int sd_allnodes = 0;
        sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
 #endif
 
+       rd = alloc_rootdomain(cpu_map);
+       if (!rd) {
+               printk(KERN_WARNING "Cannot alloc root domain\n");
+               return -ENOMEM;
+       }
+
        /*
         * Set up domains for cpus specified by the cpu_map.
         */
 #else
                sd = &per_cpu(phys_domains, i);
 #endif
-               cpu_attach_domain(sd, i);
+               cpu_attach_domain(sd, rd, i);
        }
 
        return 0;
        unregister_sched_domain_sysctl();
 
        for_each_cpu_mask(i, *cpu_map)
-               cpu_attach_domain(NULL, i);
+               cpu_attach_domain(NULL, &def_root_domain, i);
        synchronize_sched();
        arch_destroy_sched_domains(cpu_map);
 }
        int highest_cpu = 0;
        int i, j;
 
+#ifdef CONFIG_SMP
+       init_defrootdomain();
+#endif
+
        for_each_possible_cpu(i) {
                struct rt_prio_array *array;
                struct rq *rq;
                        rq->cpu_load[j] = 0;
 #ifdef CONFIG_SMP
                rq->sd = NULL;
+               rq->rd = NULL;
+               rq_attach_root(rq, &def_root_domain);
                rq->active_balance = 0;
                rq->next_balance = jiffies;
                rq->push_cpu = 0;