aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi, Shaohua <shaohua.li@intel.com>2008-08-13 05:26:01 -0400
committerArjan van de Ven <arjan@linux.intel.com>2009-03-28 16:06:22 -0400
commitdf52092f3c97788592ef72501a43fb7ac6a3cfe0 (patch)
tree1c708b2f43db6cf30bc1397ba5d3a520d0d370b7
parent0c406263f0a22b9fad65404cf2b14eced0739485 (diff)
fastboot: remove duplicate unpack_to_rootfs()
we check if initrd is initramfs first and then do the real unpack. The check isn't required, we can directly do unpack. If the initrd isn't an initramfs, we can remove the garbage. In my laptop, this saves 0.1s boot time. This patch penalizes non-initramfs initrd case, but nowadays, initramfs is the most widely used method for initrds. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Acked-by: Arjan van de Ven <arjan@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--init/initramfs.c71
1 files changed, 56 insertions, 15 deletions
diff --git a/init/initramfs.c b/init/initramfs.c
index d9c941c0c3ca..d3c56fcb30b8 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -5,6 +5,7 @@
5#include <linux/fcntl.h> 5#include <linux/fcntl.h>
6#include <linux/delay.h> 6#include <linux/delay.h>
7#include <linux/string.h> 7#include <linux/string.h>
8#include <linux/dirent.h>
8#include <linux/syscalls.h> 9#include <linux/syscalls.h>
9#include <linux/utime.h> 10#include <linux/utime.h>
10 11
@@ -166,8 +167,6 @@ static __initdata char *victim;
166static __initdata unsigned count; 167static __initdata unsigned count;
167static __initdata loff_t this_header, next_header; 168static __initdata loff_t this_header, next_header;
168 169
169static __initdata int dry_run;
170
171static inline void __init eat(unsigned n) 170static inline void __init eat(unsigned n)
172{ 171{
173 victim += n; 172 victim += n;
@@ -229,10 +228,6 @@ static int __init do_header(void)
229 parse_header(collected); 228 parse_header(collected);
230 next_header = this_header + N_ALIGN(name_len) + body_len; 229 next_header = this_header + N_ALIGN(name_len) + body_len;
231 next_header = (next_header + 3) & ~3; 230 next_header = (next_header + 3) & ~3;
232 if (dry_run) {
233 read_into(name_buf, N_ALIGN(name_len), GotName);
234 return 0;
235 }
236 state = SkipIt; 231 state = SkipIt;
237 if (name_len <= 0 || name_len > PATH_MAX) 232 if (name_len <= 0 || name_len > PATH_MAX)
238 return 0; 233 return 0;
@@ -303,8 +298,6 @@ static int __init do_name(void)
303 free_hash(); 298 free_hash();
304 return 0; 299 return 0;
305 } 300 }
306 if (dry_run)
307 return 0;
308 clean_path(collected, mode); 301 clean_path(collected, mode);
309 if (S_ISREG(mode)) { 302 if (S_ISREG(mode)) {
310 int ml = maybe_link(); 303 int ml = maybe_link();
@@ -476,10 +469,9 @@ static void __init flush_window(void)
476 outcnt = 0; 469 outcnt = 0;
477} 470}
478 471
479static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) 472static char * __init unpack_to_rootfs(char *buf, unsigned len)
480{ 473{
481 int written; 474 int written;
482 dry_run = check_only;
483 header_buf = kmalloc(110, GFP_KERNEL); 475 header_buf = kmalloc(110, GFP_KERNEL);
484 symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); 476 symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
485 name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); 477 name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
@@ -574,10 +566,57 @@ skip:
574 initrd_end = 0; 566 initrd_end = 0;
575} 567}
576 568
569#define BUF_SIZE 1024
570static void __init clean_rootfs(void)
571{
572 int fd;
573 void *buf;
574 struct linux_dirent64 *dirp;
575 int count;
576
577 fd = sys_open("/", O_RDONLY, 0);
578 WARN_ON(fd < 0);
579 if (fd < 0)
580 return;
581 buf = kzalloc(BUF_SIZE, GFP_KERNEL);
582 WARN_ON(!buf);
583 if (!buf) {
584 sys_close(fd);
585 return;
586 }
587
588 dirp = buf;
589 count = sys_getdents64(fd, dirp, BUF_SIZE);
590 while (count > 0) {
591 while (count > 0) {
592 struct stat st;
593 int ret;
594
595 ret = sys_newlstat(dirp->d_name, &st);
596 WARN_ON_ONCE(ret);
597 if (!ret) {
598 if (S_ISDIR(st.st_mode))
599 sys_rmdir(dirp->d_name);
600 else
601 sys_unlink(dirp->d_name);
602 }
603
604 count -= dirp->d_reclen;
605 dirp = (void *)dirp + dirp->d_reclen;
606 }
607 dirp = buf;
608 memset(buf, 0, BUF_SIZE);
609 count = sys_getdents64(fd, dirp, BUF_SIZE);
610 }
611
612 sys_close(fd);
613 kfree(buf);
614}
615
577static int __init populate_rootfs(void) 616static int __init populate_rootfs(void)
578{ 617{
579 char *err = unpack_to_rootfs(__initramfs_start, 618 char *err = unpack_to_rootfs(__initramfs_start,
580 __initramfs_end - __initramfs_start, 0); 619 __initramfs_end - __initramfs_start);
581 if (err) 620 if (err)
582 panic(err); 621 panic(err);
583 if (initrd_start) { 622 if (initrd_start) {
@@ -585,13 +624,15 @@ static int __init populate_rootfs(void)
585 int fd; 624 int fd;
586 printk(KERN_INFO "checking if image is initramfs..."); 625 printk(KERN_INFO "checking if image is initramfs...");
587 err = unpack_to_rootfs((char *)initrd_start, 626 err = unpack_to_rootfs((char *)initrd_start,
588 initrd_end - initrd_start, 1); 627 initrd_end - initrd_start);
589 if (!err) { 628 if (!err) {
590 printk(" it is\n"); 629 printk(" it is\n");
591 unpack_to_rootfs((char *)initrd_start,
592 initrd_end - initrd_start, 0);
593 free_initrd(); 630 free_initrd();
594 return 0; 631 return 0;
632 } else {
633 clean_rootfs();
634 unpack_to_rootfs(__initramfs_start,
635 __initramfs_end - __initramfs_start);
595 } 636 }
596 printk("it isn't (%s); looks like an initrd\n", err); 637 printk("it isn't (%s); looks like an initrd\n", err);
597 fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); 638 fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
@@ -604,7 +645,7 @@ static int __init populate_rootfs(void)
604#else 645#else
605 printk(KERN_INFO "Unpacking initramfs..."); 646 printk(KERN_INFO "Unpacking initramfs...");
606 err = unpack_to_rootfs((char *)initrd_start, 647 err = unpack_to_rootfs((char *)initrd_start,
607 initrd_end - initrd_start, 0); 648 initrd_end - initrd_start);
608 if (err) 649 if (err)
609 panic(err); 650 panic(err);
610 printk(" done\n"); 651 printk(" done\n");