All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lucas De Marchi <lucas.de.marchi@gmail.com>
To: linux-modules@vger.kernel.org
Cc: Luis Chamberlain <mcgrof@kernel.org>,
	Lucas De Marchi <lucas.de.marchi@gmail.com>
Subject: [PATCH 5/5] libkmod: Use kernel decompression when available
Date: Thu,  1 Jun 2023 15:40:01 -0700	[thread overview]
Message-ID: <20230601224001.23397-6-lucas.de.marchi@gmail.com> (raw)
In-Reply-To: <20230601224001.23397-1-lucas.de.marchi@gmail.com>

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

When using kernel compression now it's also possible to direct libkmod
to take the finit_module() path, avoiding the decompression in userspace
and just delegating it to the kernel.

Before:
	read(3, "(\265/\375\244\0", 6)          = 6
	lseek(3, 0, SEEK_SET)                   = 0
	read(3, "(\265/\375\244", 5)            = 5
	mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3fa431e000
	read(3, "\0\244\3\0\\y\6", 7)           = 7
	mmap(NULL, 372736, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3fa414f000
	brk(0x55944c6a1000)                     = 0x55944c6a1000
	read(3, "\356|\6G\27U\20 \312\260s\211\335\333\263\326\330\336\273O\211\356\306K\360Z\341\374U6\342\221"..., 53038) = 53038
	mremap(0x7f3fa431e000, 135168, 266240, MREMAP_MAYMOVE) = 0x7f3fa410e000
	read(3, ",;\3\nqf\311\362\325\211\7\341\375A\355\221\371L\\\5\7\375 \32\246<(\258=K\304"..., 20851) = 20851
	mremap(0x7f3fa410e000, 266240, 397312, MREMAP_MAYMOVE) = 0x7f3fa40ad000
	read(3, ")\36\250\213", 4)              = 4
	read(3, "", 4)                          = 0
	munmap(0x7f3fa414f000, 372736)          = 0
	init_module(0x7f3fa40ad010, 238592, "") = 0
	munmap(0x7f3fa40ad000, 397312)          = 0
	close(3)                                = 0

After:
	read(3, "(\265/\375\244P", 6)           = 6
	lseek(3, 0, SEEK_SET)                   = 0
	finit_module(3, "", 0x4 /* MODULE_INIT_??? */) = 0
	close(3)                                = 0

Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
---
 libkmod/libkmod-file.c     |  4 ++--
 libkmod/libkmod-internal.h |  3 ++-
 libkmod/libkmod-module.c   | 17 +++++++++++++----
 libkmod/libkmod.c          |  5 +++++
 4 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/libkmod/libkmod-file.c b/libkmod/libkmod-file.c
index 705770a..ffdda92 100644
--- a/libkmod/libkmod-file.c
+++ b/libkmod/libkmod-file.c
@@ -513,9 +513,9 @@ off_t kmod_file_get_size(const struct kmod_file *file)
 	return file->size;
 }
 
-bool kmod_file_get_direct(const struct kmod_file *file)
+enum kmod_file_compression_type kmod_file_get_compression(const struct kmod_file *file)
 {
-	return file->compression == KMOD_FILE_COMPRESSION_NONE;
+	return file->compression;
 }
 
 int kmod_file_get_fd(const struct kmod_file *file)
diff --git a/libkmod/libkmod-internal.h b/libkmod/libkmod-internal.h
index 7b8a158..edb4eac 100644
--- a/libkmod/libkmod-internal.h
+++ b/libkmod/libkmod-internal.h
@@ -112,6 +112,7 @@ void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod, const c
 void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod, const char *key) __attribute__((nonnull(1, 2, 3)));
 
 const struct kmod_config *kmod_get_config(const struct kmod_ctx *ctx) __attribute__((nonnull(1)));
