Merge tag 'mm-hotfixes-stable-2026-09-13-21-50' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from Andrew Morton:
 "14 hotfixes.  10 are cc:stable.  11 are for MM.

  All are singletons - please see the changelogs for details"

* tag 'mm-hotfixes-stable-2026-09-13-21-50' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  mm/folio: EXPORT_SYMBOL_FOR_KVM(lru_cache_drain_for_folio)
  mm/shrinker: fix bogus set_shrinker_bit() with cgroup.memory=nokmem
  mm/vma: correctly unaccount on mmap_prepare() failure
  mm/mlock: use the IRQ-safe accessor for NR_MLOCK in __munlock_folio()
  remove old lib/alloc_tag.c
  fs/dax: check zero or empty entry before converting xarray entry
  fs: fix missed removal of super_fs_objects_eligible()
  mm: filemap: retain mapped dropbehind folios
  mailmap: update entry for Christopher Obbard
  memcg: avoid charging the root memcg from obj_cgroup_charge_pages()
  mm, swap: fix SWAP_USAGE_OFFLIST_BIT collision with real usage count
  mailmap: map Coiby Xu's address
  mm/mremap: account mm->locked_vm correctly for MREMAP_DONTUNMAP
  mm/huge_memory: bypass THP tuneables for huge pfnmap mappings
