aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSurbhi Palande <surbhi.palande@canonical.com>2009-12-08 11:44:34 +0200
committerJohn Rigby <john.rigby@linaro.org>2011-10-17 02:31:59 -0600
commit7f4074e27ecec40fb463bea8b4b6e3ccdd763263 (patch)
treef7700eb0d0eb80220e0c50fbfe4f4c9aa58e9f51
parentddf8b8fcdba4a64932cdaffd41f1bde18d9d985c (diff)
UBUNTU: SAUCE: Make populate_rootfs asynchronous
The expansion of the initramfs is completely independant of other boot activities. The original data is already present at boot and the filesystem is not required until we are ready to start init. It is therefore reasonable to populate the rootfs asynchronously. Move this processing to an async call. This reduces kernel initialisation time (the time from bootloader to starting userspace) by several 10ths of a second on a selection of test hardware particularly SMP systems, although UP system also benefit. Signed-off-by: Surbhi Palande <surbhi.palande@canonical.com> Signed-off-by: Andy Whitcroft <apw@canonical.com>
-rw-r--r--include/linux/init.h2
-rw-r--r--init/initramfs.c15
-rw-r--r--init/main.c6
3 files changed, 20 insertions, 3 deletions
diff --git a/include/linux/init.h b/include/linux/init.h
index 9146f39cddd..a2b5b8a97e0 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -222,6 +222,8 @@ extern int initcall_debug;
static initcall_t __initcall_##fn \
__used __section(.security_initcall.init) = fn
+extern struct list_head populate_rootfs_domain;
+
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
diff --git a/init/initramfs.c b/init/initramfs.c
index 2531811d42c..22712f94e82 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -8,6 +8,7 @@
#include <linux/dirent.h>
#include <linux/syscalls.h>
#include <linux/utime.h>
+#include <linux/async.h>
static __initdata char *message;
static void __init error(char *x)
@@ -569,7 +570,9 @@ static void __init clean_rootfs(void)
}
#endif
-static int __init populate_rootfs(void)
+LIST_HEAD(populate_rootfs_domain);
+
+static void __init async_populate_rootfs(void)
{
char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
if (err)
@@ -582,7 +585,7 @@ static int __init populate_rootfs(void)
initrd_end - initrd_start);
if (!err) {
free_initrd();
- return 0;
+ return;
} else {
clean_rootfs();
unpack_to_rootfs(__initramfs_start, __initramfs_size);
@@ -606,6 +609,12 @@ static int __init populate_rootfs(void)
free_initrd();
#endif
}
- return 0;
+ return;
}
+
+static int __init populate_rootfs(void)
+{
+ async_schedule_domain(async_populate_rootfs, NULL, &populate_rootfs_domain);
+}
+
rootfs_initcall(populate_rootfs);
diff --git a/init/main.c b/init/main.c
index 70c5b0a2e05..1c691f94ffc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -811,6 +811,12 @@ static int __init kernel_init(void * unused)
(void) sys_dup(0);
(void) sys_dup(0);
/*
+ * We need to ensure that the filesystem is ready by this point, wait for
+ * async_populate_rootfs to complete.
+ */
+ async_synchronize_full_domain(&populate_rootfs_domain);
+
+ /*
* check if there is an early userspace init. If yes, let it do all
* the work
*/