On Tue, Jun 06, 2023 at 11:38:35AM -0700, Luis Chamberlain wrote:
On Thu, Jun 01, 2023 at 03:40:01PM -0700, Lucas De Marchi wrote:
With the recent changes to bypass loading the file it's possible to
reduce the work in userspace and delegating it to the kernel. Without
any compression to illustrate:
Before:
read(3, "\177ELF\2\1", 6) = 6
lseek(3, 0, SEEK_SET) = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=238592, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 238592, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fd85cbd1000
finit_module(3, "", 0) = 0
munmap(0x7fd85cbd1000, 238592) = 0
close(3) = 0
After:
read(3, "\177ELF\2\1", 6) = 6
lseek(3, 0, SEEK_SET) = 0
finit_module(3, "", 0) = 0
close(3) = 0
It's not clear to me how the patches did the above, in particular
avoiding the newfstatat() for the non-decompression use case.
because now we are not taking the path to mmap the file anymore.
From load_reg():
if (fstat(file->fd, &st) < 0)
return -errno;
file->size = st.st_size;
file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE,
file->fd, 0);
from STAT(2):
The underlying system call employed by the glibc fstatat() wrapper
function is actually called fstatat64() or, on some architectures,
newfstatat().
With load_reg() not being called anymore, these 2 syscalls are gone.
We still read the header (first 6 bytes as per above), to make sure we select
the right handler for the compression method. In the case above it was uncompressed
("\177ELF\2\1"), so we lseek() and give it to the kernel. If it was
a compression algo matching the one in use by the kernel, we would just add
the compression flag and do the same thing.
If it was a different compression type, then we'd fallback to the
previous handling with mmap() + decompression in usersapce +
init_module().
Lucas De Marchi
Luis