amarao (amarao_san) wrote,
amarao
amarao_san

The Kernel

Бесконечный менеджмент сжирает всё время, но вот что успелось...

(trivia: война за "исчезающие мегабайты" в pv_ops ядрах под Xen'ом)

упринткашил все функции из nobootmem.c (JFYI: изменение в конфиге настроек вокруг нумы не влияет на ситуацию радикально).

Имеем (3.8.0-rc1+ #6 SMP Wed Dec 26 02:29:43 MSK 2012 x86_64 GNU/Linux), 256Мб.

Отладочный вывод:

free_all_bootmem: nobootmem.c MAX_NUMNODES=1
[ 0.000000] reset_node_lowmem_managed_pages: is_highmem(z)=0, z->managed_pages=3914
[ 0.000000] reset_node_lowmem_managed_pages: is_highmem(z)=0, z->managed_pages=60480
[ 0.000000] reset_node_lowmem_managed_pages: is_highmem(z)=0, z->managed_pages=0
[ 0.000000] reset_node_lowmem_managed_pages: is_highmem(z)=0, z->managed_pages=0

Считаем: (3914+60480)*4=257576к, мы же ожидаем увидеть 262144к, разница 4568к.
Заметим, free в машине показывает 223500к, то есть где-то ещё 30 мб пропало.

Дальше вывод:
[ 0.000000] free_low_memory_core_early: start=65536, end=630784, __free_memory_core(start, end)=138, count=138
[ 0.000000] free_low_memory_core_early: start=1048576, end=16777216, __free_memory_core(start, end)=3840, count=3978
[ 0.000000] free_low_memory_core_early: start=27643904, end=31371264, __free_memory_core(start, end)=910, count=4888
[ 0.000000] free_low_memory_core_early: start=31780864, end=31903744, __free_memory_core(start, end)=30, count=4918
[ 0.000000] free_low_memory_core_early: start=54112256, end=54636544, __free_memory_core(start, end)=128, count=5046
[ 0.000000] free_low_memory_core_early: start=54648832, end=54661120, __free_memory_core(start, end)=3, count=5049
[ 0.000000] free_low_memory_core_early: start=54775808, end=134217664, __free_memory_core(start, end)=19394, count=24443
[ 0.000000] free_low_memory_core_early: start=134217728, end=253755392, __free_memory_core(start, end)=29184, count=53627
[ 0.000000] free_low_memory_core_early: start=257949696, end=260026368, __free_memory_core(start, end)=507, count=54134
[ 0.000000] free_low_memory_core_early: start=260042752, end=264241152, __free_memory_core(start, end)=1025, count=55159
[ 0.000000] free_low_memory_core_early: start=264355840, end=267290816, __free_memory_core(start, end)=716, count=55875
[ 0.000000] free_low_memory_core_early: start=267684624, end=267684672, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267684680, end=267684736, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267684740, end=267684800, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267684808, end=267684864, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267684872, end=267684928, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267693232, end=267693248, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267693360, end=267693376, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267693408, end=267693440, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267693544, end=267693568, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267693672, end=267693696, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267693800, end=267693824, __free_memory_core(start, end)=0, count=55875
[ 0.000000] free_low_memory_core_early: start=267694048, end=267694080, __free_memory_core(start, end)=0, count=55875
[ 0.000000] totalram_pages = free_all_bootmem()=55875
[ 0.000000] Memory: 223500k/262144k available (3675k kernel code, 448k absent, 38196k reserved, 5084k data, 660k init)


(тут я обратил внимание на последнюю строчку. 262144k available - это то, значение, которое мы ставили.

Ок, нам тут дали подробную распиновку:

223500 доступно.
3675 - ядро.
448 - absent (насколько я понимаю, это тот злосчастный кусочек от 640k до мегабайта, в наследство от msdos).
38196 - зарезервировано.
5084 - data
660 - init

Сумма всего этого 271563, то есть больше, чем есть на самом деле. Разница между available и mem_kb - это 38644к, то есть unavailable + absent.

Отсюда вопрос (оставляем в стороне unavailable):
Что за reserved и какогохера?

Заметим, available строго соответствует дебаг выводу из free_low_memory_core_early

Вчитаемся в функцию. (она попаганена моим дебагом):

unsigned long __init free_low_memory_core_early(int nodeid)
{
    unsigned long count = 0;
    unsigned long t = 0;
    phys_addr_t start, end, size;
    u64 i;
    printk (KERN_ERR "free_low_memory_core_early:%i\n", nodeid);
    for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL){
        t=__free_memory_core(start, end);
        count +=t;
        printk(KERN_ERR "free_low_memory_core_early: start=%lu, end=%lu, __free_memory_core(start, end)=%lu, count=%lu\n", (long unsigned) start, (long unsigned)end,t,count);
    }

    /* free range that is used for reserved array if we allocate it */
    size = get_allocated_memblock_reserved_regions_info(&start);
    if (size)
        count += __free_memory_core(start, start + size);

    return count;
}


У меня есть ощущение, что get_allocated_memblock_reserved_regions_info(&start) возвращает ноль, и вот там-то у нас эти 38Мб и заныканы...

Ща соберу с ещё большим отладом.

upd: так и есть
[ 0.000000] free_low_memory_core_early, size=0

Тогда вопрос: а откуда ядро знает про reserved, если get_allocated_memblock_reserved_regions_info(&start) равно нулю?

Кстати, у меня есть некоторый вопрос про код...

unsigned long __init free_low_memory_core_early(int nodeid)
{
    unsigned long count = 0;
    phys_addr_t start, end, size;
    u64 i;
    printk (KERN_ERR "free_low_memory_core_early:%i\n", nodeid);
    for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL)
        count +=__free_memory_core(start, end);

    /* free range that is used for reserved array if we allocate it */
    size = get_allocated_memblock_reserved_regions_info(&start);
    if (size)
        count += __free_memory_core(start, start + size);
    return count;
}

Почему get_allocated_memblock_reserved_regions_info(&start) вызывается для последнего и только последнего start? Ведь for_each_free_mem_range в финале возвращает... Я не знаю что (пока что), но интуиция мне говорит, что тут что-то не так.

В любом случае, выясняем, как линукс считает reserved в выводе выше.

Греп нас приводит обратно в arch/x86/mm/init_64.c, в void __init mem_init(void).

reservedpages = max_pfn - totalram_pages - absent_pages;

facepalm. facepalm. facepalm. То есть оно считает, что reserved, это всё, что не absent и не totalram_pages.

Другими словами, рыть надо всё-таки именно в район посчёта totalram_pages. Я на 90% уверен, что проблема именно в длинном дампе free_low_memory_core_early (см выше).
Tags: linux kernel, memory on demand, xen
Subscribe

  • фурикури

    Я тут его ещё раз пересмотрел, и за гламурным дребезгом (который хорош), я, наконец-таки, рассмотрел сюжет. Первые три серии (я про оригинальный…

  • поздне-анимешное

    Один из интересных водоразделов между западной и восточной (японской, японской) культурой я вижу в районе толстовской фразы "Все счастливые семьи…

  • berserk 2017

    Внезапно, если кто не заметил, уже аж 4 серии нового сезона. И он не менее офигенен, чем предыдущий. При том, что местами анимация провисает, история…

  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments