Possible regression with file madvise(MADV_COLLAPSE)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Linux 6.10.10 with CONFIG_READ_ONLY_THP_FOR_FS=y,
madvise(MADV_COLLAPSE) on  program text fails with EINVAL.

To reproduce, compile the reproducer with

clang -g -o text-hugepage  text-hugepage.c \
	-fuse-ld=lld \
	-Wl,-zcommon-page-size=2097152 -Wl,-zmax-page-size=2097152 \
        -Wl,-z,separate-loadable-segments

and run:

$ strace -e trace=madvise ./text-hugepage
madvise(0x400000, 2097152, MADV_HUGEPAGE) = 0
madvise(0x400000, 2097152, MADV_POPULATE_READ) = 0
madvise(0x400000, 2097152, MADV_COLLAPSE) = -1 EINVAL (Invalid
argument)

(the funky linker options are needed to make sure the .text vma spans a
hugepage).


I say "possible regression" since I haven't tried it with an older
kernel, but I believe it worked at some point or other seeing that
others managed to get it to work.

==== text-hugepage.c ====
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <sys/mman.h>

static
void
try_remap_text_segment() {
    FILE *fp = fopen("/proc/self/maps", "r");
    if (!fp) {
        return;
    }
    char *buf = NULL;
    size_t n;
    while (getline(&buf, &n, fp) >= 0) {
        char *lstart = buf;
        char *lmid = strchr(lstart, '-');
        if (!lmid) {
            continue;
        }
        *lmid++ = '\0';
        char *lend = strchr(lmid, ' ');
        if (!lend) {
            continue;
        }
        *lend = '\0';
        
        size_t start = strtoul(lstart, NULL, 16);
        size_t end = strtoul(lmid, NULL, 16);
        uintptr_t some_text_addr = (uintptr_t)&try_remap_text_segment;
        if (some_text_addr >= start && some_text_addr < end) {
            end &= ~(uintptr_t)0x1fffff;
            madvise((void*)start, end - start, MADV_HUGEPAGE);
            madvise((void*)start, end - start, MADV_POPULATE_READ);
            madvise((void*)start, end - start, MADV_COLLAPSE);
            break;
        }
    }
    free(buf);
    fclose(fp);
}

void
huge_function() {
    // Make sure .text is has a huge page full of stuff
    asm volatile (".fill 4000000, 1, 0x90");
}

int
main() {
    try_remap_text_segment();
}
==== end text-hugepage.c ====





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux