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:
commit
b4f0dd314b
3
.mailmap
3
.mailmap
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
33
MAINTAINERS
33
MAINTAINERS
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)).
|
||||||
|
|
|
||||||
5
mm/cma.c
5
mm/cma.c
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue