Patchwork [1/2] Make populate_rootfs asynchronous

login
register
mail settings
Submitter Bryan Wu
Date Feb. 5, 2010, 1:41 a.m.
Message ID <1265334066-15161-2-git-send-email-bryan.wu@canonical.com>
Download mbox | patch
Permalink /patch/44586/
State Accepted
Delegated to: Andy Whitcroft
Headers show

Comments

Bryan Wu - Feb. 5, 2010, 1:41 a.m.
From: Surbhi Palande <surbhi.palande@canonical.com>

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>

[cherry-pick from 29f1e2fdb1c62b0a7e27740d8480fbc371f76495 for backporting]
Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
---
 include/linux/init.h |    2 ++
 init/initramfs.c     |   15 ++++++++++++---
 init/main.c          |    6 ++++++
 3 files changed, 20 insertions(+), 3 deletions(-)

Patch

diff --git a/include/linux/init.h b/include/linux/init.h
index 13b633e..5a33056 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -213,6 +213,8 @@  extern void (*late_time_init)(void);
 	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 4c00edc..b8f9e3c 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)
@@ -565,7 +566,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_end - __initramfs_start);
@@ -579,7 +582,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,
@@ -603,6 +606,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 4b0f184..765cbe5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -913,6 +913,12 @@  static int __init kernel_init(void * unused)
 	do_basic_setup();
 
 	/*
+	 * 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
 	 */