15 hotfixes. 6 are cc:stable. 14 are for MM.

Singletons, with one doubleton - please see the changelogs for details.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQTTMBEPP41GrTpTJgfdBJ7gKXxAjgUCaa9ZkgAKCRDdBJ7gKXxA
 jpfeAQDAj+Sn3bRdJWCUVNgWPdNLrmZnZRw5VdipioAnfmZHZQEAqBXnm7ehn1BA
 JgQvx6zTlsyqy4FhW+Q6uLmBpKmMTQw=
 =kbLH
 -----END PGP SIGNATURE-----

Merge tag 'mm-hotfixes-stable-2026-03-09-16-36' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

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

  Singletons, with one doubleton - please see the changelogs for details"

* tag 'mm-hotfixes-stable-2026-03-09-16-36' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  MAINTAINERS, mailmap: update email address for Lorenzo Stoakes
  mm/mmu_notifier: clean up mmu_notifier.h kernel-doc
  uaccess: correct kernel-doc parameter format
  mm/huge_memory: fix a folio_split() race condition with folio_try_get()
  MAINTAINERS: add co-maintainer and reviewer for SLAB ALLOCATOR
  MAINTAINERS: add RELAY entry
  memcg: fix slab accounting in refill_obj_stock() trylock path
  mm/hugetlb.c: use __pa() instead of virt_to_phys() in early bootmem alloc code
  zram: rename writeback_compressed device attr
  tools/testing: fix testing/vma and testing/radix-tree build
  Revert "ptdesc: remove references to folios from __pagetable_ctor() and pagetable_dtor()"
  mm/cma: move put_page_testzero() out of VM_WARN_ON in cma_release()
  mm/damon/core: clear walk_control on inactive context in damos_walk()
  mm: memfd_luo: always dirty all folios
  mm: memfd_luo: always make all folios uptodate
This commit is contained in:
Linus Torvalds 2026-03-10 12:47:56 -07:00
commit b4f0dd314b
18 changed files with 163 additions and 73 deletions

View File

@ -498,7 +498,8 @@ Lior David <quic_liord@quicinc.com> <liord@codeaurora.org>
Loic Poulain <loic.poulain@oss.qualcomm.com> <loic.poulain@linaro.org> Loic Poulain <loic.poulain@oss.qualcomm.com> <loic.poulain@linaro.org>
Loic Poulain <loic.poulain@oss.qualcomm.com> <loic.poulain@intel.com> Loic Poulain <loic.poulain@oss.qualcomm.com> <loic.poulain@intel.com>
Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com> Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com>
Lorenzo Stoakes <lorenzo.stoakes@oracle.com> <lstoakes@gmail.com> Lorenzo Stoakes <ljs@kernel.org> <lstoakes@gmail.com>
Lorenzo Stoakes <ljs@kernel.org> <lorenzo.stoakes@oracle.com>
Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net> Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
Luca Weiss <luca@lucaweiss.eu> <luca@z3ntu.xyz> Luca Weiss <luca@lucaweiss.eu> <luca@z3ntu.xyz>
Lucas De Marchi <demarchi@kernel.org> <lucas.demarchi@intel.com> Lucas De Marchi <demarchi@kernel.org> <lucas.demarchi@intel.com>

View File

@ -151,11 +151,11 @@ Description:
The algorithm_params file is write-only and is used to setup The algorithm_params file is write-only and is used to setup
compression algorithm parameters. compression algorithm parameters.
What: /sys/block/zram<id>/writeback_compressed What: /sys/block/zram<id>/compressed_writeback
Date: Decemeber 2025 Date: Decemeber 2025
Contact: Richard Chang <richardycc@google.com> Contact: Richard Chang <richardycc@google.com>
Description: Description:
The writeback_compressed device atrribute toggles compressed The compressed_writeback device atrribute toggles compressed
writeback feature. writeback feature.
What: /sys/block/zram<id>/writeback_batch_size What: /sys/block/zram<id>/writeback_batch_size

View File

