struct cpuset *parent;          /* my parent */
 
-       /*
-        * Copy of global cpuset_mems_generation as of the most
-        * recent time this cpuset changed its mems_allowed.
-        */
-       int mems_generation;
-
        struct fmeter fmeter;           /* memory_pressure filter */
 
        /* partition number for rebuild_sched_domains() */
        return test_bit(CS_SPREAD_SLAB, &cs->flags);
 }
 
-/*
- * Increment this integer everytime any cpuset changes its
- * mems_allowed value.  Users of cpusets can track this generation
- * number, and avoid having to lock and reload mems_allowed unless
- * the cpuset they're using changes generation.
- *
- * A single, global generation is needed because cpuset_attach_task() could
- * reattach a task to a different cpuset, which must not have its
- * generation numbers aliased with those of that tasks previous cpuset.
- *
- * Generations are needed for mems_allowed because one task cannot
- * modify another's memory placement.  So we must enable every task,
- * on every visit to __alloc_pages(), to efficiently check whether
- * its current->cpuset->mems_allowed has changed, requiring an update
- * of its current->mems_allowed.
- *
- * Since writes to cpuset_mems_generation are guarded by the cgroup lock
- * there is no need to mark it atomic.
- */
-static int cpuset_mems_generation;
-
 static struct cpuset top_cpuset = {
        .flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
 };
  * If a task is only holding callback_mutex, then it has read-only
  * access to cpusets.
  *
- * The task_struct fields mems_allowed and mems_generation may only
- * be accessed in the context of that task, so require no locks.
+ * Now, the task_struct fields mems_allowed and mempolicy may be changed
+ * by other task, we use alloc_lock in the task_struct fields to protect
+ * them.
  *
  * The cpuset_common_file_read() handlers only hold callback_mutex across
  * small pieces of code, such as when reading out possibly multi-word
                tsk->flags &= ~PF_SPREAD_SLAB;
 }
 
-/**
- * cpuset_update_task_memory_state - update task memory placement
- *
- * If the current tasks cpusets mems_allowed changed behind our
- * backs, update current->mems_allowed, mems_generation and task NUMA
- * mempolicy to the new value.
- *
- * Task mempolicy is updated by rebinding it relative to the
- * current->cpuset if a task has its memory placement changed.
- * Do not call this routine if in_interrupt().
- *
- * Call without callback_mutex or task_lock() held.  May be
- * called with or without cgroup_mutex held.  Thanks in part to
- * 'the_top_cpuset_hack', the task's cpuset pointer will never
- * be NULL.  This routine also might acquire callback_mutex during
- * call.
- *
- * Reading current->cpuset->mems_generation doesn't need task_lock
- * to guard the current->cpuset derefence, because it is guarded
- * from concurrent freeing of current->cpuset using RCU.
- *
- * The rcu_dereference() is technically probably not needed,
- * as I don't actually mind if I see a new cpuset pointer but
- * an old value of mems_generation.  However this really only
- * matters on alpha systems using cpusets heavily.  If I dropped
- * that rcu_dereference(), it would save them a memory barrier.
- * For all other arch's, rcu_dereference is a no-op anyway, and for
- * alpha systems not using cpusets, another planned optimization,
- * avoiding the rcu critical section for tasks in the root cpuset
- * which is statically allocated, so can't vanish, will make this
- * irrelevant.  Better to use RCU as intended, than to engage in
- * some cute trick to save a memory barrier that is impossible to
- * test, for alpha systems using cpusets heavily, which might not
- * even exist.
- *
- * This routine is needed to update the per-task mems_allowed data,
- * within the tasks context, when it is trying to allocate memory
- * (in various mm/mempolicy.c routines) and notices that some other
- * task has been modifying its cpuset.
- */
-
-void cpuset_update_task_memory_state(void)
-{
-       int my_cpusets_mem_gen;
-       struct task_struct *tsk = current;
-       struct cpuset *cs;
-
-       rcu_read_lock();
-       my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
-       rcu_read_unlock();
-
-       if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) {
-               mutex_lock(&callback_mutex);
-               task_lock(tsk);
-               cs = task_cs(tsk); /* Maybe changed when task not locked */
-               guarantee_online_mems(cs, &tsk->mems_allowed);
-               tsk->cpuset_mems_generation = cs->mems_generation;
-               task_unlock(tsk);
-               mutex_unlock(&callback_mutex);
-               mpol_rebind_task(tsk, &tsk->mems_allowed);
-       }
-}
-
 /*
  * is_cpuset_subset(p, q) - Is cpuset p a subset of cpuset q?
  *
  *    other task, the task_struct mems_allowed that we are hacking
  *    is for our current task, which must allocate new pages for that
  *    migrating memory region.
- *
- *    We call cpuset_update_task_memory_state() before hacking
- *    our tasks mems_allowed, so that we are assured of being in
- *    sync with our tasks cpuset, and in particular, callbacks to
- *    cpuset_update_task_memory_state() from nested page allocations
- *    won't see any mismatch of our cpuset and task mems_generation
- *    values, so won't overwrite our hacked tasks mems_allowed
- *    nodemask.
  */
 
 static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
 {
        struct task_struct *tsk = current;
 
-       cpuset_update_task_memory_state();
-
-       mutex_lock(&callback_mutex);
        tsk->mems_allowed = *to;
-       mutex_unlock(&callback_mutex);
 
        do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
 
-       mutex_lock(&callback_mutex);
        guarantee_online_mems(task_cs(tsk),&tsk->mems_allowed);
-       mutex_unlock(&callback_mutex);
 }
 
 /*
- * Rebind task's vmas to cpuset's new mems_allowed, and migrate pages to new
- * nodes if memory_migrate flag is set. Called with cgroup_mutex held.
+ * cpuset_change_task_nodemask - change task's mems_allowed and mempolicy
+ * @tsk: the task to change
+ * @newmems: new nodes that the task will be set
+ *
+ * In order to avoid seeing no nodes if the old and new nodes are disjoint,
+ * we structure updates as setting all new allowed nodes, then clearing newly
+ * disallowed ones.
+ *
+ * Called with task's alloc_lock held
+ */
+static void cpuset_change_task_nodemask(struct task_struct *tsk,
+                                       nodemask_t *newmems)
+{
+       nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
+       mpol_rebind_task(tsk, &tsk->mems_allowed);
+       mpol_rebind_task(tsk, newmems);
+       tsk->mems_allowed = *newmems;
+}
+
+/*
+ * Update task's mems_allowed and rebind its mempolicy and vmas' mempolicy
+ * of it to cpuset's new mems_allowed, and migrate pages to new nodes if
+ * memory_migrate flag is set. Called with cgroup_mutex held.
  */
 static void cpuset_change_nodemask(struct task_struct *p,
                                   struct cgroup_scanner *scan)
        struct cpuset *cs;
        int migrate;
        const nodemask_t *oldmem = scan->data;
