Merge tag 'v3.10.107' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / kernel / cpuset.c
index 4f9dfe43ecbd777d7bf03bed72c5da566e952b62..067750bbdad8c753020ccb7afcbe60a43a84d729 100644 (file)
@@ -264,17 +264,6 @@ static struct cpuset top_cpuset = {
 static DEFINE_MUTEX(cpuset_mutex);
 static DEFINE_MUTEX(callback_mutex);
 
-/*
- * cpuset_buffer_lock protects both the cpuset_name and cpuset_nodelist
- * buffers.  They are statically allocated to prevent using excess stack
- * when calling cpuset_print_task_mems_allowed().
- */
-#define CPUSET_NAME_LEN                (128)
-#define        CPUSET_NODELIST_LEN     (256)
-static char cpuset_name[CPUSET_NAME_LEN];
-static char cpuset_nodelist[CPUSET_NODELIST_LEN];
-static DEFINE_SPINLOCK(cpuset_buffer_lock);
-
 /*
  * CPU / memory hotplug is handled asynchronously.
  */
@@ -780,25 +769,26 @@ static void rebuild_sched_domains_locked(void)
        lockdep_assert_held(&cpuset_mutex);
        get_online_cpus();
 
+       /*
+        * We have raced with CPU hotplug. Don't do anything to avoid
+        * passing doms with offlined cpu to partition_sched_domains().
+        * Anyways, hotplug work item will rebuild sched domains.
+        */
+       if (!cpumask_equal(top_cpuset.cpus_allowed, cpu_active_mask))
+               goto out;
+
        /* Generate domain masks and attrs */
        ndoms = generate_sched_domains(&doms, &attr);
 
        /* Have scheduler rebuild the domains */
        partition_sched_domains(ndoms, doms, attr);
-
+out:
        put_online_cpus();
 }
 #else /* !CONFIG_SMP */
 static void rebuild_sched_domains_locked(void)
 {
 }
-
-static int generate_sched_domains(cpumask_var_t **domains,
-                       struct sched_domain_attr **attributes)
-{
-       *domains = NULL;
-       return 1;
-}
 #endif /* CONFIG_SMP */
 
 void rebuild_sched_domains(void)
@@ -994,8 +984,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
        need_loop = task_has_mempolicy(tsk) ||
                        !nodes_intersects(*newmems, tsk->mems_allowed);
 
-       if (need_loop)
+       if (need_loop) {
+               local_irq_disable();
                write_seqcount_begin(&tsk->mems_allowed_seq);
+       }
 
        nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
        mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1);
@@ -1003,8 +995,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
        mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP2);
        tsk->mems_allowed = *newmems;
 
-       if (need_loop)
+       if (need_loop) {
                write_seqcount_end(&tsk->mems_allowed_seq);
+               local_irq_enable();
+       }
 
        task_unlock(tsk);
 }
@@ -1159,7 +1153,13 @@ done:
 
 int current_cpuset_is_being_rebound(void)
 {
-       return task_cs(current) == cpuset_being_rebound;
+       int ret;
+
+       rcu_read_lock();
+       ret = task_cs(current) == cpuset_being_rebound;
+       rcu_read_unlock();
+
+       return ret;
 }
 
 static int update_relax_domain_level(struct cpuset *cs, s64 val)
@@ -1388,16 +1388,16 @@ static int cpuset_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 
        cgroup_taskset_for_each(task, cgrp, tset) {
                /*
-                * Kthreads bound to specific cpus cannot be moved to a new
-                * cpuset; we cannot change their cpu affinity and
-                * isolating such threads by their set of allowed nodes is
-                * unnecessary.  Thus, cpusets are not applicable for such
-                * threads.  This prevents checking for success of
-                * set_cpus_allowed_ptr() on all attached tasks before
-                * cpus_allowed may be changed.
+                * Kthreads which disallow setaffinity shouldn't be moved
+                * to a new cpuset; we don't want to change their cpu
+                * affinity and isolating such threads by their set of
+                * allowed nodes is unnecessary.  Thus, cpusets are not
+                * applicable for such threads.  This prevents checking for
+                * success of set_cpus_allowed_ptr() on all attached tasks
+                * before cpus_allowed may be changed.
                 */
                ret = -EINVAL;
-               if (task->flags & PF_THREAD_BOUND)
+               if (task->flags & PF_NO_SETAFFINITY)
                        goto out_unlock;
                ret = security_task_setscheduler(task);
                if (ret)
@@ -1512,11 +1512,13 @@ static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
 {
        struct cpuset *cs = cgroup_cs(cgrp);
        cpuset_filetype_t type = cft->private;
-       int retval = -ENODEV;
+       int retval = 0;
 
        mutex_lock(&cpuset_mutex);
-       if (!is_cpuset_online(cs))
+       if (!is_cpuset_online(cs)) {
+               retval = -ENODEV;
                goto out_unlock;
+       }
 
        switch (type) {
        case FILE_CPU_EXCLUSIVE:
@@ -2005,50 +2007,6 @@ int __init cpuset_init(void)
        return 0;
 }
 
-/**
- * cpuset_do_move_task - move a given task to another cpuset
- * @tsk: pointer to task_struct the task to move
- * @scan: struct cgroup_scanner contained in its struct cpuset_hotplug_scanner
- *
- * Called by cgroup_scan_tasks() for each task in a cgroup.
- * Return nonzero to stop the walk through the tasks.
- */
-static void cpuset_do_move_task(struct task_struct *tsk,
-                               struct cgroup_scanner *scan)
-{
-       struct cgroup *new_cgroup = scan->data;
-
-       cgroup_lock();
-       cgroup_attach_task(new_cgroup, tsk);
-       cgroup_unlock();
-}
-
-/**
- * move_member_tasks_to_cpuset - move tasks from one cpuset to another
- * @from: cpuset in which the tasks currently reside
- * @to: cpuset to which the tasks will be moved
- *
- * Called with cpuset_mutex held
- * callback_mutex must not be held, as cpuset_attach() will take it.
- *
- * The cgroup_scan_tasks() function will scan all the tasks in a cgroup,
- * calling callback functions for each.
- */
-static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
-{
-       struct cgroup_scanner scan;
-
-       scan.cg = from->css.cgroup;
-       scan.test_task = NULL; /* select all tasks in cgroup */
-       scan.process_task = cpuset_do_move_task;
-       scan.heap = NULL;
-       scan.data = to->css.cgroup;
-
-       if (cgroup_scan_tasks(&scan))
-               printk(KERN_ERR "move_member_tasks_to_cpuset: "
-                               "cgroup_scan_tasks failed\n");
-}
-
 /*
  * If CPU and/or memory hotplug handlers, below, unplug any CPUs
  * or memory nodes, we need to walk over the cpuset hierarchy,
@@ -2069,7 +2027,12 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
                        nodes_empty(parent->mems_allowed))
                parent = parent_cs(parent);
 
-       move_member_tasks_to_cpuset(cs, parent);
+       if (cgroup_transfer_tasks(parent->css.cgroup, cs->css.cgroup)) {
+               rcu_read_lock();
+               printk(KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n",
+                      cgroup_name(cs->css.cgroup));
+               rcu_read_unlock();
+       }
 }
 
 /**
@@ -2222,17 +2185,8 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
        flush_workqueue(cpuset_propagate_hotplug_wq);
 
        /* rebuild sched domains if cpus_allowed has changed */
-       if (cpus_updated) {
-               struct sched_domain_attr *attr;
-               cpumask_var_t *doms;
-               int ndoms;
-
-               mutex_lock(&cpuset_mutex);
-               ndoms = generate_sched_domains(&doms, &attr);
-               mutex_unlock(&cpuset_mutex);
-
-               partition_sched_domains(ndoms, doms, attr);
-       }
+       if (cpus_updated)
+               rebuild_sched_domains();
 }
 
 void cpuset_update_active_cpus(bool cpu_online)
@@ -2251,7 +2205,6 @@ void cpuset_update_active_cpus(bool cpu_online)
        schedule_work(&cpuset_hotplug_work);
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY].
  * Call this routine anytime after node_states[N_MEMORY] changes.
@@ -2263,20 +2216,23 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
        schedule_work(&cpuset_hotplug_work);
        return NOTIFY_OK;
 }
-#endif
+
+static struct notifier_block cpuset_track_online_nodes_nb = {
+       .notifier_call = cpuset_track_online_nodes,
+       .priority = 10,         /* ??! */
+};
 
 /**
  * cpuset_init_smp - initialize cpus_allowed
  *
  * Description: Finish top cpuset after cpu, node maps are initialized
- **/
-
+ */
 void __init cpuset_init_smp(void)
 {
        cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
        top_cpuset.mems_allowed = node_states[N_MEMORY];
 
-       hotplug_memory_notifier(cpuset_track_online_nodes, 10);
+       register_hotmemory_notifier(&cpuset_track_online_nodes_nb);
 
        cpuset_propagate_hotplug_wq =
                alloc_ordered_workqueue("cpuset_hotplug", 0);
@@ -2472,9 +2428,9 @@ int __cpuset_node_allowed_softwall(int node, gfp_t gfp_mask)
 
        task_lock(current);
        cs = nearest_hardwall_ancestor(task_cs(current));
+       allowed = node_isset(node, cs->mems_allowed);
        task_unlock(current);
 
-       allowed = node_isset(node, cs->mems_allowed);
        mutex_unlock(&callback_mutex);
        return allowed;
 }
@@ -2592,6 +2548,8 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
        return nodes_intersects(tsk1->mems_allowed, tsk2->mems_allowed);
 }
 
+#define CPUSET_NODELIST_LEN    (256)
+
 /**
  * cpuset_print_task_mems_allowed - prints task's cpuset and mems_allowed
  * @task: pointer to task_struct of some task.
@@ -2602,25 +2560,22 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
  */
 void cpuset_print_task_mems_allowed(struct task_struct *tsk)
 {
-       struct dentry *dentry;
+        /* Statically allocated to prevent using excess stack. */
+       static char cpuset_nodelist[CPUSET_NODELIST_LEN];
+       static DEFINE_SPINLOCK(cpuset_buffer_lock);
 
-       dentry = task_cs(tsk)->css.cgroup->dentry;
-       spin_lock(&cpuset_buffer_lock);
+       struct cgroup *cgrp = task_cs(tsk)->css.cgroup;
 
-       if (!dentry) {
-               strcpy(cpuset_name, "/");
-       } else {
-               spin_lock(&dentry->d_lock);
-               strlcpy(cpuset_name, (const char *)dentry->d_name.name,
-                       CPUSET_NAME_LEN);
-               spin_unlock(&dentry->d_lock);
-       }
+       rcu_read_lock();
+       spin_lock(&cpuset_buffer_lock);
 
        nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
                           tsk->mems_allowed);
        printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n",
-              tsk->comm, cpuset_name, cpuset_nodelist);
+              tsk->comm, cgroup_name(cgrp), cpuset_nodelist);
+
        spin_unlock(&cpuset_buffer_lock);
+       rcu_read_unlock();
 }
 
 /*
@@ -2666,7 +2621,7 @@ void __cpuset_memory_pressure_bump(void)
  *    and we take cpuset_mutex, keeping cpuset_attach() from changing it
  *    anyway.
  */
-static int proc_cpuset_show(struct seq_file *m, void *unused_v)
+int proc_cpuset_show(struct seq_file *m, void *unused_v)
 {
        struct pid *pid;
        struct task_struct *tsk;
@@ -2700,19 +2655,6 @@ out_free:
 out:
        return retval;
 }
-
-static int cpuset_open(struct inode *inode, struct file *file)
-{
-       struct pid *pid = PROC_I(inode)->pid;
-       return single_open(file, proc_cpuset_show, pid);
-}
-
-const struct file_operations proc_cpuset_operations = {
-       .open           = cpuset_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
 #endif /* CONFIG_PROC_PID_CPUSET */
 
 /* Display task mems_allowed in /proc/<pid>/status file. */