Merge branch 'master' into for-3.9-async
authorTejun Heo <tj@kernel.org>
Wed, 23 Jan 2013 17:31:01 +0000 (09:31 -0800)
committerTejun Heo <tj@kernel.org>
Wed, 23 Jan 2013 17:31:01 +0000 (09:31 -0800)
To receive f56c3196f251012de9b3ebaff55732a9074fdaae ("async: fix
__lowest_in_progress()").

Signed-off-by: Tejun Heo <tj@kernel.org>
1  2 
include/linux/init.h
init/do_mounts_initrd.c
init/main.c
kernel/async.c
kernel/kmod.c
kernel/sched/core.c

diff --combined include/linux/init.h
  
  #define __exit          __section(.exit.text) __exitused __cold notrace
  
- /* Used for HOTPLUG, but that is always enabled now, so just make them noops */
- #define __devinit
- #define __devinitdata
- #define __devinitconst
- #define __devexit
- #define __devexitdata
- #define __devexitconst
  /* Used for HOTPLUG_CPU */
  #define __cpuinit        __section(.cpuinit.text) __cold notrace
  #define __cpuinitdata    __section(.cpuinit.data)
@@@ -161,7 -153,6 +153,7 @@@ extern unsigned int reset_devices
  /* used by init/main.c */
  void setup_arch(char **);
  void prepare_namespace(void);
 +void __init load_default_modules(void);
  
  extern void (*late_time_init)(void);
  
@@@ -338,18 -329,6 +330,6 @@@ void __init parse_early_options(char *c
  #define __INITRODATA_OR_MODULE __INITRODATA
  #endif /*CONFIG_MODULES*/
  
- /* Functions marked as __devexit may be discarded at kernel link time, depending
-    on config options.  Newer versions of binutils detect references from
-    retained sections to discarded sections and flag an error.  Pointers to
-    __devexit functions must use __devexit_p(function_name), the wrapper will
-    insert either the function_name or NULL, depending on the config options.
-  */
- #if defined(MODULE) || defined(CONFIG_HOTPLUG)
- #define __devexit_p(x) x
- #else
- #define __devexit_p(x) NULL
- #endif
  #ifdef MODULE
  #define __exit_p(x) x
  #else
diff --combined init/do_mounts_initrd.c
@@@ -36,6 -36,10 +36,10 @@@ __setup("noinitrd", no_initrd)
  static int init_linuxrc(struct subprocess_info *info, struct cred *new)
  {
        sys_unshare(CLONE_FS | CLONE_FILES);
+       /* stdin/stdout/stderr for /linuxrc */
+       sys_open("/dev/console", O_RDWR, 0);
+       sys_dup(0);
+       sys_dup(0);
        /* move initrd over / and chdir/chroot in initrd root */
        sys_chdir("/root");
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
@@@ -57,9 -61,6 +61,9 @@@ static void __init handle_initrd(void
        sys_mkdir("/old", 0700);
        sys_chdir("/old");
  
 +      /* try loading default modules from initrd */
 +      load_default_modules();
 +
        /*
         * In case that a resume from disk is carried out by linuxrc or one of
         * its children, we need to tell the freezer not to wait for us.
diff --combined init/main.c
@@@ -70,8 -70,6 +70,8 @@@
  #include <linux/perf_event.h>
  #include <linux/file.h>
  #include <linux/ptrace.h>
 +#include <linux/blkdev.h>
 +#include <linux/elevator.h>
  
  #include <asm/io.h>
  #include <asm/bugs.h>
@@@ -796,24 -794,15 +796,26 @@@ static void __init do_pre_smp_initcalls
                do_one_initcall(*fn);
  }
  
 +/*
 + * This function requests modules which should be loaded by default and is
 + * called twice right after initrd is mounted and right before init is
 + * exec'd.  If such modules are on either initrd or rootfs, they will be
 + * loaded before control is passed to userland.
 + */
 +void __init load_default_modules(void)
 +{
 +      load_default_elevator_module();
 +}
 +
  static int run_init_process(const char *init_filename)
  {
        argv_init[0] = init_filename;
-       return kernel_execve(init_filename, argv_init, envp_init);
+       return do_execve(init_filename,
+               (const char __user *const __user *)argv_init,
+               (const char __user *const __user *)envp_init);
  }
  
- static void __init kernel_init_freeable(void);
+ static noinline void __init kernel_init_freeable(void);
  
  static int __ref kernel_init(void *unused)
  {
              "See Linux Documentation/init.txt for guidance.");
  }
  
- static void __init kernel_init_freeable(void)
+ static noinline void __init kernel_init_freeable(void)
  {
        /*
         * Wait until kthreadd is all set-up.
         * we're essentially up and running. Get rid of the
         * initmem segments and start the user-mode stuff..
         */
 +
 +      /* rootfs is available now, try loading default modules */
 +      load_default_modules();
  }
diff --combined kernel/async.c
@@@ -57,8 -57,6 +57,8 @@@ asynchronous and synchronous parts of t
  #include <linux/slab.h>
  #include <linux/workqueue.h>
  
 +#include "workqueue_internal.h"
 +
  static async_cookie_t next_cookie = 1;
  
  #define MAX_WORK      32768
@@@ -88,18 -86,27 +88,27 @@@ static atomic_t entry_count
   */
  static async_cookie_t  __lowest_in_progress(struct async_domain *running)
  {
+       async_cookie_t first_running = next_cookie;     /* infinity value */
+       async_cookie_t first_pending = next_cookie;     /* ditto */
        struct async_entry *entry;
  
+       /*
+        * Both running and pending lists are sorted but not disjoint.
+        * Take the first cookies from both and return the min.
+        */
        if (!list_empty(&running->domain)) {
                entry = list_first_entry(&running->domain, typeof(*entry), list);
-               return entry->cookie;
+               first_running = entry->cookie;
        }
  
-       list_for_each_entry(entry, &async_pending, list)
-               if (entry->running == running)
-                       return entry->cookie;
+       list_for_each_entry(entry, &async_pending, list) {
+               if (entry->running == running) {
+                       first_pending = entry->cookie;
+                       break;
+               }
+       }
  
-       return next_cookie;     /* "infinity" value */
+       return min(first_running, first_pending);
  }
  
  static async_cookie_t  lowest_in_progress(struct async_domain *running)
@@@ -120,13 -127,17 +129,17 @@@ static void async_run_entry_fn(struct w
  {
        struct async_entry *entry =
                container_of(work, struct async_entry, work);
+       struct async_entry *pos;
        unsigned long flags;
        ktime_t uninitialized_var(calltime), delta, rettime;
        struct async_domain *running = entry->running;
  
-       /* 1) move self to the running queue */
+       /* 1) move self to the running queue, make sure it stays sorted */
        spin_lock_irqsave(&async_lock, flags);
-       list_move_tail(&entry->list, &running->domain);
+       list_for_each_entry_reverse(pos, &running->domain, list)
+               if (entry->cookie < pos->cookie)
+                       break;
+       list_move_tail(&entry->list, &pos->list);
        spin_unlock_irqrestore(&async_lock, flags);
  
        /* 2) run (and print duration) */
@@@ -198,6 -209,9 +211,9 @@@ static async_cookie_t __async_schedule(
        atomic_inc(&entry_count);
        spin_unlock_irqrestore(&async_lock, flags);
  
+       /* mark that this task has queued an async job, used by module init */
+       current->flags |= PF_USED_ASYNC;
        /* schedule for execution */
        queue_work(system_unbound_wq, &entry->work);
  
@@@ -339,15 -353,3 +355,15 @@@ void async_synchronize_cookie(async_coo
        async_synchronize_cookie_domain(cookie, &async_running);
  }
  EXPORT_SYMBOL_GPL(async_synchronize_cookie);
 +
 +/**
 + * current_is_async - is %current an async worker task?
 + *
 + * Returns %true if %current is an async worker task.
 + */
 +bool current_is_async(void)
 +{
 +      struct worker *worker = current_wq_worker();
 +
 +      return worker && worker->current_func == async_run_entry_fn;
 +}
diff --combined kernel/kmod.c
@@@ -38,7 -38,6 +38,7 @@@
  #include <linux/suspend.h>
  #include <linux/rwsem.h>
  #include <linux/ptrace.h>
 +#include <linux/async.h>
  #include <asm/uaccess.h>
  
  #include <trace/events/module.h>
@@@ -131,14 -130,6 +131,14 @@@ int __request_module(bool wait, const c
  #define MAX_KMOD_CONCURRENT 50        /* Completely arbitrary value - KAO */
        static int kmod_loop_msg;
  
 +      /*
 +       * We don't allow synchronous module loading from async.  Module
 +       * init may invoke async_synchronize_full() which will end up
 +       * waiting for this task which already is waiting for the module
 +       * loading to complete, leading to a deadlock.
 +       */
 +      WARN_ON_ONCE(wait && current_is_async());
 +
        va_start(args, fmt);
        ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
        va_end(args);
@@@ -228,9 -219,9 +228,9 @@@ static int ____call_usermodehelper(voi
  
        commit_creds(new);
  
-       retval = kernel_execve(sub_info->path,
-                              (const char *const *)sub_info->argv,
-                              (const char *const *)sub_info->envp);
+       retval = do_execve(sub_info->path,
+                          (const char __user *const __user *)sub_info->argv,
+                          (const char __user *const __user *)sub_info->envp);
        if (!retval)
                return 0;
  
diff --combined kernel/sched/core.c
@@@ -83,7 -83,7 +83,7 @@@
  #endif
  
  #include "sched.h"
 -#include "../workqueue_sched.h"
 +#include "../workqueue_internal.h"
  #include "../smpboot.h"
  
  #define CREATE_TRACE_POINTS
@@@ -1523,7 -1523,8 +1523,8 @@@ out
   */
  int wake_up_process(struct task_struct *p)
  {
-       return try_to_wake_up(p, TASK_ALL, 0);
+       WARN_ON(task_is_stopped_or_traced(p));
+       return try_to_wake_up(p, TASK_NORMAL, 0);
  }
  EXPORT_SYMBOL(wake_up_process);