This commit is contained in:
Linus Torvalds
2026-09-14 08:59:09 -07:00
13 changed files with 91 additions and 1082 deletions
+3 -1
View File
@@ -211,7 +211,8 @@ Christophe Leroy <chleroy@kernel.org> <christophe.leroy@c-s.fr>
Christophe Leroy <chleroy@kernel.org> <christophe.leroy@csgroup.eu>
Christophe Leroy <chleroy@kernel.org> <christophe.leroy2@cs-soprasteria.com>
Christophe Ricard <christophe.ricard@gmail.com>
Christopher Obbard <christopher.obbard@linaro.org> <chris.obbard@collabora.com>
Christopher Obbard <chris.obbard@oss.qualcomm.com> <chris.obbard@collabora.com>
Christopher Obbard <chris.obbard@oss.qualcomm.com> <christopher.obbard@linaro.org>
Christoph Hellwig <hch@lst.de>
Christoph Manszewski <c.manszewski@gmail.com> <christoph.manszewski@intel.com>
Christoph Paasch <cpaasch@openai.com> <christoph.paasch@gmail.com>
@@ -222,6 +223,7 @@ Chuck Lever <cel@kernel.org> <chuck.lever@oracle.com>
Chuck Lever <cel@kernel.org> <cel@netapp.com>
Chuck Lever <cel@kernel.org> <cel@citi.umich.edu>
Claudiu Beznea <claudiu.beznea@tuxon.dev> <claudiu.beznea@microchip.com>
Coiby Xu <coiby.xu@gmail.com> <coxu@redhat.com>
Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
Corey Minyard <minyard@acm.org>
Damian Hobson-Garcia <dhobsong@igel.co.jp>
+6 -3
View File
@@ -480,11 +480,12 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
unsigned long address, bool shared)
{
unsigned long size = dax_entry_size(entry), index;
struct folio *folio = dax_to_folio(entry);
struct folio *folio;
if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry))
return;
folio = dax_to_folio(entry);
index = linear_page_index(vma, address & ~(size - 1));
if (shared && (folio->mapping || dax_folio_is_shared(folio))) {
if (folio->mapping)
@@ -505,21 +506,23 @@ static void dax_associate_entry(void *entry, struct address_space *mapping,
static void dax_disassociate_entry(void *entry, struct address_space *mapping,
bool trunc)
{
struct folio *folio = dax_to_folio(entry);
struct folio *folio;
if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry))
return;
folio = dax_to_folio(entry);
dax_folio_put(folio);
}
static struct page *dax_busy_page(void *entry)
{
struct folio *folio = dax_to_folio(entry);
struct folio *folio;
if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry))
return NULL;
folio = dax_to_folio(entry);
if (folio_ref_count(folio) - folio_mapcount(folio))
return &folio->page;
else
+2 -16
View File
@@ -171,19 +171,6 @@ static void super_wake(struct super_block *sb, unsigned int flag)
wake_up_var(&sb->s_flags);
}
/*
* The s_op->nr_cached_objects hooks (used for example by btrfs and xfs)
* operate on filesystem-global state and ignore sc->memcg. Driving them
* from per-memcg shrink_slab_memcg() invocations only burns CPU walking
* per-cpu counters and queueing duplicate work: the actual reclaim happens on
* the global path (kswapd or root direct reclaim) regardless. Restrict them
* to that path.
*/
static inline bool super_fs_objects_eligible(struct shrink_control *sc)
{
return !sc->memcg || mem_cgroup_is_root(sc->memcg);
}
/*
* One thing we have to be careful of with a per-sb shrinker is that we don't
* drop the last active reference to the superblock from within the shrinker.
@@ -213,7 +200,7 @@ static unsigned long super_cache_scan(struct shrinker *shrink,
if (!super_trylock_shared(sb))
return SHRINK_STOP;
if (sb->s_op->nr_cached_objects && super_fs_objects_eligible(sc))
if (sb->s_op->nr_cached_objects)
fs_objects = sb->s_op->nr_cached_objects(sb, sc);
inodes = list_lru_shrink_count(&sb->s_inode_lru, sc);
@@ -274,8 +261,7 @@ static unsigned long super_cache_count(struct shrinker *shrink,
return 0;
smp_rmb();
if (sb->s_op && sb->s_op->nr_cached_objects &&
super_fs_objects_eligible(sc))
if (sb->s_op && sb->s_op->nr_cached_objects)
total_objects = sb->s_op->nr_cached_objects(sb, sc);
total_objects += list_lru_shrink_count(&sb->s_dentry_lru, sc);
-1029
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1616,7 +1616,7 @@ static void filemap_end_dropbehind(struct folio *folio)
return;
if (!folio_test_clear_dropbehind(folio))
return;
if (mapping)
if (mapping && !folio_mapped(folio))
folio_unmap_invalidate(mapping, folio, 0);
}
+2
View File
@@ -33,6 +33,7 @@
#include <linux/page_idle.h>
#include <linux/local_lock.h>
#include <linux/buffer_head.h>
#include <linux/kvm_types.h>
#include "internal.h"
#include "page_alloc.h"
@@ -926,6 +927,7 @@ void lru_cache_drain_for_folio(const struct folio *folio,
*drained = LRU_CACHE_DRAINED_ALL;
}
}
EXPORT_SYMBOL_FOR_KVM(lru_cache_drain_for_folio);
atomic_t lru_disable_count = ATOMIC_INIT(0);
+64 -22
View File
@@ -92,7 +92,7 @@ unsigned long huge_anon_orders_madvise __read_mostly;
unsigned long huge_anon_orders_inherit __read_mostly;
static bool anon_orders_configured __initdata;
static inline bool file_thp_enabled(struct vm_area_struct *vma)
static inline bool file_thp_enabled(const struct vm_area_struct *vma)
{
struct inode *inode;
@@ -118,6 +118,67 @@ static bool vma_is_special_huge(const struct vm_area_struct *vma)
return vma_test_any(vma, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT);
}
static bool vma_file_bypass_thp_tuneables(const struct vm_area_struct *vma,
enum tva_type type)
{
const bool has_huge_fault = vma->vm_ops->huge_fault;
/* MADV_COLLAPSE ignores tuneables. */
if (type == TVA_FORCED_COLLAPSE)
return true;
/* Huge PFN mappings are uncompactable so the policy doesn't apply. */
if (vma_test(vma, VMA_PFNMAP_BIT) && has_huge_fault)
return true;
return false;
}
static bool vma_file_allow_thp_tuneables(vm_flags_t vm_flags)
{
/* THP=always? */
if (hugepage_global_always())
return true;
/* THP=madvise and marked MADV_HUGEPAGE? */
if (hugepage_global_enabled() && (vm_flags & VM_HUGEPAGE))
return true;
return false;
}
static bool vma_file_check_thp_tuneables(const struct vm_area_struct *vma,
vm_flags_t vm_flags, enum tva_type type)
{
return vma_file_bypass_thp_tuneables(vma, type) ||
vma_file_allow_thp_tuneables(vm_flags);
}
static bool vma_can_map_huge_file(const struct vm_area_struct *vma,
vm_flags_t vm_flags, enum tva_type type)
{
const bool has_huge_fault = vma->vm_ops->huge_fault;
/*
* Enforce THP collapse requirements as necessary. Anonymous vmas
* were already handled in thp_vma_allowable_orders().
*/
if (!vma_file_check_thp_tuneables(vma, vm_flags, type))
return false;
switch (type) {
case TVA_PAGEFAULT:
/*
* Trust that ->huge_fault() handlers know what they are doing
* in fault path.
*/
return has_huge_fault;
case TVA_SMAPS:
if (has_huge_fault)
return true;
fallthrough;
default:
/* Only regular file is valid in collapse path. */
return file_thp_enabled(vma);
}
}
unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,
vm_flags_t vm_flags,
enum tva_type type,
@@ -190,27 +251,8 @@ unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,
vma, vma_start_pgoff(vma), 0,
forced_collapse);
if (!vma_is_anonymous(vma)) {
/*
* Enforce THP collapse requirements as necessary. Anonymous vmas
* were already handled in thp_vma_allowable_orders().
*/
if (!forced_collapse &&
(!hugepage_global_enabled() || (!(vm_flags & VM_HUGEPAGE) &&
!hugepage_global_always())))
return 0;
/*
* Trust that ->huge_fault() handlers know what they are doing
* in fault path.
*/
if (((in_pf || smaps)) && vma->vm_ops->huge_fault)
return orders;
/* Only regular file is valid in collapse path */
if (((!in_pf || smaps)) && file_thp_enabled(vma))
return orders;
return 0;
}
if (!vma_is_anonymous(vma))
return vma_can_map_huge_file(vma, vm_flags, type) ? orders : 0;
if (vma_is_temporary_stack(vma))
return 0;
+1 -1
View File
@@ -3158,7 +3158,7 @@ static int obj_cgroup_charge_pages(struct obj_cgroup *objcg, gfp_t gfp,
memcg = get_mem_cgroup_from_objcg(objcg);
ret = try_charge_memcg(memcg, gfp, nr_pages);
ret = try_charge(memcg, gfp, nr_pages);
if (ret)
goto out;
+1 -1
View File
@@ -141,7 +141,7 @@ static struct lruvec *__munlock_folio(struct folio *folio, struct lruvec *lruvec
munlock:
if (folio_test_clear_mlocked(folio)) {
__zone_stat_mod_folio(folio, NR_MLOCK, -nr_pages);
zone_stat_mod_folio(folio, NR_MLOCK, -nr_pages);
if (isolated || !folio_test_unevictable(folio))
__count_vm_events(UNEVICTABLE_PGMUNLOCKED, nr_pages);
else
+4 -5
View File
@@ -1355,12 +1355,11 @@ static void dontunmap_complete(struct vma_remap_struct *vrm,
if (vma_is_anonymous(vma) && !vma->vm_file)
vma_set_pgoff(vma, pgoff_unfaulted);
}
/* Because we won't unmap we don't need to touch locked_vm. */
}
static unsigned long move_vma(struct vma_remap_struct *vrm)
{
const bool is_dontunmap = vrm->flags & MREMAP_DONTUNMAP;
struct mm_struct *mm = current->mm;
struct vm_area_struct *new_vma;
unsigned long hiwater_vm;
@@ -1401,10 +1400,10 @@ static unsigned long move_vma(struct vma_remap_struct *vrm)
*/
hiwater_vm = mm->hiwater_vm;
vrm_stat_account(vrm, vrm->new_len);
if (unlikely(!err && (vrm->flags & MREMAP_DONTUNMAP)))
if (unlikely(is_dontunmap && !err))
dontunmap_complete(vrm, new_vma);
else
vrm_stat_account(vrm, vrm->new_len);
if (!is_dontunmap || err)
unmap_source_vma(vrm);
mm->hiwater_vm = hiwater_vm;
+2
View File
@@ -227,6 +227,8 @@ static int shrinker_memcg_alloc(struct shrinker *shrinker)
{
int id;
shrinker->id = -1;
if (mem_cgroup_disabled())
return -ENOSYS;
if (mem_cgroup_kmem_disabled() && !(shrinker->flags & SHRINKER_NONSLAB))
+1 -1
View File
@@ -156,7 +156,7 @@ static struct swap_info_struct *swap_entry_to_info(swp_entry_t entry)
* This bit will be set if the device is not on the plist and not
* usable, will be cleared if the device is on the plist.
*/
#define SWAP_USAGE_OFFLIST_BIT (1UL << (BITS_PER_TYPE(atomic_t) - 2))
#define SWAP_USAGE_OFFLIST_BIT (1UL << (BITS_PER_TYPE(atomic_long_t) - 2))
#define SWAP_USAGE_COUNTER_MASK (~SWAP_USAGE_OFFLIST_BIT)
static long swap_usage_in_pages(struct swap_info_struct *si)
{
+4 -2
View File
@@ -2859,10 +2859,12 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
map.check_ksm_early = can_set_ksm_flags_early(&map);
error = __mmap_setup(&map, &desc, uf);
if (!error && have_mmap_prepare)
error = call_mmap_prepare(&map, &desc);
if (error)
goto abort_munmap;
if (have_mmap_prepare)
error = call_mmap_prepare(&map, &desc);
if (error)
goto unacct_error;
if (map.check_ksm_early)
update_ksm_flags(&map);