rev |
line source |
pascal@20261
|
1 --- linux-3.16.53/init/initramfs.c
|
pascal@20261
|
2 +++ linux-3.16.53/init/initramfs.c
|
pascal@20261
|
3 @@ -384,6 +384,52 @@
|
pankso@12285
|
4 [Reset] = do_reset,
|
pankso@12285
|
5 };
|
pankso@12285
|
6
|
pankso@12285
|
7 +#include <linux/initrd.h>
|
pankso@12285
|
8 +#define INITRD_PAGE ((PAGE_SIZE > 64*1024) ? PAGE_SIZE : 64*1024)
|
pankso@12285
|
9 +#define INITRD_DOT (1024*1024)
|
pankso@12285
|
10 +
|
pankso@12285
|
11 +static void free_rootfs_mem(unsigned long start, unsigned long end)
|
pankso@12285
|
12 +{
|
pascal@20279
|
13 + free_init_pages(NULL, start, end);
|
pankso@12285
|
14 +}
|
pankso@12285
|
15 +
|
pankso@12285
|
16 +static void _free_initrd(unsigned long initrd_start, unsigned long initrd_end,
|
pankso@12285
|
17 + void (*free_initrd_mem)(unsigned long, unsigned long));
|
pankso@12285
|
18 +
|
pankso@12285
|
19 +static struct {
|
pascal@17037
|
20 + unsigned long offset, last, inptr, freed;
|
pankso@12285
|
21 + char *max;
|
pankso@12285
|
22 +} fill;
|
pankso@12285
|
23 +
|
pankso@12285
|
24 +static void release_inbuf(unsigned n)
|
pankso@12285
|
25 +{
|
pankso@12285
|
26 + if (n >= INITRD_PAGE) {
|
pascal@17037
|
27 + unsigned long rem = n % INITRD_PAGE;
|
pascal@17037
|
28 + unsigned long end = initrd_start + n - rem;
|
pankso@12285
|
29 + _free_initrd(initrd_start, end, free_rootfs_mem);
|
pankso@12285
|
30 + fill.freed += n - rem;
|
pankso@12285
|
31 + if (fill.freed >= INITRD_DOT) {
|
pankso@12285
|
32 + fill.freed -= INITRD_DOT;
|
pankso@12285
|
33 + printk(".");
|
pankso@12285
|
34 + }
|
pankso@12285
|
35 + initrd_start = end;
|
pankso@12285
|
36 + fill.offset = rem;
|
pankso@12285
|
37 + }
|
pankso@12285
|
38 +}
|
pankso@12285
|
39 +
|
pascal@17037
|
40 +static unsigned long fill_buffer(void *buffer, unsigned size)
|
pankso@12285
|
41 +{
|
pascal@17037
|
42 + unsigned long max = fill.max - (char *) initrd_start - fill.offset;
|
pankso@12285
|
43 + if (max > size) max = size;
|
pankso@12285
|
44 + if (max > INITRD_PAGE) max = INITRD_PAGE;
|
pankso@12285
|
45 + memcpy(buffer, (void *)(initrd_start + fill.offset), max);
|
pankso@12285
|
46 + release_inbuf(fill.offset);
|
pankso@12285
|
47 + fill.offset += max;
|
pankso@12285
|
48 + fill.inptr += fill.last;
|
pankso@12285
|
49 + fill.last = max;
|
pankso@12285
|
50 + return max;
|
pankso@12285
|
51 +}
|
pankso@12285
|
52 +
|
pankso@12285
|
53 static int __init write_buffer(char *buf, unsigned len)
|
pankso@12285
|
54 {
|
pankso@12285
|
55 count = len;
|
pascal@20261
|
56 @@ -427,6 +473,7 @@
|
pankso@12285
|
57 decompress_fn decompress;
|
pankso@12285
|
58 const char *compress_name;
|
pankso@12285
|
59 static __initdata char msg_buf[64];
|
pankso@12285
|
60 + int early_free_initrd = (buf == (char *) initrd_start);
|
pankso@12285
|
61
|
pankso@12285
|
62 header_buf = kmalloc(110, GFP_KERNEL);
|
pankso@12285
|
63 symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
|
pascal@20261
|
64 @@ -440,11 +487,16 @@
|
pankso@12285
|
65 message = NULL;
|
pankso@12285
|
66 while (!message && len) {
|
pankso@12285
|
67 loff_t saved_offset = this_header;
|
pankso@12285
|
68 + fill.offset = buf - (char *) initrd_start;
|
pankso@12285
|
69 + fill.max = buf + len;
|
pankso@12285
|
70 + fill.inptr = fill.last = fill.freed = 0;
|
pankso@12285
|
71 if (*buf == '0' && !(this_header & 3)) {
|
pankso@12285
|
72 state = Start;
|
pankso@12285
|
73 written = write_buffer(buf, len);
|
pankso@12285
|
74 buf += written;
|
pankso@12285
|
75 len -= written;
|
pankso@12285
|
76 + if (early_free_initrd)
|
pankso@12285
|
77 + release_inbuf(buf - (char *) initrd_start);
|
pankso@12285
|
78 continue;
|
pankso@12285
|
79 }
|
pankso@12285
|
80 if (!*buf) {
|
pascal@20261
|
81 @@ -457,7 +509,12 @@
|
pankso@12285
|
82 decompress = decompress_method(buf, len, &compress_name);
|
pascal@20261
|
83 pr_debug("Detected %s compressed data\n", compress_name);
|
pankso@12285
|
84 if (decompress) {
|
pankso@12285
|
85 - res = decompress(buf, len, NULL, flush_buffer, NULL,
|
pankso@12285
|
86 + if (early_free_initrd) {
|
pankso@12285
|
87 + res = decompress(NULL, 0, fill_buffer,
|
pankso@12285
|
88 + flush_buffer, NULL, &my_inptr, error);
|
pankso@12285
|
89 + my_inptr += fill.inptr;
|
pankso@12285
|
90 + }
|
pankso@12285
|
91 + else res = decompress(buf, len, NULL, flush_buffer, NULL,
|
pankso@12285
|
92 &my_inptr, error);
|
pankso@12285
|
93 if (res)
|
pankso@12285
|
94 error("decompressor failed");
|
pascal@20261
|
95 @@ -499,7 +556,8 @@
|
pankso@12285
|
96 #include <linux/initrd.h>
|
pankso@12285
|
97 #include <linux/kexec.h>
|
pankso@12285
|
98
|
pankso@12285
|
99 -static void __init free_initrd(void)
|
pankso@12285
|
100 +static void _free_initrd(unsigned long initrd_start, unsigned long initrd_end,
|
pankso@12285
|
101 + void (*free_initrd_mem)(unsigned long, unsigned long))
|
pankso@12285
|
102 {
|
pankso@12285
|
103 #ifdef CONFIG_KEXEC
|
pankso@12285
|
104 unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
|
pascal@20261
|
105 @@ -527,6 +585,12 @@
|
pankso@12285
|
106 #endif
|
pankso@12285
|
107 free_initrd_mem(initrd_start, initrd_end);
|
pankso@12285
|
108 skip:
|
pankso@12285
|
109 + ;
|
pankso@12285
|
110 +}
|
pankso@12285
|
111 +
|
pankso@12285
|
112 +static void __init free_initrd(void)
|
pankso@12285
|
113 +{
|
pankso@12285
|
114 + _free_initrd(initrd_start, initrd_end, free_initrd_mem);
|
pankso@12285
|
115 initrd_start = 0;
|
pankso@12285
|
116 initrd_end = 0;
|
pankso@12285
|
117 }
|