+       nodemask_t newmems;
+
+       cs = cgroup_cs(scan->cg);
+       guarantee_online_mems(cs, &newmems);
+
+       task_lock(p);
+       cpuset_change_task_nodemask(p, &newmems);
+       task_unlock(p);
 
        mm = get_task_mm(p);
        if (!mm)
                return;
 
-       cs = cgroup_cs(scan->cg);
        migrate = is_memory_migrate(cs);
 
        mpol_rebind_mm(mm, &cs->mems_allowed);
 /*
  * Handle user request to change the 'mems' memory placement
  * of a cpuset.  Needs to validate the request, update the
- * cpusets mems_allowed and mems_generation, and for each
- * task in the cpuset, rebind any vma mempolicies and if
- * the cpuset is marked 'memory_migrate', migrate the tasks
- * pages to the new memory.
+ * cpusets mems_allowed, and for each task in the cpuset,
+ * update mems_allowed and rebind task's mempolicy and any vma
+ * mempolicies and if the cpuset is marked 'memory_migrate',
+ * migrate the tasks pages to the new memory.
  *
  * Call with cgroup_mutex held.  May take callback_mutex during call.
  * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
 
        mutex_lock(&callback_mutex);
        cs->mems_allowed = trialcs->mems_allowed;
-       cs->mems_generation = cpuset_mems_generation++;
        mutex_unlock(&callback_mutex);
 
        update_tasks_nodemask(cs, &oldmem, &heap);
 
        if (cs == &top_cpuset) {
                cpumask_copy(cpus_attach, cpu_possible_mask);
+               to = node_possible_map;
        } else {
-               mutex_lock(&callback_mutex);
                guarantee_online_cpus(cs, cpus_attach);
-               mutex_unlock(&callback_mutex);
+               guarantee_online_mems(cs, &to);
        }
        err = set_cpus_allowed_ptr(tsk, cpus_attach);
        if (err)
                return;
 
+       task_lock(tsk);
+       cpuset_change_task_nodemask(tsk, &to);
+       task_unlock(tsk);
        cpuset_update_task_spread_flag(cs, tsk);
 
        from = oldcs->mems_allowed;
        struct cpuset *parent;
 
        if (!cont->parent) {
-               /* This is early initialization for the top cgroup */
-               top_cpuset.mems_generation = cpuset_mems_generation++;
                return &top_cpuset.css;
        }
        parent = cgroup_cs(cont->parent);
                return ERR_PTR(-ENOMEM);
        }
 
-       cpuset_update_task_memory_state();
        cs->flags = 0;
        if (is_spread_page(parent))
                set_bit(CS_SPREAD_PAGE, &cs->flags);
        set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
        cpumask_clear(cs->cpus_allowed);
        nodes_clear(cs->mems_allowed);
