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:
@ -121,6 +121,22 @@ config FEATURE_2_4_MODULES
|
|||||||
This increases size considerably. Say N unless you plan
|
This increases size considerably. Say N unless you plan
|
||||||
to run ancient kernels.
|
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
|
config FEATURE_INSMOD_VERSION_CHECKING
|
||||||
bool "Enable module version checking"
|
bool "Enable module version checking"
|
||||||
default n
|
default n
|
||||||
|
@ -3783,12 +3783,20 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
|
|||||||
int m_has_modinfo;
|
int m_has_modinfo;
|
||||||
#endif
|
#endif
|
||||||
char *image;
|
char *image;
|
||||||
size_t image_size = 64 * 1024 * 1024;
|
size_t image_size;
|
||||||
|
bool mmaped;
|
||||||
|
|
||||||
|
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 */
|
/* Load module into memory and unzip if compressed */
|
||||||
image = xmalloc_open_zipped_read_close(m_filename, &image_size);
|
image = xmalloc_open_zipped_read_close(m_filename, &image_size);
|
||||||
if (!image)
|
if (!image)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
m_name = xstrdup(bb_basename(m_filename));
|
m_name = xstrdup(bb_basename(m_filename));
|
||||||
/* "module.o[.gz]" -> "module" */
|
/* "module.o[.gz]" -> "module" */
|
||||||
@ -3901,6 +3909,9 @@ int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
|
|||||||
exit_status = EXIT_SUCCESS;
|
exit_status = EXIT_SUCCESS;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (mmaped)
|
||||||
|
munmap(image, image_size);
|
||||||
|
else
|
||||||
free(image);
|
free(image);
|
||||||
free(m_name);
|
free(m_name);
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ char* FAST_FUNC filename2modname(const char *filename, char *modname)
|
|||||||
return modname;
|
return modname;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * FAST_FUNC parse_cmdline_module_options(char **argv)
|
char* FAST_FUNC parse_cmdline_module_options(char **argv)
|
||||||
{
|
{
|
||||||
char *options;
|
char *options;
|
||||||
int optlen;
|
int optlen;
|
||||||
@ -77,6 +77,40 @@ char * FAST_FUNC parse_cmdline_module_options(char **argv)
|
|||||||
return options;
|
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:
|
/* Return:
|
||||||
* 0 on success,
|
* 0 on success,
|
||||||
* -errno on open/read error,
|
* -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)
|
int FAST_FUNC bb_init_module(const char *filename, const char *options)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t image_size;
|
||||||
char *image;
|
char *image;
|
||||||
int rc;
|
int rc;
|
||||||
|
bool mmaped;
|
||||||
|
|
||||||
if (!options)
|
if (!options)
|
||||||
options = "";
|
options = "";
|
||||||
@ -97,16 +132,24 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options)
|
|||||||
return bb_init_module_24(filename, options);
|
return bb_init_module_24(filename, options);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Use the 2.6 way */
|
image_size = INT_MAX - 4095;
|
||||||
len = 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 */
|
errno = ENOMEM; /* may be changed by e.g. open errors below */
|
||||||
image = xmalloc_open_zipped_read_close(filename, &len);
|
image = xmalloc_open_zipped_read_close(filename, &image_size);
|
||||||
if (!image)
|
if (!image)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
init_module(image, len, options);
|
init_module(image, image_size, options);
|
||||||
rc = errno;
|
rc = errno;
|
||||||
|
if (mmaped)
|
||||||
|
munmap(image, image_size);
|
||||||
|
else
|
||||||
free(image);
|
free(image);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,12 @@ enum {
|
|||||||
#endif
|
#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:
|
/* Return:
|
||||||
* 0 on success,
|
* 0 on success,
|
||||||
* -errno on open/read error,
|
* -errno on open/read error,
|
||||||
|
Reference in New Issue
Block a user