# HG changeset patch # User Pascal Bellard # Date 1249940359 -7200 # Node ID 22410fa562c70a816ec9720ec84dcd5992e8046e # Parent d7465f7f9abbf152cb7d602b5bb50a50885321d6 linux: free initrd cpio data earlier diff -r d7465f7f9abb -r 22410fa562c7 linux/receipt --- a/linux/receipt Mon Aug 10 12:33:20 2009 +0000 +++ b/linux/receipt Mon Aug 10 23:39:19 2009 +0200 @@ -34,6 +34,7 @@ done <> PAGE_SHIFT); + +- printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); ++ if (what) printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); + + for (; addr < end; addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + +--- linux-2.6.30.4/init/initramfs.c ++++ linux-2.6.30.4/init/initramfs.c +@@ -374,6 +374,47 @@ + [Reset] = do_reset, + }; + ++#include ++#define INITRD_PAGE ((PAGE_SIZE > 1024*1024) ? PAGE_SIZE : 1024*1024) ++ ++static void free_rootfs_mem(unsigned long start, unsigned long end) ++{ ++ free_init_pages(NULL, start, end); ++} ++ ++static void _free_initrd(unsigned long initrd_start, unsigned long initrd_end, ++ void (*free_initrd_mem)(unsigned long, unsigned long)); ++ ++static struct { ++ int offset, last, inptr; ++ char *max; ++} fill; ++ ++static void release_inbuf(void) ++{ ++ if (fill.offset >= INITRD_PAGE) { ++ unsigned rem = fill.offset % INITRD_PAGE; ++ unsigned end = initrd_start + fill.offset - rem; ++ _free_initrd(initrd_start, end, free_rootfs_mem); ++ printk("."); ++ initrd_start = end; ++ fill.offset = rem; ++ } ++} ++ ++static int fill_buffer(void *buffer, unsigned size) ++{ ++ int max = fill.max - (char *) initrd_start - fill.offset; ++ if (max > size) max = size; ++ if (max > INITRD_PAGE) max = INITRD_PAGE; ++ memcpy(buffer, (void *)(initrd_start + fill.offset), max); ++ fill.offset += max; ++ release_inbuf(); ++ fill.inptr += fill.last; ++ fill.last = max; ++ return max; ++} ++ + static int __init write_buffer(char *buf, unsigned len) + { + count = len; +@@ -417,6 +458,7 @@ + decompress_fn decompress; + const char *compress_name; + static __initdata char msg_buf[64]; ++ int early_free_initrd = (buf == (char *) initrd_start); + + header_buf = kmalloc(110, GFP_KERNEL); + symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); +@@ -430,8 +472,31 @@ + message = NULL; + while (!message && len) { + loff_t saved_offset = this_header; ++ fill.offset = buf - (char *) initrd_start; ++ fill.max = buf + len; ++ fill.inptr = fill.last = 0; + if (*buf == '0' && !(this_header & 3)) { + state = Start; ++ if (early_free_initrd) { ++ while (len) { ++ unsigned n = len, tofree; ++ if (n > INITRD_PAGE) ++ n = INITRD_PAGE; ++ flush_buffer(buf, n); ++ buf += n; ++ len -= n; ++ n = buf - (char *) initrd_start; ++ tofree = n - (n % INITRD_PAGE); ++ if (!tofree) ++ continue; ++ _free_initrd(initrd_start, ++ initrd_start + tofree, ++ free_rootfs_mem); ++ initrd_start += tofree; ++ printk("."); ++ } ++ continue; ++ } + written = write_buffer(buf, len); + buf += written; + len -= written; +@@ -445,9 +510,15 @@ + } + this_header = 0; + decompress = decompress_method(buf, len, &compress_name); +- if (decompress) +- decompress(buf, len, NULL, flush_buffer, NULL, ++ if (decompress) { ++ if (early_free_initrd) { ++ decompress(NULL, 0, fill_buffer, flush_buffer, ++ NULL, &my_inptr, error); ++ my_inptr += fill.inptr; ++ } ++ else decompress(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error); ++ } + else if (compress_name) { + if (!message) { + snprintf(msg_buf, sizeof msg_buf, +@@ -484,7 +555,8 @@ + #include + #include + +-static void __init free_initrd(void) ++static void _free_initrd(unsigned long initrd_start, unsigned long initrd_end, ++ void (*free_initrd_mem)(unsigned long, unsigned long)) + { + #ifdef CONFIG_KEXEC + unsigned long crashk_start = (unsigned long)__va(crashk_res.start); +@@ -512,6 +584,12 @@ + #endif + free_initrd_mem(initrd_start, initrd_end); + skip: ++ ; ++} ++ ++static void __init free_initrd(void) ++{ ++ _free_initrd(initrd_start, initrd_end, free_initrd_mem); + initrd_start = 0; + initrd_end = 0; + }