@ -216,7 +216,7 @@ writeback_limit WO specifies the maximum amount of write IO zram
writeback_limit_enable RW show and set writeback_limit feature writeback_limit_enable RW show and set writeback_limit feature
writeback_batch_size RW show and set maximum number of in-flight writeback_batch_size RW show and set maximum number of in-flight
writeback operations writeback operations
writeback_compressed RW show and set compressed writeback feature compressed_writeback RW show and set compressed writeback feature
comp_algorithm RW show and change the compression algorithm comp_algorithm RW show and change the compression algorithm
algorithm_params WO setup compression algorithm parameters algorithm_params WO setup compression algorithm parameters
compact WO trigger memory compaction compact WO trigger memory compaction
@ -439,11 +439,11 @@ budget in next setting is user's job.
By default zram stores written back pages in decompressed (raw) form, which By default zram stores written back pages in decompressed (raw) form, which
means that writeback operation involves decompression of the page before means that writeback operation involves decompression of the page before
writing it to the backing device. This behavior can be changed by enabling writing it to the backing device. This behavior can be changed by enabling
`writeback_compressed` feature, which causes zram to write compressed pages `compressed_writeback` feature, which causes zram to write compressed pages
to the backing device, thus avoiding decompression overhead. To enable to the backing device, thus avoiding decompression overhead. To enable
this feature, execute:: this feature, execute::
$ echo yes > /sys/block/zramX/writeback_compressed $ echo yes > /sys/block/zramX/compressed_writeback
Note that this feature should be configured before the `zramX` device is Note that this feature should be configured before the `zramX` device is
initialized. initialized.

View File

@ -16643,7 +16643,7 @@ F: mm/balloon.c
MEMORY MANAGEMENT - CORE MEMORY MANAGEMENT - CORE
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: David Hildenbrand <david@kernel.org> M: David Hildenbrand <david@kernel.org>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> R: Lorenzo Stoakes <ljs@kernel.org>
R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
R: Mike Rapoport <rppt@kernel.org> R: Mike Rapoport <rppt@kernel.org>
@ -16773,7 +16773,7 @@ F: mm/workingset.c
MEMORY MANAGEMENT - MISC MEMORY MANAGEMENT - MISC
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: David Hildenbrand <david@kernel.org> M: David Hildenbrand <david@kernel.org>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> R: Lorenzo Stoakes <ljs@kernel.org>
R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
R: Mike Rapoport <rppt@kernel.org> R: Mike Rapoport <rppt@kernel.org>
@ -16864,7 +16864,7 @@ R: David Hildenbrand <david@kernel.org>
R: Michal Hocko <mhocko@kernel.org> R: Michal Hocko <mhocko@kernel.org>
R: Qi Zheng <zhengqi.arch@bytedance.com> R: Qi Zheng <zhengqi.arch@bytedance.com>
R: Shakeel Butt <shakeel.butt@linux.dev> R: Shakeel Butt <shakeel.butt@linux.dev>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> R: Lorenzo Stoakes <ljs@kernel.org>
L: linux-mm@kvack.org L: linux-mm@kvack.org
S: Maintained S: Maintained
F: mm/vmscan.c F: mm/vmscan.c
@ -16873,7 +16873,7 @@ F: mm/workingset.c
MEMORY MANAGEMENT - RMAP (REVERSE MAPPING) MEMORY MANAGEMENT - RMAP (REVERSE MAPPING)
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: David Hildenbrand <david@kernel.org> M: David Hildenbrand <david@kernel.org>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> M: Lorenzo Stoakes <ljs@kernel.org>
R: Rik van Riel <riel@surriel.com> R: Rik van Riel <riel@surriel.com>
R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
@ -16918,7 +16918,7 @@ F: mm/swapfile.c
MEMORY MANAGEMENT - THP (TRANSPARENT HUGE PAGE) MEMORY MANAGEMENT - THP (TRANSPARENT HUGE PAGE)
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: David Hildenbrand <david@kernel.org> M: David Hildenbrand <david@kernel.org>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> M: Lorenzo Stoakes <ljs@kernel.org>
R: Zi Yan <ziy@nvidia.com> R: Zi Yan <ziy@nvidia.com>
R: Baolin Wang <baolin.wang@linux.alibaba.com> R: Baolin Wang <baolin.wang@linux.alibaba.com>
R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Liam R. Howlett <Liam.Howlett@oracle.com>
@ -16958,7 +16958,7 @@ F: tools/testing/selftests/mm/uffd-*.[ch]
MEMORY MANAGEMENT - RUST MEMORY MANAGEMENT - RUST
M: Alice Ryhl <aliceryhl@google.com> M: Alice Ryhl <aliceryhl@google.com>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> R: Lorenzo Stoakes <ljs@kernel.org>
R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Liam R. Howlett <Liam.Howlett@oracle.com>
L: linux-mm@kvack.org L: linux-mm@kvack.org
L: rust-for-linux@vger.kernel.org L: rust-for-linux@vger.kernel.org
@ -16974,7 +16974,7 @@ F: rust/kernel/page.rs
MEMORY MAPPING MEMORY MAPPING
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: Liam R. Howlett <Liam.Howlett@oracle.com> M: Liam R. Howlett <Liam.Howlett@oracle.com>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> M: Lorenzo Stoakes <ljs@kernel.org>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
R: Jann Horn <jannh@google.com> R: Jann Horn <jannh@google.com>
R: Pedro Falcato <pfalcato@suse.de> R: Pedro Falcato <pfalcato@suse.de>
@ -17004,7 +17004,7 @@ MEMORY MAPPING - LOCKING
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: Suren Baghdasaryan <surenb@google.com> M: Suren Baghdasaryan <surenb@google.com>
M: Liam R. Howlett <Liam.Howlett@oracle.com> M: Liam R. Howlett <Liam.Howlett@oracle.com>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> M: Lorenzo Stoakes <ljs@kernel.org>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
R: Shakeel Butt <shakeel.butt@linux.dev> R: Shakeel Butt <shakeel.butt@linux.dev>
L: linux-mm@kvack.org L: linux-mm@kvack.org
@ -17019,7 +17019,7 @@ F: mm/mmap_lock.c
MEMORY MAPPING - MADVISE (MEMORY ADVICE) MEMORY MAPPING - MADVISE (MEMORY ADVICE)
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
M: Liam R. Howlett <Liam.Howlett@oracle.com> M: Liam R. Howlett <Liam.Howlett@oracle.com>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> M: Lorenzo Stoakes <ljs@kernel.org>
M: David Hildenbrand <david@kernel.org> M: David Hildenbrand <david@kernel.org>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
R: Jann Horn <jannh@google.com> R: Jann Horn <jannh@google.com>
@ -22267,6 +22267,16 @@ L: linux-wireless@vger.kernel.org
S: Orphan S: Orphan
F: drivers/net/wireless/rsi/ F: drivers/net/wireless/rsi/
RELAY
M: Andrew Morton <akpm@linux-foundation.org>
M: Jens Axboe <axboe@kernel.dk>
M: Jason Xing <kernelxing@tencent.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/filesystems/relay.rst
F: include/linux/relay.h
F: kernel/relay.c
REGISTER MAP ABSTRACTION REGISTER MAP ABSTRACTION
M: Mark Brown <broonie@kernel.org> M: Mark Brown <broonie@kernel.org>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
@ -23156,7 +23166,7 @@ K: \b(?i:rust)\b
RUST [ALLOC] RUST [ALLOC]
M: Danilo Krummrich <dakr@kernel.org> M: Danilo Krummrich <dakr@kernel.org>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> R: Lorenzo Stoakes <ljs@kernel.org>
R: Vlastimil Babka <vbabka@kernel.org> R: Vlastimil Babka <vbabka@kernel.org>
R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Uladzislau Rezki <urezki@gmail.com> R: Uladzislau Rezki <urezki@gmail.com>
@ -24333,11 +24343,12 @@ F: drivers/nvmem/layouts/sl28vpd.c
SLAB ALLOCATOR SLAB ALLOCATOR
M: Vlastimil Babka <vbabka@kernel.org> M: Vlastimil Babka <vbabka@kernel.org>
M: Harry Yoo <harry.yoo@oracle.com>
M: Andrew Morton <akpm@linux-foundation.org> M: Andrew Morton <akpm@linux-foundation.org>
R: Hao Li <hao.li@linux.dev>
R: Christoph Lameter <cl@gentwo.org> R: Christoph Lameter <cl@gentwo.org>
R: David Rientjes <rientjes@google.com> R: David Rientjes <rientjes@google.com>
R: Roman Gushchin <roman.gushchin@linux.dev> R: Roman Gushchin <roman.gushchin@linux.dev>
R: Harry Yoo <harry.yoo@oracle.com>
L: linux-mm@kvack.org L: linux-mm@kvack.org
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab.git

View File

@ -549,7 +549,7 @@ static ssize_t bd_stat_show(struct device *dev, struct device_attribute *attr,
return ret; return ret;
} }
static ssize_t writeback_compressed_store(struct device *dev, static ssize_t compressed_writeback_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
{ {
@ -564,12 +564,12 @@ static ssize_t writeback_compressed_store(struct device *dev,
return -EBUSY; return -EBUSY;
} }
zram->wb_compressed = val; zram->compressed_wb = val;
return len; return len;
} }
static ssize_t writeback_compressed_show(struct device *dev, static ssize_t compressed_writeback_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
@ -577,7 +577,7 @@ static ssize_t writeback_compressed_show(struct device *dev,
struct zram *zram = dev_to_zram(dev); struct zram *zram = dev_to_zram(dev);
guard(rwsem_read)(&zram->dev_lock); guard(rwsem_read)(&zram->dev_lock);
val = zram->wb_compressed; val = zram->compressed_wb;
return sysfs_emit(buf, "%d\n", val); return sysfs_emit(buf, "%d\n", val);
} }
@ -946,7 +946,7 @@ static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
goto out; goto out;
} }
if (zram->wb_compressed) { if (zram->compressed_wb) {
/* /*
* ZRAM_WB slots get freed, we need to preserve data required * ZRAM_WB slots get freed, we need to preserve data required
* for read decompression. * for read decompression.
@ -960,7 +960,7 @@ static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
set_slot_flag(zram, index, ZRAM_WB); set_slot_flag(zram, index, ZRAM_WB);
set_slot_handle(zram, index, req->blk_idx); set_slot_handle(zram, index, req->blk_idx);
if (zram->wb_compressed) { if (zram->compressed_wb) {
if (huge) if (huge)
set_slot_flag(zram, index, ZRAM_HUGE); set_slot_flag(zram, index, ZRAM_HUGE);
set_slot_size(zram, index, size); set_slot_size(zram, index, size);
@ -1100,7 +1100,7 @@ static int zram_writeback_slots(struct zram *zram,
*/ */
if (!test_slot_flag(zram, index, ZRAM_PP_SLOT)) if (!test_slot_flag(zram, index, ZRAM_PP_SLOT))
goto next; goto next;
if (zram->wb_compressed) if (zram->compressed_wb)
err = read_from_zspool_raw(zram, req->page, index); err = read_from_zspool_raw(zram, req->page, index);
else else
err = read_from_zspool(zram, req->page, index); err = read_from_zspool(zram, req->page, index);
@ -1429,7 +1429,7 @@ static void zram_async_read_endio(struct bio *bio)
* *
* Keep the existing behavior for now. * Keep the existing behavior for now.
*/ */
if (zram->wb_compressed == false) { if (zram->compressed_wb == false) {
/* No decompression needed, complete the parent IO */ /* No decompression needed, complete the parent IO */
bio_endio(req->parent); bio_endio(req->parent);
bio_put(bio); bio_put(bio);
@ -1508,7 +1508,7 @@ static int read_from_bdev_sync(struct zram *zram, struct page *page, u32 index,
flush_work(&req.work); flush_work(&req.work);
destroy_work_on_stack(&req.work); destroy_work_on_stack(&req.work);
if (req.error || zram->wb_compressed == false) if (req.error || zram->compressed_wb == false)
return req.error; return req.error;
return decompress_bdev_page(zram, page, index); return decompress_bdev_page(zram, page, index);
@ -3007,7 +3007,7 @@ static DEVICE_ATTR_WO(writeback);
static DEVICE_ATTR_RW(writeback_limit); static DEVICE_ATTR_RW(writeback_limit);
static DEVICE_ATTR_RW(writeback_limit_enable); static DEVICE_ATTR_RW(writeback_limit_enable);
static DEVICE_ATTR_RW(writeback_batch_size); static DEVICE_ATTR_RW(writeback_batch_size);
static DEVICE_ATTR_RW(writeback_compressed); static DEVICE_ATTR_RW(compressed_writeback);
#endif #endif
#ifdef CONFIG_ZRAM_MULTI_COMP #ifdef CONFIG_ZRAM_MULTI_COMP
static DEVICE_ATTR_RW(recomp_algorithm); static DEVICE_ATTR_RW(recomp_algorithm);
@ -3031,7 +3031,7 @@ static struct attribute *zram_disk_attrs[] = {
&dev_attr_writeback_limit.attr, &dev_attr_writeback_limit.attr,
&dev_attr_writeback_limit_enable.attr, &dev_attr_writeback_limit_enable.attr,
&dev_attr_writeback_batch_size.attr, &dev_attr_writeback_batch_size.attr,
&dev_attr_writeback_compressed.attr, &dev_attr_compressed_writeback.attr,
#endif #endif
&dev_attr_io_stat.attr, &dev_attr_io_stat.attr,
&dev_attr_mm_stat.attr, &dev_attr_mm_stat.attr,
@ -3091,7 +3091,7 @@ static int zram_add(void)
init_rwsem(&zram->dev_lock); init_rwsem(&zram->dev_lock);
#ifdef CONFIG_ZRAM_WRITEBACK #ifdef CONFIG_ZRAM_WRITEBACK
zram->wb_batch_size = 32; zram->wb_batch_size = 32;
zram->wb_compressed = false; zram->compressed_wb = false;
#endif #endif
/* gendisk structure */ /* gendisk structure */

View File

@ -133,7 +133,7 @@ struct zram {
#ifdef CONFIG_ZRAM_WRITEBACK #ifdef CONFIG_ZRAM_WRITEBACK
struct file *backing_dev; struct file *backing_dev;
bool wb_limit_enable; bool wb_limit_enable;
bool wb_compressed; bool compressed_wb;
u32 wb_batch_size; u32 wb_batch_size;
u64 bd_wb_limit; u64 bd_wb_limit;
struct block_device *bdev; struct block_device *bdev;

View File

@ -3514,26 +3514,21 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; }
static inline void ptlock_free(struct ptdesc *ptdesc) {} static inline void ptlock_free(struct ptdesc *ptdesc) {}
#endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */ #endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
static inline unsigned long ptdesc_nr_pages(const struct ptdesc *ptdesc)
{
return compound_nr(ptdesc_page(ptdesc));
}
static inline void __pagetable_ctor(struct ptdesc *ptdesc) static inline void __pagetable_ctor(struct ptdesc *ptdesc)
{ {
pg_data_t *pgdat = NODE_DATA(memdesc_nid(ptdesc->pt_flags)); struct folio *folio = ptdesc_folio(ptdesc);
__SetPageTable(ptdesc_page(ptdesc)); __folio_set_pgtable(folio);
mod_node_page_state(pgdat, NR_PAGETABLE, ptdesc_nr_pages(ptdesc)); lruvec_stat_add_folio(folio, NR_PAGETABLE);
} }
static inline void pagetable_dtor(struct ptdesc *ptdesc) static inline void pagetable_dtor(struct ptdesc *ptdesc)
{ {
pg_data_t *pgdat = NODE_DATA(memdesc_nid(ptdesc->pt_flags)); struct folio *folio = ptdesc_folio(ptdesc);
ptlock_free(ptdesc); ptlock_free(ptdesc);
__ClearPageTable(ptdesc_page(ptdesc)); __folio_clear_pgtable(folio);
mod_node_page_state(pgdat, NR_PAGETABLE, -ptdesc_nr_pages(ptdesc)); lruvec_stat_sub_folio(folio, NR_PAGETABLE);
} }
static inline void pagetable_dtor_free(struct ptdesc *ptdesc) static inline void pagetable_dtor_free(struct ptdesc *ptdesc)

View File

@ -234,7 +234,7 @@ struct mmu_notifier {
}; };
/** /**
* struct mmu_interval_notifier_ops * struct mmu_interval_notifier_ops - callback for range notification
* @invalidate: Upon return the caller must stop using any SPTEs within this * @invalidate: Upon return the caller must stop using any SPTEs within this
* range. This function can sleep. Return false only if sleeping * range. This function can sleep. Return false only if sleeping
* was required but mmu_notifier_range_blockable(range) is false. * was required but mmu_notifier_range_blockable(range) is false.
@ -309,8 +309,8 @@ void mmu_interval_notifier_remove(struct mmu_interval_notifier *interval_sub);
/** /**
* mmu_interval_set_seq - Save the invalidation sequence * mmu_interval_set_seq - Save the invalidation sequence
* @interval_sub - The subscription passed to invalidate * @interval_sub: The subscription passed to invalidate
* @cur_seq - The cur_seq passed to the invalidate() callback * @cur_seq: The cur_seq passed to the invalidate() callback
* *
* This must be called unconditionally from the invalidate callback of a * This must be called unconditionally from the invalidate callback of a
* struct mmu_interval_notifier_ops under the same lock that is used to call * struct mmu_interval_notifier_ops under the same lock that is used to call
@ -329,8 +329,8 @@ mmu_interval_set_seq(struct mmu_interval_notifier *interval_sub,
/** /**
* mmu_interval_read_retry - End a read side critical section against a VA range * mmu_interval_read_retry - End a read side critical section against a VA range
* interval_sub: The subscription * @interval_sub: The subscription
* seq: The return of the paired mmu_interval_read_begin() * @seq: The return of the paired mmu_interval_read_begin()
* *
* This MUST be called under a user provided lock that is also held * This MUST be called under a user provided lock that is also held
* unconditionally by op->invalidate() when it calls mmu_interval_set_seq(). * unconditionally by op->invalidate() when it calls mmu_interval_set_seq().
@ -338,7 +338,7 @@ mmu_interval_set_seq(struct mmu_interval_notifier *interval_sub,
* Each call should be paired with a single mmu_interval_read_begin() and * Each call should be paired with a single mmu_interval_read_begin() and
* should be used to conclude the read side. * should be used to conclude the read side.
* *
* Returns true if an invalidation collided with this critical section, and * Returns: true if an invalidation collided with this critical section, and
* the caller should retry. * the caller should retry.
*/ */
static inline bool static inline bool
@ -350,20 +350,21 @@ mmu_interval_read_retry(struct mmu_interval_notifier *interval_sub,
/** /**
* mmu_interval_check_retry - Test if a collision has occurred * mmu_interval_check_retry - Test if a collision has occurred
* interval_sub: The subscription * @interval_sub: The subscription
* seq: The return of the matching mmu_interval_read_begin() * @seq: The return of the matching mmu_interval_read_begin()
* *
* This can be used in the critical section between mmu_interval_read_begin() * This can be used in the critical section between mmu_interval_read_begin()
* and mmu_interval_read_retry(). A return of true indicates an invalidation * and mmu_interval_read_retry().
* has collided with this critical region and a future
* mmu_interval_read_retry() will return true.
*
* False is not reliable and only suggests a collision may not have
* occurred. It can be called many times and does not have to hold the user
* provided lock.
* *
* This call can be used as part of loops and other expensive operations to * This call can be used as part of loops and other expensive operations to
* expedite a retry. * expedite a retry.
* It can be called many times and does not have to hold the user
* provided lock.
*
* Returns: true indicates an invalidation has collided with this critical
* region and a future mmu_interval_read_retry() will return true.
* False is not reliable and only suggests a collision may not have
* occurred.
*/ */
static inline bool static inline bool
mmu_interval_check_retry(struct mmu_interval_notifier *interval_sub, mmu_interval_check_retry(struct mmu_interval_notifier *interval_sub,

View File

@ -792,7 +792,7 @@ for (bool done = false; !done; done = true) \
/** /**
* scoped_user_rw_access_size - Start a scoped user read/write access with given size * scoped_user_rw_access_size - Start a scoped user read/write access with given size
* @uptr Pointer to the user space address to read from and write to * @uptr: Pointer to the user space address to read from and write to
* @size: Size of the access starting from @uptr * @size: Size of the access starting from @uptr
* @elbl: Error label to goto when the access region is rejected * @elbl: Error label to goto when the access region is rejected
* *
@ -803,7 +803,7 @@ for (bool done = false; !done; done = true) \
/** /**
* scoped_user_rw_access - Start a scoped user read/write access * scoped_user_rw_access - Start a scoped user read/write access
* @uptr Pointer to the user space address to read from and write to * @uptr: Pointer to the user space address to read from and write to
* @elbl: Error label to goto when the access region is rejected * @elbl: Error label to goto when the access region is rejected
* *
* The size of the access starting from @uptr is determined via sizeof(*@uptr)). * The size of the access starting from @uptr is determined via sizeof(*@uptr)).

View File

@ -1013,6 +1013,7 @@ bool cma_release(struct cma *cma, const struct page *pages,
unsigned long count) unsigned long count)
{ {
struct cma_memrange *cmr; struct cma_memrange *cmr;
unsigned long ret = 0;
unsigned long i, pfn; unsigned long i, pfn;
cmr = find_cma_memrange(cma, pages, count); cmr = find_cma_memrange(cma, pages, count);
@ -1021,7 +1022,9 @@ bool cma_release(struct cma *cma, const struct page *pages,
pfn = page_to_pfn(pages); pfn = page_to_pfn(pages);
for (i = 0; i < count; i++, pfn++) for (i = 0; i < count; i++, pfn++)
VM_WARN_ON(!put_page_testzero(pfn_to_page(pfn))); ret += !put_page_testzero(pfn_to_page(pfn));
WARN(ret, "%lu pages are still in use!\n", ret);
__cma_release_frozen(cma, cmr, pages, count); __cma_release_frozen(cma, cmr, pages, count);

View File

@ -1562,8 +1562,13 @@ int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control)
} }
ctx->walk_control = control; ctx->walk_control = control;
mutex_unlock(&ctx->walk_control_lock); mutex_unlock(&ctx->walk_control_lock);
if (!damon_is_running(ctx)) if (!damon_is_running(ctx)) {
mutex_lock(&ctx->walk_control_lock);
if (ctx->walk_control == control)
ctx->walk_control = NULL;
mutex_unlock(&ctx->walk_control_lock);
return -EINVAL; return -EINVAL;
}
wait_for_completion(&control->completion); wait_for_completion(&control->completion);
if (control->canceled) if (control->canceled)
return -ECANCELED; return -ECANCELED;

View File

@ -3631,6 +3631,7 @@ static int __split_unmapped_folio(struct folio *folio, int new_order,
const bool is_anon = folio_test_anon(folio); const bool is_anon = folio_test_anon(folio);
int old_order = folio_order(folio); int old_order = folio_order(folio);
int start_order = split_type == SPLIT_TYPE_UNIFORM ? new_order : old_order - 1; int start_order = split_type == SPLIT_TYPE_UNIFORM ? new_order : old_order - 1;
struct folio *old_folio = folio;
int split_order; int split_order;
/* /*
@ -3651,12 +3652,16 @@ static int __split_unmapped_folio(struct folio *folio, int new_order,
* uniform split has xas_split_alloc() called before * uniform split has xas_split_alloc() called before
* irq is disabled to allocate enough memory, whereas * irq is disabled to allocate enough memory, whereas
* non-uniform split can handle ENOMEM. * non-uniform split can handle ENOMEM.
* Use the to-be-split folio, so that a parallel
* folio_try_get() waits on it until xarray is updated
* with after-split folios and the original one is
* unfrozen.
*/ */
if (split_type == SPLIT_TYPE_UNIFORM) if (split_type == SPLIT_TYPE_UNIFORM) {
xas_split(xas, folio, old_order); xas_split(xas, old_folio, old_order);
else { } else {
xas_set_order(xas, folio->index, split_order); xas_set_order(xas, folio->index, split_order);
xas_try_split(xas, folio, old_order); xas_try_split(xas, old_folio, old_order);
if (xas_error(xas)) if (xas_error(xas))
return xas_error(xas); return xas_error(xas);
} }

View File

@ -3101,7 +3101,7 @@ static __init void *alloc_bootmem(struct hstate *h, int nid, bool node_exact)
* extract the actual node first. * extract the actual node first.
*/ */
if (m) if (m)
listnode = early_pfn_to_nid(PHYS_PFN(virt_to_phys(m))); listnode = early_pfn_to_nid(PHYS_PFN(__pa(m)));
} }
if (m) { if (m) {
@ -3160,7 +3160,7 @@ found:
* The head struct page is used to get folio information by the HugeTLB * The head struct page is used to get folio information by the HugeTLB
* subsystem like zone id and node id. * subsystem like zone id and node id.
*/ */
memblock_reserved_mark_noinit(virt_to_phys((void *)m + PAGE_SIZE), memblock_reserved_mark_noinit(__pa((void *)m + PAGE_SIZE),
huge_page_size(h) - PAGE_SIZE); huge_page_size(h) - PAGE_SIZE);
return 1; return 1;

View File

@ -3086,7 +3086,7 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
if (!local_trylock(&obj_stock.lock)) { if (!local_trylock(&obj_stock.lock)) {
if (pgdat) if (pgdat)
mod_objcg_mlstate(objcg, pgdat, idx, nr_bytes); mod_objcg_mlstate(objcg, pgdat, idx, nr_acct);
nr_pages = nr_bytes >> PAGE_SHIFT; nr_pages = nr_bytes >> PAGE_SHIFT;
nr_bytes = nr_bytes & (PAGE_SIZE - 1); nr_bytes = nr_bytes & (PAGE_SIZE - 1);
atomic_add(nr_bytes, &objcg->nr_charged_bytes); atomic_add(nr_bytes, &objcg->nr_charged_bytes);

View File

@ -146,19 +146,56 @@ static int memfd_luo_preserve_folios(struct file *file,
for (i = 0; i < nr_folios; i++) { for (i = 0; i < nr_folios; i++) {
struct memfd_luo_folio_ser *pfolio = &folios_ser[i]; struct memfd_luo_folio_ser *pfolio = &folios_ser[i];
struct folio *folio = folios[i]; struct folio *folio = folios[i];
unsigned int flags = 0;
err = kho_preserve_folio(folio); err = kho_preserve_folio(folio);
if (err) if (err)
goto err_unpreserve; goto err_unpreserve;
if (folio_test_dirty(folio)) folio_lock(folio);
flags |= MEMFD_LUO_FOLIO_DIRTY;
if (folio_test_uptodate(folio)) /*
flags |= MEMFD_LUO_FOLIO_UPTODATE; * A dirty folio is one which has been written to. A clean folio
* is its opposite. Since a clean folio does not carry user
* data, it can be freed by page reclaim under memory pressure.
*
* Saving the dirty flag at prepare() time doesn't work since it
* can change later. Saving it at freeze() also won't work
* because the dirty bit is normally synced at unmap and there
* might still be a mapping of the file at freeze().
*
* To see why this is a problem, say a folio is clean at
* preserve, but gets dirtied later. The pfolio flags will mark
* it as clean. After retrieve, the next kernel might try to
* reclaim this folio under memory pressure, losing user data.
*
* Unconditionally mark it dirty to avoid this problem. This
* comes at the cost of making clean folios un-reclaimable after
* live update.
*/
folio_mark_dirty(folio);
/*
* If the folio is not uptodate, it was fallocated but never
* used. Saving this flag at prepare() doesn't work since it
* might change later when someone uses the folio.
*
* Since we have taken the performance penalty of allocating,
* zeroing, and pinning all the folios in the holes, take a bit
* more and zero all non-uptodate folios too.
*
* NOTE: For someone looking to improve preserve performance,
* this is a good place to look.
*/
if (!folio_test_uptodate(folio)) {
folio_zero_range(folio, 0, folio_size(folio));
flush_dcache_folio(folio);
folio_mark_uptodate(folio);
}
folio_unlock(folio);
pfolio->pfn = folio_pfn(folio); pfolio->pfn = folio_pfn(folio);
pfolio->flags = flags; pfolio->flags = MEMFD_LUO_FOLIO_DIRTY | MEMFD_LUO_FOLIO_UPTODATE;
pfolio->index = folio->index; pfolio->index = folio->index;
} }

View File

@ -5,6 +5,10 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/gfp_types.h> #include <linux/gfp_types.h>
/* Helper macro to avoid gfp flags if they are the default one */
#define __default_gfp(a,...) a
#define default_gfp(...) __default_gfp(__VA_ARGS__ __VA_OPT__(,) GFP_KERNEL)
static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
{ {
return !!(gfp_flags & __GFP_DIRECT_RECLAIM); return !!(gfp_flags & __GFP_DIRECT_RECLAIM);

View File

@ -68,6 +68,25 @@
__builtin_mul_overflow(__a, __b, __d); \ __builtin_mul_overflow(__a, __b, __d); \
}) })
/**
* size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX
* @factor1: first factor
* @factor2: second factor
*
* Returns: calculate @factor1 * @factor2, both promoted to size_t,
* with any overflow causing the return value to be SIZE_MAX. The
* lvalue must be size_t to avoid implicit type conversion.
*/
static inline size_t __must_check size_mul(size_t factor1, size_t factor2)
{
size_t bytes;
if (check_mul_overflow(factor1, factor2, &bytes))
return SIZE_MAX;
return bytes;
}
/** /**
* array_size() - Calculate size of 2-dimensional array. * array_size() - Calculate size of 2-dimensional array.
* *

View File

@ -202,4 +202,13 @@ static inline unsigned int kmem_cache_sheaf_size(struct slab_sheaf *sheaf)
return sheaf->size; return sheaf->size;
} }
#define __alloc_objs(KMALLOC, GFP, TYPE, COUNT) \
({ \
const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \
(TYPE *)KMALLOC(__obj_size, GFP); \
})
#define kzalloc_obj(P, ...) \
__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
#endif /* _TOOLS_SLAB_H */ #endif /* _TOOLS_SLAB_H */