6

I'm on a redhat machine. I'm changing the value of max_map_count via sysctl:

# sysctl vm.max_map_count
vm.max_map_count = 65530
# sysctl -w vm.max_map_count=655300
vm.max_map_count = 655300
# sysctl vm.max_map_count
vm.max_map_count = 655300

I then write that value to /etc/sysctl.conf so it persists a reboot.

I'm doing this to address the munmap needs of a particular long-lived service. I understand that modifying the sysctl value is immediate for the system. My question is: do I need to restart the individual service in order for this updated setting to take effect against that particular running process, or does the updated count limit apply immediately to the running process?

1 Answer 1

3

Running the below program, I found that the process does not need to be restarted. That is, setting the max_map_count takes effect for all processes immediately.

(I took a subset of code from https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/mem/tunable/max_map_count.c#L171 to write the following. Note that the license from that is GPLv2 or later.)

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>


const char* MAX_MAP_PROC_FILE = "/proc/sys/vm/max_map_count";

/* This is a filter to exclude map entries which aren't accounted
 * for in the vm_area_struct's map_count.
 */
static bool filter_map(const char *line)
{
    char buf[BUFSIZ];
    int ret;

    ret = sscanf(line, "%*p-%*p %*4s %*p %*2d:%*2d %*d %s", buf);
    if (ret != 1)
        return false;

#if defined(__x86_64__) || defined(__x86__)
    /* On x86, there's an old compat vsyscall page */
    if (!strcmp(buf, "[vsyscall]"))
        return true;
#elif defined(__ia64__)
    /* On ia64, the vdso is not a proper mapping */
    if (!strcmp(buf, "[vdso]"))
        return true;
#elif defined(__arm__)
    /* Skip it when run it in aarch64 */
    if ((!strcmp(un.machine, "aarch64"))
    || (!strcmp(un.machine, "aarch64_be")))
        return false;

    /* Older arm kernels didn't label their vdso maps */
    if (!strncmp(line, "ffff0000-ffff1000", 17))
        return true;
#endif

    return false;
}


static long count_maps(pid_t pid)
{
    FILE *fp;
    size_t len;
    char *line = NULL;
    char maps_proc_name[BUFSIZ];
    long map_count = 0;

    snprintf(maps_proc_name, BUFSIZ, "/proc/%d/maps", pid);
    fp = fopen(maps_proc_name, "r");
    if (fp == NULL) {
    fprintf(stderr, "Could not open proc file: %s\n", maps_proc_name);
    exit(1);
    }
    while (getline(&line, &len, fp) != -1) {
        /* exclude vdso and vsyscall */
        if (filter_map(line))
            continue;
        map_count++;
    }
    fclose(fp);

    return map_count;
}


static void update_max_map()
{
    FILE *fp = fopen(MAX_MAP_PROC_FILE, "w");
    if (fp == NULL) {
        fprintf(stderr, "Could not open proc file: %s\n", MAX_MAP_PROC_FILE);
        exit(1);
    }

    fprintf(fp, "%d", 655300);

    fclose(fp);
}

static void map_and_print_count()
{
    int num_lines = 0;
    while (mmap(NULL, 1, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0) != MAP_FAILED)
    {
    }
    printf("mmap failed with errno: %s\n", strerror(errno));

    num_lines = count_maps(getpid());
    printf("number of lines: %d\n", num_lines);
}

int
main(int argc, char* argv[])
{
    int num_lines = 0;
    num_lines = count_maps(getpid());

    printf("number of lines to start: %d\n", num_lines);
    map_and_print_count();

    update_max_map();
    map_and_print_count();

    return 0;
}

Running this gives the following output:

# gcc -Wall -o max_map_count max_map_count.c  && ./max_map_count
number of lines to start: 16
mmap failed with errno: Cannot allocate memory
number of lines: 65531
mmap failed with errno: Cannot allocate memory
number of lines: 655301

Note that the process, after updating the max_map_count, was now able to grab the specified number of maps while the process was running.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .