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>
This commit is contained in:
Denys Vlasenko 2009-10-25 04:35:22 +01:00
parent 30f3c1d5fd
commit 77c066ea5c
4 changed files with 92 additions and 16 deletions

View File

@ -121,6 +121,22 @@ config FEATURE_2_4_MODULES
This increases size considerably. Say N unless you plan
to run ancient kernels.
config FEATURE_INSMOD_TRY_MMAP
bool "Try to load module from a mmap'ed area"
default n
depends on INSMOD || MODPROBE_SMALL
help
This option causes module loading code to try to mmap
module first. If it does not work (for example,
it does not work for compressed modules), module will be read
(and unpacked if needed) into a memory block allocated by malloc.
The only case when mmap works but malloc does not is when
you are trying to load a big module on a very memory-constrained
machine. Malloc will momentarily need 2x as much memory as mmap.
Choosing N saves about 250 bytes of code (on 32-bit x86).
config FEATURE_INSMOD_VERSION_CHECKING
bool "Enable module version checking"
default n

View File

@ -3783,12 +3783,20 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
int m_has_modinfo;
#endif
char *image;
size_t image_size = 64 * 1024 * 1024;
size_t image_size;
bool mmaped;
/* Load module into memory and unzip if compressed */
image = xmalloc_open_zipped_read_close(m_filename, &image_size);
if (!image)
return EXIT_FAILURE;
image_size = INT_MAX - 4095;
mmaped = 0;
image = try_to_mmap_module(m_filename, &image_size);
if (image) {
mmaped = 1;
} else {
/* Load module into memory and unzip if compressed */
image = xmalloc_open_zipped_read_close(m_filename, &image_size);
if (!image)
return EXIT_FAILURE;
}
m_name = xstrdup(bb_basename(m_filename));
/* "module.o[.gz]" -> "module" */
@ -3901,7 +3909,10 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
exit_status = EXIT_SUCCESS;
out:
free(image);
if (mmaped)
munmap(image, image_size);
else
free(image);
free(m_name);
return exit_status;

View File

@ -62,7 +62,7 @@ char* FAST_FUNC filename2modname(const char *filename, char *modname)
return modname;
}
char * FAST_FUNC parse_cmdline_module_options(char **argv)
char* FAST_FUNC parse_cmdline_module_options(char **argv)
{
char *options;
int optlen;
@ -77,6 +77,40 @@ char * FAST_FUNC parse_cmdline_module_options(char **argv)
return options;
}
#if ENABLE_FEATURE_INSMOD_TRY_MMAP
void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
{
/* We have user reports of failure to load 3MB module
* on a 16MB RAM machine. Apparently even a transient
* memory spike to 6MB during module load
* is too big for that system. */
void *image;
struct stat st;
int fd;
fd = xopen(filename, O_RDONLY);
fstat(fd, &st);
image = NULL;
/* st.st_size is off_t, we can't just pass it to mmap */
if (st.st_size <= *image_size_p) {
size_t image_size = st.st_size;
image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (image == MAP_FAILED) {
image = NULL;
} else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) {
/* No ELF signature. Compressed module? */
munmap(image, image_size);
image = NULL;
} else {
/* Success. Report the size */
*image_size_p = image_size;
}
}
close(fd);
return image;
}
#endif
/* Return:
* 0 on success,
* -errno on open/read error,
@ -84,9 +118,10 @@ char * FAST_FUNC parse_cmdline_module_options(char **argv)
*/
int FAST_FUNC bb_init_module(const char *filename, const char *options)
{
size_t len;
size_t image_size;
char *image;
int rc;
bool mmaped;
if (!options)
options = "";
@ -97,17 +132,25 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options)
return bb_init_module_24(filename, options);
#endif
/* Use the 2.6 way */
len = INT_MAX - 4095;
errno = ENOMEM; /* may be changed by e.g. open errors below */
image = xmalloc_open_zipped_read_close(filename, &len);
if (!image)
return -errno;
image_size = INT_MAX - 4095;
mmaped = 0;
image = try_to_mmap_module(filename, &image_size);
if (image) {
mmaped = 1;
} else {
errno = ENOMEM; /* may be changed by e.g. open errors below */
image = xmalloc_open_zipped_read_close(filename, &image_size);
if (!image)
return -errno;
}
errno = 0;
init_module(image, len, options);
init_module(image, image_size, options);
rc = errno;
free(image);
if (mmaped)
munmap(image, image_size);
else
free(image);
return rc;
}

View File

@ -51,6 +51,12 @@ enum {
#endif
};
#if ENABLE_FEATURE_INSMOD_TRY_MMAP
void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p);
#else
# define try_to_mmap_module(filename, image_size) NULL
#endif
/* Return:
* 0 on success,
* -errno on open/read error,