Re: [PATCH v3] hugetlb: only adjust reservation during unmapping if mapcount is 0

Guillaume Morin <[email protected]>
Newsgroups org.kvack.linux-mm
Message-ID <[email protected]>
On 30 Jul 15:01, Andrew Morton wrote:
>
> On Tue, 28 Jul 2026 21:29:03 +0200 Guillaume Morin <[email protected]> wrote:
> 
> > Since df7a6d1f6405, __unmap_hugepage_range can adjust reservations. In
> > the case of folio mapped in both a parent and a child, if the parent
> > unmaps the range first, the reservation adjustment will result in
> > an underflow of the reserved count. Once the child unmaps the range, the
> > count is restored.
> > Change __unmap_hugepage_range() to check the mapcount before adjusting
> > the reservation.
> 
> Thanks.  AI review mentions a couple of things, one pre-existing:
> 	https://sashiko.dev/#/patchset/[email protected]
 
Not sure about the pre-existing one, perhaps Bruno/Rik can comment?

But if I understand the bot scenario correctly, the new issue is
incorrect.

The bot is correct that during the 2nd fault region_add() will
return 0 when the new reservation is committed. But that return value is
changed into a 1 at the end of __vma_reservation_common() for private
mappings (there is a lengthy comment about that). Therefore it does not
fallback to the 'hugepage_subpool_put_pages(spool, 1)' path and
therefore there shouldn't be any resv count change.

I wrote a quick repro of the scenario as I understand it and the
reserved count is as expected.

#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

int hugetlb_nr_resv_pages(unsigned long *num)
{
       const char* field = "HugePages_Rsvd: ";
       FILE *f = fopen("/proc/meminfo", "r");
       char line[256];

       if (!f) {
               perror("Could not open /proc/meminfo");
               return 0;
       }
       while (fgets(line, sizeof(line), f)) {
               if (strncmp(line, field, strlen(field)))
                       continue;
               const char *p = line + strlen(field);
               while (*p && isspace(*p))
                       ++p;
               if (!*p) {
                       break;
               }
               *num = strtoul(p, NULL, 10);
               fclose(f);
               return 1;
       }
       fclose(f);
       return 0;
}

int main(void) {
    pid_t pid;
    unsigned long num;
    void *mem = mmap(NULL, 2048*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
    if (mem == MAP_FAILED) {
        perror("mmap");
        return 1;
    }
    if (!hugetlb_nr_resv_pages(&num)) {
        perror("hugetlb_nr_resv_pages");
        return 1;
    }
    printf("Before the initial fault, number of reserved huge pages: %lu\n", num);
    *(char *)mem = 1;
    if (!hugetlb_nr_resv_pages(&num)) {
        perror("hugetlb_nr_resv_pages");
        return 1;
    }
    printf("After the initial fault, number of reserved huge pages: %lu\n", num);

    pid = fork();
    if (pid == -1) {
        perror("fork");
        return 1;
    }
    if (pid == 0) {
        // Child process
        pause();
        return 0;
    } 
    // Parent process
    if (madvise(mem, 2048*1024, MADV_DONTNEED)) {
        perror("madvise");
        return 1;
    }
    if (!hugetlb_nr_resv_pages(&num)) {
        perror("hugetlb_nr_resv_pages");
        return 1;
    }
    printf("After MADV_DONTNEED, number of reserved huge pages: %lu\n", num);
    if (!hugetlb_nr_resv_pages(&num)) {
        perror("hugetlb_nr_resv_pages");
        return 1;
    }
    *(char *)mem = 1;
    if (!hugetlb_nr_resv_pages(&num)) {
        perror("hugetlb_nr_resv_pages");
        return 1;
    }
    printf("After the new fault, number of reserved huge pages: %lu\n", num);
    kill(pid, SIGINT);

    return 0;
}


-- 
Guillaume Morin <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.