1. 27 1月, 2021 1 次提交
  2. 25 1月, 2021 2 次提交
    • A
      kasan, mm: fix resetting page_alloc tags for HW_TAGS · acb35b17
      Andrey Konovalov 提交于
      A previous commit added resetting KASAN page tags to
      kernel_init_free_pages() to avoid false-positives due to accesses to
      metadata with the hardware tag-based mode.
      
      That commit did reset page tags before the metadata access, but didn't
      restore them after.  As the result, KASAN fails to detect bad accesses
      to page_alloc allocations on some configurations.
      
      Fix this by recovering the tag after the metadata access.
      
      Link: https://lkml.kernel.org/r/02b5bcd692e912c27d484030f666b350ad7e4ae4.1611074450.git.andreyknvl@google.com
      Fixes: aa1ef4d7 ("kasan, mm: reset tags when accessing metadata")
      Signed-off-by: NAndrey Konovalov <andreyknvl@google.com>
      Cc: Dmitry Vyukov <dvyukov@google.com>
      Cc: Alexander Potapenko <glider@google.com>
      Cc: Marco Elver <elver@google.com>
      Cc: Catalin Marinas <catalin.marinas@arm.com>
      Cc: Will Deacon <will.deacon@arm.com>
      Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
      Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
      Cc: Peter Collingbourne <pcc@google.com>
      Cc: Evgenii Stepanov <eugenis@google.com>
      Cc: Branislav Rankov <Branislav.Rankov@arm.com>
      Cc: Kevin Brodsky <kevin.brodsky@arm.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      acb35b17
    • M
      mm: fix initialization of struct page for holes in memory layout · d3921cb8
      Mike Rapoport 提交于
      There could be struct pages that are not backed by actual physical
      memory.  This can happen when the actual memory bank is not a multiple
      of SECTION_SIZE or when an architecture does not register memory holes
      reserved by the firmware as memblock.memory.
      
      Such pages are currently initialized using init_unavailable_mem()
      function that iterates through PFNs in holes in memblock.memory and if
      there is a struct page corresponding to a PFN, the fields if this page
      are set to default values and the page is marked as Reserved.
      
      init_unavailable_mem() does not take into account zone and node the page
      belongs to and sets both zone and node links in struct page to zero.
      
      On a system that has firmware reserved holes in a zone above ZONE_DMA,
      for instance in a configuration below:
      
      	# grep -A1 E820 /proc/iomem
      	7a17b000-7a216fff : Unknown E820 type
      	7a217000-7bffffff : System RAM
      
      unset zone link in struct page will trigger
      
      	VM_BUG_ON_PAGE(!zone_spans_pfn(page_zone(page), pfn), page);
      
      because there are pages in both ZONE_DMA32 and ZONE_DMA (unset zone link
      in struct page) in the same pageblock.
      
      Update init_unavailable_mem() to use zone constraints defined by an
      architecture to properly setup the zone link and use node ID of the
      adjacent range in memblock.memory to set the node link.
      
      Link: https://lkml.kernel.org/r/20210111194017.22696-3-rppt@kernel.org
      Fixes: 73a6e474 ("mm: memmap_init: iterate over memblock regions rather that check each PFN")
      Signed-off-by: NMike Rapoport <rppt@linux.ibm.com>
      Reported-by: NAndrea Arcangeli <aarcange@redhat.com>
      Cc: Andrea Arcangeli <aarcange@redhat.com>
      Cc: Baoquan He <bhe@redhat.com>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: David Hildenbrand <david@redhat.com>
      Cc: "H. Peter Anvin" <hpa@zytor.com>
      Cc: Ingo Molnar <mingo@redhat.com>
      Cc: Mel Gorman <mgorman@suse.de>
      Cc: Michal Hocko <mhocko@kernel.org>
      Cc: Qian Cai <cai@lca.pw>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Vlastimil Babka <vbabka@suse.cz>
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      d3921cb8
  3. 13 1月, 2021 1 次提交
  4. 30 12月, 2020 1 次提交
    • B
      mm: memmap defer init doesn't work as expected · dc2da7b4
      Baoquan He 提交于
      VMware observed a performance regression during memmap init on their
      platform, and bisected to commit 73a6e474 ("mm: memmap_init:
      iterate over memblock regions rather that check each PFN") causing it.
      
      Before the commit:
      
        [0.033176] Normal zone: 1445888 pages used for memmap
        [0.033176] Normal zone: 89391104 pages, LIFO batch:63
        [0.035851] ACPI: PM-Timer IO Port: 0x448
      
      With commit
      
        [0.026874] Normal zone: 1445888 pages used for memmap
        [0.026875] Normal zone: 89391104 pages, LIFO batch:63
        [2.028450] ACPI: PM-Timer IO Port: 0x448
      
      The root cause is the current memmap defer init doesn't work as expected.
      
      Before, memmap_init_zone() was used to do memmap init of one whole zone,
      to initialize all low zones of one numa node, but defer memmap init of
      the last zone in that numa node.  However, since commit 73a6e474,
      function memmap_init() is adapted to iterater over memblock regions
      inside one zone, then call memmap_init_zone() to do memmap init for each
      region.
      
      E.g, on VMware's system, the memory layout is as below, there are two
      memory regions in node 2.  The current code will mistakenly initialize the
      whole 1st region [mem 0xab00000000-0xfcffffffff], then do memmap defer to
      iniatialize only one memmory section on the 2nd region [mem
      0x10000000000-0x1033fffffff].  In fact, we only expect to see that there's
      only one memory section's memmap initialized.  That's why more time is
      costed at the time.
      
      [    0.008842] ACPI: SRAT: Node 0 PXM 0 [mem 0x00000000-0x0009ffff]
      [    0.008842] ACPI: SRAT: Node 0 PXM 0 [mem 0x00100000-0xbfffffff]
      [    0.008843] ACPI: SRAT: Node 0 PXM 0 [mem 0x100000000-0x55ffffffff]
      [    0.008844] ACPI: SRAT: Node 1 PXM 1 [mem 0x5600000000-0xaaffffffff]
      [    0.008844] ACPI: SRAT: Node 2 PXM 2 [mem 0xab00000000-0xfcffffffff]
      [    0.008845] ACPI: SRAT: Node 2 PXM 2 [mem 0x10000000000-0x1033fffffff]
      
      Now, let's add a parameter 'zone_end_pfn' to memmap_init_zone() to pass
      down the real zone end pfn so that defer_init() can use it to judge
      whether defer need be taken in zone wide.
      
      Link: https://lkml.kernel.org/r/20201223080811.16211-1-bhe@redhat.com
      Link: https://lkml.kernel.org/r/20201223080811.16211-2-bhe@redhat.com
      Fixes: commit 73a6e474 ("mm: memmap_init: iterate over memblock regions rather that check each PFN")
      Signed-off-by: NBaoquan He <bhe@redhat.com>
      Reported-by: NRahul Gopakumar <gopakumarr@vmware.com>
      Reviewed-by: NMike Rapoport <rppt@linux.ibm.com>
      Cc: David Hildenbrand <david@redhat.com>
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      dc2da7b4
  5. 23 12月, 2020 2 次提交
  6. 16 12月, 2020 23 次提交
  7. 03 12月, 2020 2 次提交
    • R
      mm: Convert page kmemcg type to a page memcg flag · 18b2db3b
      Roman Gushchin 提交于
      PageKmemcg flag is currently defined as a page type (like buddy, offline,
      table and guard).  Semantically it means that the page was accounted as a
      kernel memory by the page allocator and has to be uncharged on the
      release.
      
      As a side effect of defining the flag as a page type, the accounted page
      can't be mapped to userspace (look at page_has_type() and comments above).
      In particular, this blocks the accounting of vmalloc-backed memory used
      by some bpf maps, because these maps do map the memory to userspace.
      
      One option is to fix it by complicating the access to page->mapcount,
      which provides some free bits for page->page_type.
      
      But it's way better to move this flag into page->memcg_data flags.
      Indeed, the flag makes no sense without enabled memory cgroups and memory
      cgroup pointer set in particular.
      
      This commit replaces PageKmemcg() and __SetPageKmemcg() with
      PageMemcgKmem() and an open-coded OR operation setting the memcg pointer
      with the MEMCG_DATA_KMEM bit.  __ClearPageKmemcg() can be simple deleted,
      as the whole memcg_data is zeroed at once.
      
      As a bonus, on !CONFIG_MEMCG build the PageMemcgKmem() check will be
      compiled out.
      Signed-off-by: NRoman Gushchin <guro@fb.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NShakeel Butt <shakeelb@google.com>
      Acked-by: NJohannes Weiner <hannes@cmpxchg.org>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Link: https://lkml.kernel.org/r/20201027001657.3398190-5-guro@fb.com
      Link: https://lore.kernel.org/bpf/20201201215900.3569844-5-guro@fb.com
      18b2db3b
    • R
      mm: memcontrol: Use helpers to read page's memcg data · bcfe06bf
      Roman Gushchin 提交于
      Patch series "mm: allow mapping accounted kernel pages to userspace", v6.
      
      Currently a non-slab kernel page which has been charged to a memory cgroup
      can't be mapped to userspace.  The underlying reason is simple: PageKmemcg
      flag is defined as a page type (like buddy, offline, etc), so it takes a
      bit from a page->mapped counter.  Pages with a type set can't be mapped to
      userspace.
      
      But in general the kmemcg flag has nothing to do with mapping to
      userspace.  It only means that the page has been accounted by the page
      allocator, so it has to be properly uncharged on release.
      
      Some bpf maps are mapping the vmalloc-based memory to userspace, and their
      memory can't be accounted because of this implementation detail.
      
      This patchset removes this limitation by moving the PageKmemcg flag into
      one of the free bits of the page->mem_cgroup pointer.  Also it formalizes
      accesses to the page->mem_cgroup and page->obj_cgroups using new helpers,
      adds several checks and removes a couple of obsolete functions.  As the
      result the code became more robust with fewer open-coded bit tricks.
      
      This patch (of 4):
      
      Currently there are many open-coded reads of the page->mem_cgroup pointer,
      as well as a couple of read helpers, which are barely used.
      
      It creates an obstacle on a way to reuse some bits of the pointer for
      storing additional bits of information.  In fact, we already do this for
      slab pages, where the last bit indicates that a pointer has an attached
      vector of objcg pointers instead of a regular memcg pointer.
      
      This commits uses 2 existing helpers and introduces a new helper to
      converts all read sides to calls of these helpers:
        struct mem_cgroup *page_memcg(struct page *page);
        struct mem_cgroup *page_memcg_rcu(struct page *page);
        struct mem_cgroup *page_memcg_check(struct page *page);
      
      page_memcg_check() is intended to be used in cases when the page can be a
      slab page and have a memcg pointer pointing at objcg vector.  It does
      check the lowest bit, and if set, returns NULL.  page_memcg() contains a
      VM_BUG_ON_PAGE() check for the page not being a slab page.
      
      To make sure nobody uses a direct access, struct page's
      mem_cgroup/obj_cgroups is converted to unsigned long memcg_data.
      Signed-off-by: NRoman Gushchin <guro@fb.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Reviewed-by: NShakeel Butt <shakeelb@google.com>
      Acked-by: NJohannes Weiner <hannes@cmpxchg.org>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Link: https://lkml.kernel.org/r/20201027001657.3398190-1-guro@fb.com
      Link: https://lkml.kernel.org/r/20201027001657.3398190-2-guro@fb.com
      Link: https://lore.kernel.org/bpf/20201201215900.3569844-2-guro@fb.com
      bcfe06bf
  8. 19 11月, 2020 1 次提交
    • D
      page_frag: Recover from memory pressure · d8c19014
      Dongli Zhang 提交于
      The ethernet driver may allocate skb (and skb->data) via napi_alloc_skb().
      This ends up to page_frag_alloc() to allocate skb->data from
      page_frag_cache->va.
      
      During the memory pressure, page_frag_cache->va may be allocated as
      pfmemalloc page. As a result, the skb->pfmemalloc is always true as
      skb->data is from page_frag_cache->va. The skb will be dropped if the
      sock (receiver) does not have SOCK_MEMALLOC. This is expected behaviour
      under memory pressure.
      
      However, once kernel is not under memory pressure any longer (suppose large
      amount of memory pages are just reclaimed), the page_frag_alloc() may still
      re-use the prior pfmemalloc page_frag_cache->va to allocate skb->data. As a
      result, the skb->pfmemalloc is always true unless page_frag_cache->va is
      re-allocated, even if the kernel is not under memory pressure any longer.
      
      Here is how kernel runs into issue.
      
      1. The kernel is under memory pressure and allocation of
      PAGE_FRAG_CACHE_MAX_ORDER in __page_frag_cache_refill() will fail. Instead,
      the pfmemalloc page is allocated for page_frag_cache->va.
      
      2: All skb->data from page_frag_cache->va (pfmemalloc) will have
      skb->pfmemalloc=true. The skb will always be dropped by sock without
      SOCK_MEMALLOC. This is an expected behaviour.
      
      3. Suppose a large amount of pages are reclaimed and kernel is not under
      memory pressure any longer. We expect skb->pfmemalloc drop will not happen.
      
      4. Unfortunately, page_frag_alloc() does not proactively re-allocate
      page_frag_alloc->va and will always re-use the prior pfmemalloc page. The
      skb->pfmemalloc is always true even kernel is not under memory pressure any
      longer.
      
      Fix this by freeing and re-allocating the page instead of recycling it.
      
      References: https://lore.kernel.org/lkml/20201103193239.1807-1-dongli.zhang@oracle.com/
      References: https://lore.kernel.org/linux-mm/20201105042140.5253-1-willy@infradead.org/Suggested-by: NMatthew Wilcox (Oracle) <willy@infradead.org>
      Cc: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
      Cc: Bert Barbe <bert.barbe@oracle.com>
      Cc: Rama Nichanamatlu <rama.nichanamatlu@oracle.com>
      Cc: Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
      Cc: Manjunath Patil <manjunath.b.patil@oracle.com>
      Cc: Joe Jin <joe.jin@oracle.com>
      Cc: SRINIVAS <srinivas.eeda@oracle.com>
      Fixes: 79930f58 ("net: do not deplete pfmemalloc reserve")
      Signed-off-by: NDongli Zhang <dongli.zhang@oracle.com>
      Acked-by: NVlastimil Babka <vbabka@suse.cz>
      Reviewed-by: NEric Dumazet <edumazet@google.com>
      Link: https://lore.kernel.org/r/20201115201029.11903-1-dongli.zhang@oracle.comSigned-off-by: NJakub Kicinski <kuba@kernel.org>
      d8c19014
  9. 17 10月, 2020 7 次提交
    • M
      mm: rename page_order() to buddy_order() · ab130f91
      Matthew Wilcox (Oracle) 提交于
      The current page_order() can only be called on pages in the buddy
      allocator.  For compound pages, you have to use compound_order().  This is
      confusing and led to a bug, so rename page_order() to buddy_order().
      Signed-off-by: NMatthew Wilcox (Oracle) <willy@infradead.org>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Link: https://lkml.kernel.org/r/20201001152259.14932-2-willy@infradead.orgSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      ab130f91
    • D
      mm/page_alloc: place pages to tail in __free_pages_core() · 7fef431b
      David Hildenbrand 提交于
      __free_pages_core() is used when exposing fresh memory to the buddy during
      system boot and when onlining memory in generic_online_page().
      
      generic_online_page() is used in two cases:
      
      1. Direct memory onlining in online_pages().
      2. Deferred memory onlining in memory-ballooning-like mechanisms (HyperV
         balloon and virtio-mem), when parts of a section are kept
         fake-offline to be fake-onlined later on.
      
      In 1, we already place pages to the tail of the freelist.  Pages will be
      freed to MIGRATE_ISOLATE lists first and moved to the tail of the
      freelists via undo_isolate_page_range().
      
      In 2, we currently don't implement a proper rule.  In case of virtio-mem,
      where we currently always online MAX_ORDER - 1 pages, the pages will be
      placed to the HEAD of the freelist - undesireable.  While the hyper-v
      balloon calls generic_online_page() with single pages, usually it will
      call it on successive single pages in a larger block.
      
      The pages are fresh, so place them to the tail of the freelist and avoid
      the PCP.  In __free_pages_core(), remove the now superflouos call to
      set_page_refcounted() and add a comment regarding page initialization and
      the refcount.
      
      Note: In 2.  we currently don't shuffle.  If ever relevant (page shuffling
      is usually of limited use in virtualized environments), we might want to
      shuffle after a sequence of generic_online_page() calls in the relevant
      callers.
      Signed-off-by: NDavid Hildenbrand <david@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NVlastimil Babka <vbabka@suse.cz>
      Reviewed-by: NOscar Salvador <osalvador@suse.de>
      Reviewed-by: NWei Yang <richard.weiyang@linux.alibaba.com>
      Acked-by: NPankaj Gupta <pankaj.gupta.linux@gmail.com>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Alexander Duyck <alexander.h.duyck@linux.intel.com>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Cc: Dave Hansen <dave.hansen@intel.com>
      Cc: Mike Rapoport <rppt@kernel.org>
      Cc: "K. Y. Srinivasan" <kys@microsoft.com>
      Cc: Haiyang Zhang <haiyangz@microsoft.com>
      Cc: Stephen Hemminger <sthemmin@microsoft.com>
      Cc: Wei Liu <wei.liu@kernel.org>
      Cc: Matthew Wilcox <willy@infradead.org>
      Cc: Michael Ellerman <mpe@ellerman.id.au>
      Cc: Michal Hocko <mhocko@kernel.org>
      Cc: Scott Cheloha <cheloha@linux.ibm.com>
      Link: https://lkml.kernel.org/r/20201005121534.15649-5-david@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      7fef431b
    • D
      mm/page_alloc: move pages to tail in move_to_free_list() · 293ffa5e
      David Hildenbrand 提交于
      Whenever we move pages between freelists via move_to_free_list()/
      move_freepages_block(), we don't actually touch the pages:
      1. Page isolation doesn't actually touch the pages, it simply isolates
         pageblocks and moves all free pages to the MIGRATE_ISOLATE freelist.
         When undoing isolation, we move the pages back to the target list.
      2. Page stealing (steal_suitable_fallback()) moves free pages directly
         between lists without touching them.
      3. reserve_highatomic_pageblock()/unreserve_highatomic_pageblock() moves
         free pages directly between freelists without touching them.
      
      We already place pages to the tail of the freelists when undoing isolation
      via __putback_isolated_page(), let's do it in any case (e.g., if order <=
      pageblock_order) and document the behavior. To simplify, let's move the
      pages to the tail for all move_to_free_list()/move_freepages_block() users.
      
      In 2., the target list is empty, so there should be no change.  In 3., we
      might observe a change, however, highatomic is more concerned about
      allocations succeeding than cache hotness - if we ever realize this change
      degrades a workload, we can special-case this instance and add a proper
      comment.
      
      This change results in all pages getting onlined via online_pages() to be
      placed to the tail of the freelist.
      Signed-off-by: NDavid Hildenbrand <david@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NOscar Salvador <osalvador@suse.de>
      Reviewed-by: NWei Yang <richard.weiyang@linux.alibaba.com>
      Acked-by: NPankaj Gupta <pankaj.gupta.linux@gmail.com>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Alexander Duyck <alexander.h.duyck@linux.intel.com>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Cc: Dave Hansen <dave.hansen@intel.com>
      Cc: Vlastimil Babka <vbabka@suse.cz>
      Cc: Mike Rapoport <rppt@kernel.org>
      Cc: Scott Cheloha <cheloha@linux.ibm.com>
      Cc: Michael Ellerman <mpe@ellerman.id.au>
      Cc: Haiyang Zhang <haiyangz@microsoft.com>
      Cc: "K. Y. Srinivasan" <kys@microsoft.com>
      Cc: Matthew Wilcox <willy@infradead.org>
      Cc: Michal Hocko <mhocko@suse.com>
      Cc: Stephen Hemminger <sthemmin@microsoft.com>
      Cc: Wei Liu <wei.liu@kernel.org>
      Link: https://lkml.kernel.org/r/20201005121534.15649-4-david@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      293ffa5e
    • D
      mm/page_alloc: place pages to tail in __putback_isolated_page() · 47b6a24a
      David Hildenbrand 提交于
      __putback_isolated_page() already documents that pages will be placed to
      the tail of the freelist - this is, however, not the case for "order >=
      MAX_ORDER - 2" (see buddy_merge_likely()) - which should be the case for
      all existing users.
      
      This change affects two users:
      - free page reporting
      - page isolation, when undoing the isolation (including memory onlining).
      
      This behavior is desirable for pages that haven't really been touched
      lately, so exactly the two users that don't actually read/write page
      content, but rather move untouched pages.
      
      The new behavior is especially desirable for memory onlining, where we
      allow allocation of newly onlined pages via undo_isolate_page_range() in
      online_pages().  Right now, we always place them to the head of the
      freelist, resulting in undesireable behavior: Assume we add individual
      memory chunks via add_memory() and online them right away to the NORMAL
      zone.  We create a dependency chain of unmovable allocations e.g., via the
      memmap.  The memmap of the next chunk will be placed onto previous chunks
      - if the last block cannot get offlined+removed, all dependent ones cannot
      get offlined+removed.  While this can already be observed with individual
      DIMMs, it's more of an issue for virtio-mem (and I suspect also ppc
      DLPAR).
      
      Document that this should only be used for optimizations, and no code
      should rely on this behavior for correction (if the order of the freelists
      ever changes).
      
      We won't care about page shuffling: memory onlining already properly
      shuffles after onlining.  free page reporting doesn't care about
      physically contiguous ranges, and there are already cases where page
      isolation will simply move (physically close) free pages to (currently)
      the head of the freelists via move_freepages_block() instead of shuffling.
      If this becomes ever relevant, we should shuffle the whole zone when
      undoing isolation of larger ranges, and after free_contig_range().
      Signed-off-by: NDavid Hildenbrand <david@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NAlexander Duyck <alexander.h.duyck@linux.intel.com>
      Reviewed-by: NOscar Salvador <osalvador@suse.de>
      Reviewed-by: NWei Yang <richard.weiyang@linux.alibaba.com>
      Reviewed-by: NPankaj Gupta <pankaj.gupta.linux@gmail.com>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Cc: Dave Hansen <dave.hansen@intel.com>
      Cc: Vlastimil Babka <vbabka@suse.cz>
      Cc: Mike Rapoport <rppt@kernel.org>
      Cc: Scott Cheloha <cheloha@linux.ibm.com>
      Cc: Michael Ellerman <mpe@ellerman.id.au>
      Cc: Haiyang Zhang <haiyangz@microsoft.com>
      Cc: "K. Y. Srinivasan" <kys@microsoft.com>
      Cc: Matthew Wilcox <willy@infradead.org>
      Cc: Michal Hocko <mhocko@kernel.org>
      Cc: Stephen Hemminger <sthemmin@microsoft.com>
      Cc: Wei Liu <wei.liu@kernel.org>
      Link: https://lkml.kernel.org/r/20201005121534.15649-3-david@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      47b6a24a
    • D
      mm/page_alloc: convert "report" flag of __free_one_page() to a proper flag · f04a5d5d
      David Hildenbrand 提交于
      Patch series "mm: place pages to the freelist tail when onlining and undoing isolation", v2.
      
      When adding separate memory blocks via add_memory*() and onlining them
      immediately, the metadata (especially the memmap) of the next block will
      be placed onto one of the just added+onlined block.  This creates a chain
      of unmovable allocations: If the last memory block cannot get
      offlined+removed() so will all dependent ones.  We directly have unmovable
      allocations all over the place.
      
      This can be observed quite easily using virtio-mem, however, it can also
      be observed when using DIMMs.  The freshly onlined pages will usually be
      placed to the head of the freelists, meaning they will be allocated next,
      turning the just-added memory usually immediately un-removable.  The fresh
      pages are cold, prefering to allocate others (that might be hot) also
      feels to be the natural thing to do.
      
      It also applies to the hyper-v balloon xen-balloon, and ppc64 dlpar: when
      adding separate, successive memory blocks, each memory block will have
      unmovable allocations on them - for example gigantic pages will fail to
      allocate.
      
      While the ZONE_NORMAL doesn't provide any guarantees that memory can get
      offlined+removed again (any kind of fragmentation with unmovable
      allocations is possible), there are many scenarios (hotplugging a lot of
      memory, running workload, hotunplug some memory/as much as possible) where
      we can offline+remove quite a lot with this patchset.
      
      a) To visualize the problem, a very simple example:
      
      Start a VM with 4GB and 8GB of virtio-mem memory:
      
       [root@localhost ~]# lsmem
       RANGE                                 SIZE  STATE REMOVABLE  BLOCK
       0x0000000000000000-0x00000000bfffffff   3G online       yes   0-23
       0x0000000100000000-0x000000033fffffff   9G online       yes 32-103
      
       Memory block size:       128M
       Total online memory:      12G
       Total offline memory:      0B
      
      Then try to unplug as much as possible using virtio-mem. Observe which
      memory blocks are still around. Without this patch set:
      
       [root@localhost ~]# lsmem
       RANGE                                  SIZE  STATE REMOVABLE   BLOCK
       0x0000000000000000-0x00000000bfffffff    3G online       yes    0-23
       0x0000000100000000-0x000000013fffffff    1G online       yes   32-39
       0x0000000148000000-0x000000014fffffff  128M online       yes      41
       0x0000000158000000-0x000000015fffffff  128M online       yes      43
       0x0000000168000000-0x000000016fffffff  128M online       yes      45
       0x0000000178000000-0x000000017fffffff  128M online       yes      47
       0x0000000188000000-0x0000000197ffffff  256M online       yes   49-50
       0x00000001a0000000-0x00000001a7ffffff  128M online       yes      52
       0x00000001b0000000-0x00000001b7ffffff  128M online       yes      54
       0x00000001c0000000-0x00000001c7ffffff  128M online       yes      56
       0x00000001d0000000-0x00000001d7ffffff  128M online       yes      58
       0x00000001e0000000-0x00000001e7ffffff  128M online       yes      60
       0x00000001f0000000-0x00000001f7ffffff  128M online       yes      62
       0x0000000200000000-0x0000000207ffffff  128M online       yes      64
       0x0000000210000000-0x0000000217ffffff  128M online       yes      66
       0x0000000220000000-0x0000000227ffffff  128M online       yes      68
       0x0000000230000000-0x0000000237ffffff  128M online       yes      70
       0x0000000240000000-0x0000000247ffffff  128M online       yes      72
       0x0000000250000000-0x0000000257ffffff  128M online       yes      74
       0x0000000260000000-0x0000000267ffffff  128M online       yes      76
       0x0000000270000000-0x0000000277ffffff  128M online       yes      78
       0x0000000280000000-0x0000000287ffffff  128M online       yes      80
       0x0000000290000000-0x0000000297ffffff  128M online       yes      82
       0x00000002a0000000-0x00000002a7ffffff  128M online       yes      84
       0x00000002b0000000-0x00000002b7ffffff  128M online       yes      86
       0x00000002c0000000-0x00000002c7ffffff  128M online       yes      88
       0x00000002d0000000-0x00000002d7ffffff  128M online       yes      90
       0x00000002e0000000-0x00000002e7ffffff  128M online       yes      92
       0x00000002f0000000-0x00000002f7ffffff  128M online       yes      94
       0x0000000300000000-0x0000000307ffffff  128M online       yes      96
       0x0000000310000000-0x0000000317ffffff  128M online       yes      98
       0x0000000320000000-0x0000000327ffffff  128M online       yes     100
       0x0000000330000000-0x000000033fffffff  256M online       yes 102-103
      
       Memory block size:       128M
       Total online memory:     8.1G
       Total offline memory:      0B
      
      With this patch set:
      
       [root@localhost ~]# lsmem
       RANGE                                 SIZE  STATE REMOVABLE BLOCK
       0x0000000000000000-0x00000000bfffffff   3G online       yes  0-23
       0x0000000100000000-0x000000013fffffff   1G online       yes 32-39
      
       Memory block size:       128M
       Total online memory:       4G
       Total offline memory:      0B
      
      All memory can get unplugged, all memory block can get removed.  Of
      course, no workload ran and the system was basically idle, but it
      highlights the issue - the fairly deterministic chain of unmovable
      allocations.  When a huge page for the 2MB memmap is needed, a
      just-onlined 4MB page will be split.  The remaining 2MB page will be used
      for the memmap of the next memory block.  So one memory block will hold
      the memmap of the two following memory blocks.  Finally the pages of the
      last-onlined memory block will get used for the next bigger allocations -
      if any allocation is unmovable, all dependent memory blocks cannot get
      unplugged and removed until that allocation is gone.
      
      Note that with bigger memory blocks (e.g., 256MB), *all* memory
      blocks are dependent and none can get unplugged again!
      
      b) Experiment with memory intensive workload
      
      I performed an experiment with an older version of this patch set (before
      we used undo_isolate_page_range() in online_pages(): Hotplug 56GB to a VM
      with an initial 4GB, onlining all memory to ZONE_NORMAL right from the
      kernel when adding it.  I then run various memory intensive workloads that
      consume most system memory for a total of 45 minutes.  Once finished, I
      try to unplug as much memory as possible.
      
      With this change, I am able to remove via virtio-mem (adding individual
      128MB memory blocks) 413 out of 448 added memory blocks.  Via individual
      (256MB) DIMMs 380 out of 448 added memory blocks.  (I don't have any
      numbers without this patchset, but looking at the above example, it's at
      most half of the 448 memory blocks for virtio-mem, and most probably none
      for DIMMs).
      
      Again, there are workloads that might behave very differently due to the
      nature of ZONE_NORMAL.
      
      This change also affects (besides memory onlining):
      - Other users of undo_isolate_page_range(): Pages are always placed to the
        tail.
      -- When memory offlining fails
      -- When memory isolation fails after having isolated some pageblocks
      -- When alloc_contig_range() either succeeds or fails
      - Other users of __putback_isolated_page(): Pages are always placed to the
        tail.
      -- Free page reporting
      - Other users of __free_pages_core()
      -- AFAIKs, any memory that is getting exposed to the buddy during boot.
         IIUC we will now usually allocate memory from lower addresses within
         a zone first (especially during boot).
      - Other users of generic_online_page()
      -- Hyper-V balloon
      
      This patch (of 5):
      
      Let's prepare for additional flags and avoid long parameter lists of
      bools.  Follow-up patches will also make use of the flags in
      __free_pages_ok().
      Signed-off-by: NDavid Hildenbrand <david@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NAlexander Duyck <alexander.h.duyck@linux.intel.com>
      Reviewed-by: NVlastimil Babka <vbabka@suse.cz>
      Reviewed-by: NOscar Salvador <osalvador@suse.de>
      Reviewed-by: NWei Yang <richard.weiyang@linux.alibaba.com>
      Reviewed-by: NPankaj Gupta <pankaj.gupta.linux@gmail.com>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Cc: Dave Hansen <dave.hansen@intel.com>
      Cc: Mike Rapoport <rppt@kernel.org>
      Cc: Matthew Wilcox <willy@infradead.org>
      Cc: Haiyang Zhang <haiyangz@microsoft.com>
      Cc: "K. Y. Srinivasan" <kys@microsoft.com>
      Cc: Michael Ellerman <mpe@ellerman.id.au>
      Cc: Michal Hocko <mhocko@suse.com>
      Cc: Scott Cheloha <cheloha@linux.ibm.com>
      Cc: Stephen Hemminger <sthemmin@microsoft.com>
      Cc: Wei Liu <wei.liu@kernel.org>
      Cc: Michal Hocko <mhocko@kernel.org>
      Link: https://lkml.kernel.org/r/20201005121534.15649-1-david@redhat.com
      Link: https://lkml.kernel.org/r/20201005121534.15649-2-david@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      f04a5d5d
    • D
      mm: pass migratetype into memmap_init_zone() and move_pfn_range_to_zone() · d882c006
      David Hildenbrand 提交于
      On the memory onlining path, we want to start with MIGRATE_ISOLATE, to
      un-isolate the pages after memory onlining is complete.  Let's allow
      passing in the migratetype.
      Signed-off-by: NDavid Hildenbrand <david@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NOscar Salvador <osalvador@suse.de>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Wei Yang <richard.weiyang@linux.alibaba.com>
      Cc: Baoquan He <bhe@redhat.com>
      Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
      Cc: Tony Luck <tony.luck@intel.com>
      Cc: Fenghua Yu <fenghua.yu@intel.com>
      Cc: Logan Gunthorpe <logang@deltatee.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Mike Rapoport <rppt@kernel.org>
      Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
      Cc: Michel Lespinasse <walken@google.com>
      Cc: Charan Teja Reddy <charante@codeaurora.org>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Link: https://lkml.kernel.org/r/20200819175957.28465-10-david@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      d882c006
    • D
      mm/page_alloc: drop stale pageblock comment in memmap_init_zone*() · 4eb29bd9
      David Hildenbrand 提交于
      Commit ac5d2539 ("mm: meminit: reduce number of times pageblocks are
      set during struct page init") moved the actual zone range check, leaving
      only the alignment check for pageblocks.
      
      Let's drop the stale comment and make the pageblock check easier to read.
      Signed-off-by: NDavid Hildenbrand <david@redhat.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Reviewed-by: NOscar Salvador <osalvador@suse.de>
      Acked-by: NMichal Hocko <mhocko@suse.com>
      Cc: Wei Yang <richard.weiyang@linux.alibaba.com>
      Cc: Baoquan He <bhe@redhat.com>
      Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
      Cc: Mel Gorman <mgorman@suse.de>
      Cc: Charan Teja Reddy <charante@codeaurora.org>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Fenghua Yu <fenghua.yu@intel.com>
      Cc: Logan Gunthorpe <logang@deltatee.com>
      Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Cc: Michel Lespinasse <walken@google.com>
      Cc: Mike Rapoport <rppt@kernel.org>
      Cc: Tony Luck <tony.luck@intel.com>
      Link: https://lkml.kernel.org/r/20200819175957.28465-9-david@redhat.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      4eb29bd9