+enum kmod_file_compression_type kmod_get_kernel_compression(const struct kmod_ctx *ctx) __attribute__((nonnull(1)));
 
 /* libkmod-config.c */
 struct kmod_config_path {
@@ -162,7 +163,7 @@ struct kmod_elf *kmod_file_get_elf(struct kmod_file *file) __attribute__((nonnul
 int kmod_file_load_contents(struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 void *kmod_file_get_contents(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 off_t kmod_file_get_size(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
-bool kmod_file_get_direct(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
+enum kmod_file_compression_type kmod_file_get_compression(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 int kmod_file_get_fd(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 void kmod_file_unref(struct kmod_file *file) __attribute__((nonnull(1)));
 
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index 6ed5ad4..a9e1be8 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -864,15 +864,24 @@ extern long init_module(const void *mem, unsigned long len, const char *args);
 static int do_finit_module(struct kmod_module *mod, unsigned int flags,
 			   const char *args)
 {
+	enum kmod_file_compression_type compression, kernel_compression;
 	unsigned int kernel_flags = 0;
 	int err;
 
 	/*
-	 * Re-use ENOSYS, returned when there is no such syscall, so the
-	 * fallback to init_module applies
+	 * When module is not compressed or its compression type matches the
+	 * one in use by the kernel, there is no need to read the file
+	 * in userspace. Otherwise, re-use ENOSYS to trigger the same fallback
+	 * as when finit_module() is not supported.
 	 */
-	if (!kmod_file_get_direct(mod->file))
-		return -ENOSYS;
+	compression = kmod_file_get_compression(mod->file);
+	kernel_compression = kmod_get_kernel_compression(mod->ctx);
+	if (!(compression == KMOD_FILE_COMPRESSION_NONE ||
+	      compression == kernel_compression))
+		return ENOSYS;
+
+	if (compression != KMOD_FILE_COMPRESSION_NONE)
+		kernel_flags |= MODULE_INIT_COMPRESSED_FILE;
 
 	if (flags & KMOD_INSERT_FORCE_VERMAGIC)
 		kernel_flags |= MODULE_INIT_IGNORE_VERMAGIC;
diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c
index 103469e..1b8773c 100644
--- a/libkmod/libkmod.c
+++ b/libkmod/libkmod.c
@@ -1016,3 +1016,8 @@ const struct kmod_config *kmod_get_config(const struct kmod_ctx *ctx)
 {
 	return ctx->config;
 }
+
+enum kmod_file_compression_type kmod_get_kernel_compression(const struct kmod_ctx *ctx)
+{
+	return ctx->kernel_compression;
+}
-- 
2.40.1


  parent reply	other threads:[~2023-06-01 22:40 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-01 22:39 [PATCH 0/5] libkmod: Use kernel decompression support Lucas De Marchi
2023-06-01 22:39 ` [PATCH 1/5] libkmod: Do not inititialize file->memory on open Lucas De Marchi
2023-06-06 18:24   ` Luis Chamberlain
2023-06-01 22:39 ` [PATCH 2/5] libkmod: Extract finit_module vs init_module paths Lucas De Marchi
2023-06-06 18:27   ` Luis Chamberlain
2023-06-01 22:39 ` [PATCH 3/5] libkmod: Keep track of compression type Lucas De Marchi
2023-06-06 18:28   ` Luis Chamberlain
2023-06-01 22:40 ` [PATCH 4/5] libkmod: Keep track of in-kernel compression support Lucas De Marchi
2023-06-06 18:29   ` Luis Chamberlain
2023-06-06 18:30   ` Luis Chamberlain
2023-06-01 22:40 ` Lucas De Marchi [this message]
2023-06-06 18:38   ` [PATCH 5/5] libkmod: Use kernel decompression when available Luis Chamberlain
2023-06-06 19:01     ` Lucas De Marchi
2023-07-24 13:28 ` [PATCH 0/5] libkmod: Use kernel decompression support Lucas De Marchi
2023-06-15  9:36 [PATCH 5/5] libkmod: Use kernel decompression when available Emil Velikov
2023-06-15 10:09 ` Emil Velikov
2023-06-27 14:05   ` Lucas De Marchi
2023-06-16  5:12 ` Lucas De Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230601224001.23397-6-lucas.de.marchi@gmail.com \
    --to=lucas.de.marchi@gmail.com \
    --cc=linux-modules@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.