-       cs->mems_generation = cpuset_mems_generation++;
        fmeter_init(&cs->fmeter);
        cs->relax_domain_level = -1;
 
 {
        struct cpuset *cs = cgroup_cs(cont);
 
-       cpuset_update_task_memory_state();
-
        if (is_sched_load_balance(cs))
                update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
 
        .early_init = 1,
 };
 
-/*
- * cpuset_init_early - just enough so that the calls to
- * cpuset_update_task_memory_state() in early init code
- * are harmless.
- */
-
-int __init cpuset_init_early(void)
-{
-       alloc_cpumask_var(&top_cpuset.cpus_allowed, GFP_NOWAIT);
-
-       top_cpuset.mems_generation = cpuset_mems_generation++;
-       return 0;
-}
-
-
 /**
  * cpuset_init - initialize cpusets at system boot
  *
 {
        int err = 0;
 
+       if (!alloc_cpumask_var(&top_cpuset.cpus_allowed, GFP_KERNEL))
+               BUG();
+
        cpumask_setall(top_cpuset.cpus_allowed);
        nodes_setall(top_cpuset.mems_allowed);
 
        fmeter_init(&top_cpuset.fmeter);
-       top_cpuset.mems_generation = cpuset_mems_generation++;
        set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags);
        top_cpuset.relax_domain_level = -1;
 
 
        return 0;
 }
 
-/* Create a new policy */
+/*
+ * mpol_set_nodemask is called after mpol_new() to set up the nodemask, if
+ * any, for the new policy.  mpol_new() has already validated the nodes
+ * parameter with respect to the policy mode and flags.  But, we need to
+ * handle an empty nodemask with MPOL_PREFERRED here.
+ *
+ * Must be called holding task's alloc_lock to protect task's mems_allowed
+ * and mempolicy.  May also be called holding the mmap_semaphore for write.
+ */
+static int mpol_set_nodemask(struct mempolicy *pol, const nodemask_t *nodes)
+{
+       nodemask_t cpuset_context_nmask;
+       int ret;
+
+       /* if mode is MPOL_DEFAULT, pol is NULL. This is right. */
+       if (pol == NULL)
+               return 0;
+
+       VM_BUG_ON(!nodes);
+       if (pol->mode == MPOL_PREFERRED && nodes_empty(*nodes))
+               nodes = NULL;   /* explicit local allocation */
+       else {
+               if (pol->flags & MPOL_F_RELATIVE_NODES)
+                       mpol_relative_nodemask(&cpuset_context_nmask, nodes,
+                                              &cpuset_current_mems_allowed);
+               else
+                       nodes_and(cpuset_context_nmask, *nodes,
+                                 cpuset_current_mems_allowed);
+               if (mpol_store_user_nodemask(pol))
+                       pol->w.user_nodemask = *nodes;
+               else
+                       pol->w.cpuset_mems_allowed =
+                                               cpuset_current_mems_allowed;
+       }
+
+       ret = mpol_ops[pol->mode].create(pol,
+                               nodes ? &cpuset_context_nmask : NULL);
+       return ret;
+}
+
+/*
+ * This function just creates a new policy, does some check and simple
+ * initialization. You must invoke mpol_set_nodemask() to set nodes.
+ */
 static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
                                  nodemask_t *nodes)
 {
        struct mempolicy *policy;
-       nodemask_t cpuset_context_nmask;
-       int ret;
 
        pr_debug("setting mode %d flags %d nodes[0] %lx\n",
                 mode, flags, nodes ? nodes_addr(*nodes)[0] : -1);
                        if (((flags & MPOL_F_STATIC_NODES) ||
                             (flags & MPOL_F_RELATIVE_NODES)))
                                return ERR_PTR(-EINVAL);
-                       nodes = NULL;   /* flag local alloc */
                }
        } else if (nodes_empty(*nodes))
                return ERR_PTR(-EINVAL);
        policy->mode = mode;
        policy->flags = flags;
 
