linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / init / initramfs.c
index 6d70d82..07cd51c 100644 (file)
@@ -26,12 +26,10 @@ static void __init free(void *where)
 
 /* link hash */
 
-#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
-
 static __initdata struct hash {
        int ino, minor, major;
        struct hash *next;
-       char name[N_ALIGN(PATH_MAX)];
+       char *name;
 } *head[32];
 
 static inline int hash(int major, int minor, int ino)
@@ -59,7 +57,7 @@ static char __init *find_link(int major, int minor, int ino, char *name)
        q->ino = ino;
        q->minor = minor;
        q->major = major;
-       strcpy(q->name, name);
+       q->name = name;
        q->next = NULL;
        *p = q;
        return NULL;
@@ -135,6 +133,8 @@ static inline void eat(unsigned n)
        count -= n;
 }
 
+#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
+
 static __initdata char *collected;
 static __initdata int remains;
 static __initdata char *collect;
@@ -249,6 +249,7 @@ static int __init do_name(void)
        if (dry_run)
                return 0;
        if (S_ISREG(mode)) {
+               sys_unlink(collected);
                if (maybe_link() >= 0) {
                        wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
                        if (wfd >= 0) {
@@ -263,6 +264,7 @@ static int __init do_name(void)
                sys_chmod(collected, mode);
        } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
+               sys_unlink(collected);
                if (maybe_link() == 0) {
                        sys_mknod(collected, mode, rdev);
                        sys_chown(collected, uid, gid);
@@ -291,6 +293,7 @@ static int __init do_copy(void)
 static int __init do_symlink(void)
 {
        collected[N_ALIGN(name_len) + body_len] = '\0';
+       sys_unlink(collected);
        sys_symlink(collected + N_ALIGN(name_len), collected);
        sys_lchown(collected, uid, gid);
        state = SkipIt;
@@ -466,6 +469,36 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
 extern char __initramfs_start[], __initramfs_end[];
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/initrd.h>
+#include <linux/kexec.h>
+
+static void __init free_initrd(void)
+{
+#ifdef CONFIG_KEXEC
+       unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
+       unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
+
+       /*
+        * If the initrd region is overlapped with crashkernel reserved region,
+        * free only memory that is not part of crashkernel region.
+        */
+       if (initrd_start < crashk_end && initrd_end > crashk_start) {
+               /*
+                * Initialize initrd memory region since the kexec boot does
+                * not do.
+                */
+               memset((void *)initrd_start, 0, initrd_end - initrd_start);
+               if (initrd_start < crashk_start)
+                       free_initrd_mem(initrd_start, crashk_start);
+               if (initrd_end > crashk_end)
+                       free_initrd_mem(crashk_end, initrd_end);
+       } else
+#endif
+               free_initrd_mem(initrd_start, initrd_end);
+
+       initrd_start = 0;
+       initrd_end = 0;
+}
+
 #endif
 
 void __init populate_rootfs(void)
@@ -484,7 +517,7 @@ void __init populate_rootfs(void)
                        printk(" it is\n");
                        unpack_to_rootfs((char *)initrd_start,
                                initrd_end - initrd_start, 0);
-                       free_initrd_mem(initrd_start, initrd_end);
+                       free_initrd();
                        return;
                }
                printk("it isn't (%s); looks like an initrd\n", err);
@@ -493,7 +526,7 @@ void __init populate_rootfs(void)
                        sys_write(fd, (char *)initrd_start,
                                        initrd_end - initrd_start);
                        sys_close(fd);
-                       free_initrd_mem(initrd_start, initrd_end);
+                       free_initrd();
                }
        }
 #endif