diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-25 04:35:22 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-25 04:35:22 +0100 |
commit | 77c066ea5cf4b1ee606a81e48388ff0b1d019134 (patch) | |
tree | b51b001a013a4be3a2ad09fdc22cfdccf29bdbaf | |
parent | 30f3c1d5fdf8999491a01cb3fe8be8a40da52a75 (diff) | |
download | busybox-w32-77c066ea5cf4b1ee606a81e48388ff0b1d019134.tar.gz busybox-w32-77c066ea5cf4b1ee606a81e48388ff0b1d019134.tar.bz2 busybox-w32-77c066ea5cf4b1ee606a81e48388ff0b1d019134.zip |
modutils: add FEATURE_INSMOD_TRY_MMAP option
function old new delta
try_to_mmap_module - 121 +121
bb_init_module_24 4514 4578 +64
bb_init_module 119 173 +54
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 239/0) Total: 239 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | modutils/Config.in | 16 | ||||
-rw-r--r-- | modutils/modutils-24.c | 25 | ||||
-rw-r--r-- | modutils/modutils.c | 63 | ||||
-rw-r--r-- | modutils/modutils.h | 6 |
4 files changed, 93 insertions, 17 deletions
diff --git a/modutils/Config.in b/modutils/Config.in index d2a2e04d1..83c12b67f 100644 --- a/modutils/Config.in +++ b/modutils/Config.in | |||
@@ -121,6 +121,22 @@ config FEATURE_2_4_MODULES | |||
121 | This increases size considerably. Say N unless you plan | 121 | This increases size considerably. Say N unless you plan |
122 | to run ancient kernels. | 122 | to run ancient kernels. |
123 | 123 | ||
124 | config FEATURE_INSMOD_TRY_MMAP | ||
125 | bool "Try to load module from a mmap'ed area" | ||
126 | default n | ||
127 | depends on INSMOD || MODPROBE_SMALL | ||
128 | help | ||
129 | This option causes module loading code to try to mmap | ||
130 | module first. If it does not work (for example, | ||
131 | it does not work for compressed modules), module will be read | ||
132 | (and unpacked if needed) into a memory block allocated by malloc. | ||
133 | |||
134 | The only case when mmap works but malloc does not is when | ||
135 | you are trying to load a big module on a very memory-constrained | ||
136 | machine. Malloc will momentarily need 2x as much memory as mmap. | ||
137 | |||
138 | Choosing N saves about 250 bytes of code (on 32-bit x86). | ||
139 | |||
124 | config FEATURE_INSMOD_VERSION_CHECKING | 140 | config FEATURE_INSMOD_VERSION_CHECKING |
125 | bool "Enable module version checking" | 141 | bool "Enable module version checking" |
126 | default n | 142 | default n |
diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c index e5ff54d29..a878e740c 100644 --- a/modutils/modutils-24.c +++ b/modutils/modutils-24.c | |||
@@ -3783,12 +3783,20 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options) | |||
3783 | int m_has_modinfo; | 3783 | int m_has_modinfo; |
3784 | #endif | 3784 | #endif |
3785 | char *image; | 3785 | char *image; |
3786 | size_t image_size = 64 * 1024 * 1024; | 3786 | size_t image_size; |
3787 | 3787 | bool mmaped; | |
3788 | /* Load module into memory and unzip if compressed */ | 3788 | |
3789 | image = xmalloc_open_zipped_read_close(m_filename, &image_size); | 3789 | image_size = INT_MAX - 4095; |
3790 | if (!image) | 3790 | mmaped = 0; |
3791 | return EXIT_FAILURE; | 3791 | image = try_to_mmap_module(m_filename, &image_size); |
3792 | if (image) { | ||
3793 | mmaped = 1; | ||
3794 | } else { | ||
3795 | /* Load module into memory and unzip if compressed */ | ||
3796 | image = xmalloc_open_zipped_read_close(m_filename, &image_size); | ||
3797 | if (!image) | ||
3798 | return EXIT_FAILURE; | ||
3799 | } | ||
3792 | 3800 | ||
3793 | m_name = xstrdup(bb_basename(m_filename)); | 3801 | m_name = xstrdup(bb_basename(m_filename)); |
3794 | /* "module.o[.gz]" -> "module" */ | 3802 | /* "module.o[.gz]" -> "module" */ |
@@ -3901,7 +3909,10 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options) | |||
3901 | exit_status = EXIT_SUCCESS; | 3909 | exit_status = EXIT_SUCCESS; |
3902 | 3910 | ||
3903 | out: | 3911 | out: |
3904 | free(image); | 3912 | if (mmaped) |
3913 | munmap(image, image_size); | ||
3914 | else | ||
3915 | free(image); | ||
3905 | free(m_name); | 3916 | free(m_name); |
3906 | 3917 | ||
3907 | return exit_status; | 3918 | return exit_status; |
diff --git a/modutils/modutils.c b/modutils/modutils.c index 969926db9..850a8683b 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
@@ -62,7 +62,7 @@ char* FAST_FUNC filename2modname(const char *filename, char *modname) | |||
62 | return modname; | 62 | return modname; |
63 | } | 63 | } |
64 | 64 | ||
65 | char * FAST_FUNC parse_cmdline_module_options(char **argv) | 65 | char* FAST_FUNC parse_cmdline_module_options(char **argv) |
66 | { | 66 | { |
67 | char *options; | 67 | char *options; |
68 | int optlen; | 68 | int optlen; |
@@ -77,6 +77,40 @@ char * FAST_FUNC parse_cmdline_module_options(char **argv) | |||
77 | return options; | 77 | return options; |
78 | } | 78 | } |
79 | 79 | ||
80 | #if ENABLE_FEATURE_INSMOD_TRY_MMAP | ||
81 | void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) | ||
82 | { | ||
83 | /* We have user reports of failure to load 3MB module | ||
84 | * on a 16MB RAM machine. Apparently even a transient | ||
85 | * memory spike to 6MB during module load | ||
86 | * is too big for that system. */ | ||
87 | void *image; | ||
88 | struct stat st; | ||
89 | int fd; | ||
90 | |||
91 | fd = xopen(filename, O_RDONLY); | ||
92 | fstat(fd, &st); | ||
93 | image = NULL; | ||
94 | /* st.st_size is off_t, we can't just pass it to mmap */ | ||
95 | if (st.st_size <= *image_size_p) { | ||
96 | size_t image_size = st.st_size; | ||
97 | image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
98 | if (image == MAP_FAILED) { | ||
99 | image = NULL; | ||
100 | } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) { | ||
101 | /* No ELF signature. Compressed module? */ | ||
102 | munmap(image, image_size); | ||
103 | image = NULL; | ||
104 | } else { | ||
105 | /* Success. Report the size */ | ||
106 | *image_size_p = image_size; | ||
107 | } | ||
108 | } | ||
109 | close(fd); | ||
110 | return image; | ||
111 | } | ||
112 | #endif | ||
113 | |||
80 | /* Return: | 114 | /* Return: |
81 | * 0 on success, | 115 | * 0 on success, |
82 | * -errno on open/read error, | 116 | * -errno on open/read error, |
@@ -84,9 +118,10 @@ char * FAST_FUNC parse_cmdline_module_options(char **argv) | |||
84 | */ | 118 | */ |
85 | int FAST_FUNC bb_init_module(const char *filename, const char *options) | 119 | int FAST_FUNC bb_init_module(const char *filename, const char *options) |
86 | { | 120 | { |
87 | size_t len; | 121 | size_t image_size; |
88 | char *image; | 122 | char *image; |
89 | int rc; | 123 | int rc; |
124 | bool mmaped; | ||
90 | 125 | ||
91 | if (!options) | 126 | if (!options) |
92 | options = ""; | 127 | options = ""; |
@@ -97,17 +132,25 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options) | |||
97 | return bb_init_module_24(filename, options); | 132 | return bb_init_module_24(filename, options); |
98 | #endif | 133 | #endif |
99 | 134 | ||
100 | /* Use the 2.6 way */ | 135 | image_size = INT_MAX - 4095; |
101 | len = INT_MAX - 4095; | 136 | mmaped = 0; |
102 | errno = ENOMEM; /* may be changed by e.g. open errors below */ | 137 | image = try_to_mmap_module(filename, &image_size); |
103 | image = xmalloc_open_zipped_read_close(filename, &len); | 138 | if (image) { |
104 | if (!image) | 139 | mmaped = 1; |
105 | return -errno; | 140 | } else { |
141 | errno = ENOMEM; /* may be changed by e.g. open errors below */ | ||
142 | image = xmalloc_open_zipped_read_close(filename, &image_size); | ||
143 | if (!image) | ||
144 | return -errno; | ||
145 | } | ||
106 | 146 | ||
107 | errno = 0; | 147 | errno = 0; |
108 | init_module(image, len, options); | 148 | init_module(image, image_size, options); |
109 | rc = errno; | 149 | rc = errno; |
110 | free(image); | 150 | if (mmaped) |
151 | munmap(image, image_size); | ||
152 | else | ||
153 | free(image); | ||
111 | return rc; | 154 | return rc; |
112 | } | 155 | } |
113 | 156 | ||
diff --git a/modutils/modutils.h b/modutils/modutils.h index 1cf4bba95..131a5087b 100644 --- a/modutils/modutils.h +++ b/modutils/modutils.h | |||
@@ -51,6 +51,12 @@ enum { | |||
51 | #endif | 51 | #endif |
52 | }; | 52 | }; |
53 | 53 | ||
54 | #if ENABLE_FEATURE_INSMOD_TRY_MMAP | ||
55 | void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p); | ||
56 | #else | ||
57 | # define try_to_mmap_module(filename, image_size) NULL | ||
58 | #endif | ||
59 | |||
54 | /* Return: | 60 | /* Return: |
55 | * 0 on success, | 61 | * 0 on success, |
56 | * -errno on open/read error, | 62 | * -errno on open/read error, |