-       if (nodes) {
-               /*
-                * cpuset related setup doesn't apply to local allocation
-                */
-               cpuset_update_task_memory_state();
-               if (flags & MPOL_F_RELATIVE_NODES)
-                       mpol_relative_nodemask(&cpuset_context_nmask, nodes,
-                                              &cpuset_current_mems_allowed);
-               else
-                       nodes_and(cpuset_context_nmask, *nodes,
-                                 cpuset_current_mems_allowed);
-               if (mpol_store_user_nodemask(policy))
-                       policy->w.user_nodemask = *nodes;
-               else
-                       policy->w.cpuset_mems_allowed =
-                                               cpuset_mems_allowed(current);
-       }
-
-       ret = mpol_ops[mode].create(policy,
-                               nodes ? &cpuset_context_nmask : NULL);
-       if (ret < 0) {
-               kmem_cache_free(policy_cache, policy);
-               return ERR_PTR(ret);
-       }
        return policy;
 }
 
 /*
  * Wrapper for mpol_rebind_policy() that just requires task
  * pointer, and updates task mempolicy.
+ *
+ * Called with task's alloc_lock held.
  */
 
 void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
 static long do_set_mempolicy(unsigned short mode, unsigned short flags,
                             nodemask_t *nodes)
 {
-       struct mempolicy *new;
+       struct mempolicy *new, *old;
        struct mm_struct *mm = current->mm;
+       int ret;
 
        new = mpol_new(mode, flags, nodes);
        if (IS_ERR(new))
         */
        if (mm)
                down_write(&mm->mmap_sem);
-       mpol_put(current->mempolicy);
+       task_lock(current);
+       ret = mpol_set_nodemask(new, nodes);
+       if (ret) {
+               task_unlock(current);
+               if (mm)
+                       up_write(&mm->mmap_sem);
+               mpol_put(new);
+               return ret;
+       }
+       old = current->mempolicy;
        current->mempolicy = new;
        mpol_set_task_struct_flag();
        if (new && new->mode == MPOL_INTERLEAVE &&
            nodes_weight(new->v.nodes))
                current->il_next = first_node(new->v.nodes);
+       task_unlock(current);
        if (mm)
                up_write(&mm->mmap_sem);
 
+       mpol_put(old);
        return 0;
 }
 
 /*
  * Return nodemask for policy for get_mempolicy() query
+ *
+ * Called with task's alloc_lock held
  */
 static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
 {
        struct vm_area_struct *vma = NULL;
        struct mempolicy *pol = current->mempolicy;
 
-       cpuset_update_task_memory_state();
        if (flags &
                ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED))
                return -EINVAL;
                if (flags & (MPOL_F_NODE|MPOL_F_ADDR))
                        return -EINVAL;
                *policy = 0;    /* just so it's initialized */
+               task_lock(current);
                *nmask  = cpuset_current_mems_allowed;
+               task_unlock(current);
                return 0;
        }
 
        }
 
        err = 0;
-       if (nmask)
+       if (nmask) {
+               task_lock(current);
                get_policy_nodemask(pol, nmask);
+               task_unlock(current);
+       }
 
  out:
        mpol_cond_put(pol);
                        return err;
        }
        down_write(&mm->mmap_sem);
+       task_lock(current);
+       err = mpol_set_nodemask(new, nmask);
+       task_unlock(current);
+       if (err) {
+               up_write(&mm->mmap_sem);
+               mpol_put(new);
+               return err;
+       }
        vma = check_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
 
        struct mempolicy *pol = get_vma_policy(current, vma, addr);
        struct zonelist *zl;
 
-       cpuset_update_task_memory_state();
-
        if (unlikely(pol->mode == MPOL_INTERLEAVE)) {
                unsigned nid;
 
 {
        struct mempolicy *pol = current->mempolicy;
 
-       if ((gfp & __GFP_WAIT) && !in_interrupt())
-               cpuset_update_task_memory_state();
        if (!pol || in_interrupt() || (gfp & __GFP_THISNODE))
                pol = &default_policy;
 
  */
 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
 {
+       int ret;
+
        sp->root = RB_ROOT;             /* empty tree == default mempolicy */
        spin_lock_init(&sp->lock);
 
 
                /* contextualize the tmpfs mount point mempolicy */
                new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
-               mpol_put(mpol); /* drop our ref on sb mpol */
-               if (IS_ERR(new))
+               if (IS_ERR(new)) {
+                       mpol_put(mpol); /* drop our ref on sb mpol */
                        return;         /* no valid nodemask intersection */
+               }
+
+               task_lock(current);
+               ret = mpol_set_nodemask(new, &mpol->w.user_nodemask);
+               task_unlock(current);
+               mpol_put(mpol); /* drop our ref on sb mpol */
+               if (ret) {
+                       mpol_put(new);
+                       return;
+               }
 
                /* Create pseudo-vma that contains just the policy */
                memset(&pvma, 0, sizeof(struct vm_area_struct));
        new = mpol_new(mode, mode_flags, &nodes);
        if (IS_ERR(new))
                err = 1;
-       else if (no_context)
-               new->w.user_nodemask = nodes;   /* save for contextualization */
+       else {
+               int ret;
+
+               task_lock(current);
+               ret = mpol_set_nodemask(new, &nodes);
+               task_unlock(current);
+               if (ret)
+                       err = 1;
+               else if (no_context) {
+                       /* save for contextualization */
+                       new->w.user_nodemask = nodes;
+               }
+       }
 
 out:
        /* Restore string for error message */