#author("2025-09-13T02:10:25+09:00","default:guest","guest") #author("2025-09-13T02:10:36+09:00","default:guest","guest") *参照元 [#r0997772] #backlinks *説明 [#g9831878] -パス: [[linux-5.15/mm/page_alloc.c]] -FIXME: これは何? --説明 **引数 [#be4802db] -struct zone *zone -- --[[linux-5.15/zone]] --int order -int order -- --int start_migratetype -int start_migratetype -- --unsigned int alloc_flags -unsigned int alloc_flags -- **返り値 [#s5f4f672] -bool -- **参考 [#v9edcf02] *実装 [#g0e41b38] /* * Try finding a free buddy page on the fallback list and put it on the free * list of requested migratetype, possibly along with other pages from the same * block, depending on fragmentation avoidance heuristics. Returns true if * fallback was found so that __rmqueue_smallest() can grab it. * * The use of signed ints for order and current_order is a deliberate * deviation from the rest of this file, to make the for loop * condition simpler. */ static __always_inline bool __rmqueue_fallback(struct zone *zone, int order, int start_migratetype, unsigned int alloc_flags) { struct free_area *area; int current_order; int min_order = order; struct page *page; int fallback_mt; bool can_steal; /* * Do not steal pages from freelists belonging to other pageblocks * i.e. orders < pageblock_order. If there are no local zones free, * the zonelists will be reiterated without ALLOC_NOFRAGMENT. */ if (alloc_flags & ALLOC_NOFRAGMENT) min_order = pageblock_order; - --[[linux-5.15/free_area]] --[[linux-5.15/page]] /* * Find the largest available free page in the other list. This roughly * approximates finding the pageblock with the most free pages, which * would be too costly to do exactly. */ for (current_order = MAX_ORDER - 1; current_order >= min_order; --current_order) { area = &(zone->free_area[current_order]); fallback_mt = find_suitable_fallback(area, current_order, start_migratetype, false, &can_steal); if (fallback_mt == -1) continue; /* * We cannot steal all free pages from the pageblock and the * requested migratetype is movable. In that case it's better to * steal and split the smallest available page instead of the * largest available page, because even if the next movable * allocation falls back into a different pageblock than this * one, it won't cause permanent fragmentation. */ if (!can_steal && start_migratetype == MIGRATE_MOVABLE && current_order > order) goto find_smallest; goto do_steal; } return false; - --[[linux-5.15/find_suitable_fallback()]] find_smallest: for (current_order = order; current_order < MAX_ORDER; current_order++) { area = &(zone->free_area[current_order]); fallback_mt = find_suitable_fallback(area, current_order, start_migratetype, false, &can_steal); if (fallback_mt != -1) break; } /* * This should not happen - we already found a suitable fallback * when looking for the largest page. */ VM_BUG_ON(current_order == MAX_ORDER); - --[[linux-5.15/find_suitable_fallback()]] --[[linux-5.15/VM_BUG_ON()]] do_steal: page = get_page_from_free_area(area, fallback_mt); steal_suitable_fallback(zone, page, alloc_flags, start_migratetype, can_steal); trace_mm_page_alloc_extfrag(page, order, current_order, start_migratetype, fallback_mt); return true; } - --[[linux-5.15/get_page_from_free_area()]] --[[linux-5.15/steal_suitable_fallback()]] --[[linux-5.15/trace_mm_page_alloc_extfrag()]] *コメント [#f99b50c1]