To prepare for supporting boot-time page size selection, refactor code to remove assumptions about PAGE_SIZE being compile-time constant. Code intended to be equivalent when compile-time page size is active. In binfmt_elf, convert CPP conditional to C ternary operator; this will be folded to the same code by the compiler when in compile-time page size mode, but will also work for runtime evaluation in boot-time page size mode. In coredump, modify __dump_skip() to emit zeros in blocks of PAGE_SIZE_MIN. This resolves to the previous PAGE_SIZE for compile-time page size, but that doesn't work for boot-time page size. PAGE_SIZE_MIN is preferred here over PAGE_SIZE_MAX to save memory. Wrap global variables that are initialized with PAGE_SIZE derived values using DEFINE_GLOBAL_PAGE_SIZE_VAR() so their initialization can be deferred for boot-time page size builds. Signed-off-by: Ryan Roberts <ryan.roberts@xxxxxxx> --- ***NOTE*** Any confused maintainers may want to read the cover note here for context: https://lore.kernel.org/all/20241014105514.3206191-1-ryan.roberts@xxxxxxx/ fs/binfmt_elf.c | 11 ++++------- fs/coredump.c | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 19fa49cd9907f..e439d36c43c7e 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -84,11 +84,8 @@ static int elf_core_dump(struct coredump_params *cprm); #define elf_core_dump NULL #endif -#if ELF_EXEC_PAGESIZE > PAGE_SIZE -#define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE -#else -#define ELF_MIN_ALIGN PAGE_SIZE -#endif +#define ELF_MIN_ALIGN \ + (ELF_EXEC_PAGESIZE > PAGE_SIZE ? ELF_EXEC_PAGESIZE : PAGE_SIZE) #ifndef ELF_CORE_EFLAGS #define ELF_CORE_EFLAGS 0 @@ -98,7 +95,7 @@ static int elf_core_dump(struct coredump_params *cprm); #define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1)) #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1)) -static struct linux_binfmt elf_format = { +static DEFINE_GLOBAL_PAGE_SIZE_VAR(struct linux_binfmt, elf_format, { .module = THIS_MODULE, .load_binary = load_elf_binary, .load_shlib = load_elf_library, @@ -106,7 +103,7 @@ static struct linux_binfmt elf_format = { .core_dump = elf_core_dump, .min_coredump = ELF_EXEC_PAGESIZE, #endif -}; +}); #define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE)) diff --git a/fs/coredump.c b/fs/coredump.c index 7f12ff6ad1d3e..203f2a158246e 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -825,7 +825,7 @@ static int __dump_emit(struct coredump_params *cprm, const void *addr, int nr) static int __dump_skip(struct coredump_params *cprm, size_t nr) { - static char zeroes[PAGE_SIZE]; + static char zeroes[PAGE_SIZE_MIN]; struct file *file = cprm->file; if (file->f_mode & FMODE_LSEEK) { if (dump_interrupted() || @@ -834,10 +834,10 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr) cprm->pos += nr; return 1; } else { - while (nr > PAGE_SIZE) { - if (!__dump_emit(cprm, zeroes, PAGE_SIZE)) + while (nr > PAGE_SIZE_MIN) { + if (!__dump_emit(cprm, zeroes, PAGE_SIZE_MIN)) return 0; - nr -= PAGE_SIZE; + nr -= PAGE_SIZE_MIN; } return __dump_emit(cprm, zeroes, nr); } -- 2.43.0