*参照元 [#o2045ad6]
#backlinks

*説明 [#hb157032]
-パス: [[linux-4.4.1/]]
-パス: [[linux-4.4.1/mm/page_alloc.c]]

-FIXME: これは何?
--説明


**引数 [#u89957b1]
-
-unsigned long start
--
-unsigned long end
--
-unsigned migratetype
--


**返り値 [#hce649ef]
-
-int
--


**参考 [#i5d2b328]


*実装 [#c3dd730c]
 /**
  * alloc_contig_range() -- tries to allocate given range of pages
  * @start:      start PFN to allocate
  * @end:        one-past-the-last PFN to allocate
  * @migratetype:        migratetype of the underlaying pageblocks (either
  *                      #MIGRATE_MOVABLE or #MIGRATE_CMA).  All pageblocks
  *                      in range must have the same migratetype and it must
  *                      be either of the two.
  *
  * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES
  * aligned, however it's the caller's responsibility to guarantee that
  * we are the only thread that changes migrate type of pageblocks the
  * pages fall in.
  *
  * The PFN range must belong to a single zone.
  *                     
  * Returns zero on success or negative error code.  On success all
  * pages which PFN is in [start, end) are allocated for the caller and
  * need to be freed with free_contig_range().
  */     
 int alloc_contig_range(unsigned long start, unsigned long end,
                        unsigned migratetype)
 {
         unsigned long outer_start, outer_end;
         unsigned int order;
         int ret = 0;
 
         struct compact_control cc = {
                 .nr_migratepages = 0,
                 .order = -1,
                 .zone = page_zone(pfn_to_page(start)),
                 .mode = MIGRATE_SYNC,
                 .ignore_skip_hint = true,
         };
         INIT_LIST_HEAD(&cc.migratepages);
 
-
--[[linux-4.4.1/compact_control]]
--[[linux-4.4.1/page_zone()]]
--[[linux-4.4.1/pfn_to_page()]]
--[[linux-4.4.1/INIT_LIST_HEAD()]]

         /*
          * What we do here is we mark all pageblocks in range as
          * MIGRATE_ISOLATE.  Because pageblock and max order pages may
          * have different sizes, and due to the way page allocator
          * work, we align the range to biggest of the two pages so
          * that page allocator won't try to merge buddies from
          * different pageblocks and change MIGRATE_ISOLATE to some
          * other migration type.
          *
          * Once the pageblocks are marked as MIGRATE_ISOLATE, we
          * migrate the pages from an unaligned range (ie. pages that
          * we are interested in).  This will put all the pages in
          * range back to page allocator as MIGRATE_ISOLATE.
          *
          * When this is done, we take the pages in range from page
          * allocator removing them from the buddy system.  This way
          * page allocator will never consider using them.
          *
          * This lets us mark the pageblocks back as
          * MIGRATE_CMA/MIGRATE_MOVABLE so that free pages in the
          * aligned range but not in the unaligned, original range are
          * put back to page allocator so that buddy can use them.
          */
 
         ret = start_isolate_page_range(pfn_max_align_down(start),
                                        pfn_max_align_up(end), migratetype,
                                        false);
         if (ret)
                 return ret;
 
-
--[[linux-4.4.1/start_isolate_page_range()]]
--[[linux-4.4.1/pfn_max_align_down()]]
--[[linux-4.4.1/pfn_max_align_up()]]

         ret = __alloc_contig_migrate_range(&cc, start, end);
         if (ret)
                 goto done;
 
-
--[[linux-4.4.1/__alloc_contig_migrate_range()]]

         /*
          * Pages from [start, end) are within a MAX_ORDER_NR_PAGES
          * aligned blocks that are marked as MIGRATE_ISOLATE.  What's
          * more, all pages in [start, end) are free in page allocator.
          * What we are going to do is to allocate all pages from
          * [start, end) (that is remove them from page allocator).
          *
          * The only problem is that pages at the beginning and at the
          * end of interesting range may be not aligned with pages that
          * page allocator holds, ie. they can be part of higher order
          * pages.  Because of this, we reserve the bigger range and
          * once this is done free the pages we are not interested in.
          *
          * We don't have to hold zone->lock here because the pages are
          * isolated thus they won't get removed from buddy.
          */
 
         lru_add_drain_all();
         drain_all_pages(cc.zone);
 
-
--[[linux-4.4.1/lru_add_drain_all()]]
--[[linux-4.4.1/drain_all_pages()]]

         order = 0;
         outer_start = start;
         while (!PageBuddy(pfn_to_page(outer_start))) {
                 if (++order >= MAX_ORDER) {
                         ret = -EBUSY;
                         goto done;
                 }
                 outer_start &= ~0UL << order;
         }
 
-
--[[linux-4.4.1/PageBuddy()]]

         /* Make sure the range is really isolated. */
         if (test_pages_isolated(outer_start, end, false)) {
                 pr_info("%s: [%lx, %lx) PFNs busy\n",
                         __func__, outer_start, end);
                 ret = -EBUSY;
                 goto done;
         }
 
-
--[[linux-4.4.1/test_pages_isolated()]]

         /* Grab isolated pages from freelists. */
         outer_end = isolate_freepages_range(&cc, outer_start, end);
         if (!outer_end) {
                 ret = -EBUSY;
                 goto done;
         }
 
-
--[[linux-4.4.1/isolate_freepages_range()]]

         /* Free head and tail (if any) */
         if (start != outer_start)
                 free_contig_range(outer_start, start - outer_start);
         if (end != outer_end)
                 free_contig_range(end, outer_end - end);
 
-
--[[linux-4.4.1/free_contig_range()]]

 done:
         undo_isolate_page_range(pfn_max_align_down(start),
                                 pfn_max_align_up(end), migratetype);
-
--[[linux-4.4.1/undo_isolate_page_range()]]

         return ret;
 }


*コメント [#a2b5fb0a]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS