aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-25 04:35:22 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-25 04:35:22 +0100
commit77c066ea5cf4b1ee606a81e48388ff0b1d019134 (patch)
treeb51b001a013a4be3a2ad09fdc22cfdccf29bdbaf
parent30f3c1d5fdf8999491a01cb3fe8be8a40da52a75 (diff)
downloadbusybox-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.in16
-rw-r--r--modutils/modutils-24.c25
-rw-r--r--modutils/modutils.c63
-rw-r--r--modutils/modutils.h6
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
124config 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
124config FEATURE_INSMOD_VERSION_CHECKING 140config 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
65char * FAST_FUNC parse_cmdline_module_options(char **argv) 65char* 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
81void* 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 */
85int FAST_FUNC bb_init_module(const char *filename, const char *options) 119int 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
55void* 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,