Skip to content

Commit 4b49c0b

Browse files
committed
Merge tag 'mm-hotfixes-stable-2024-11-12-16-39' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull misc fixes from Andrew Morton: "10 hotfixes, 7 of which are cc:stable. 7 are MM, 3 are not. All singletons" * tag 'mm-hotfixes-stable-2024-11-12-16-39' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm: swapfile: fix cluster reclaim work crash on rotational devices selftests: hugetlb_dio: fixup check for initial conditions to skip in the start mm/thp: fix deferred split queue not partially_mapped: fix mm/gup: avoid an unnecessary allocation call for FOLL_LONGTERM cases nommu: pass NULL argument to vma_iter_prealloc() ocfs2: fix UBSAN warning in ocfs2_verify_volume() nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint nilfs2: fix null-ptr-deref in block_touch_buffer tracepoint mm: page_alloc: move mlocked flag clearance into free_pages_prepare() mm: count zeromap read and set for swapout and swapin
2 parents f1b785f + dcf32ea commit 4b49c0b

File tree

19 files changed

+158
-75
lines changed

19 files changed

+158
-75
lines changed

Documentation/admin-guide/cgroup-v2.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,15 @@ The following nested keys are defined.
15991599
pglazyfreed (npn)
16001600
Amount of reclaimed lazyfree pages
16011601

1602+
swpin_zero
1603+
Number of pages swapped into memory and filled with zero, where I/O
1604+
was optimized out because the page content was detected to be zero
1605+
during swapout.
1606+
1607+
swpout_zero
1608+
Number of zero-filled pages swapped out with I/O skipped due to the
1609+
content being detected as zero.
1610+
16021611
zswpin
16031612
Number of pages moved in to memory from zswap.
16041613

fs/nilfs2/btnode.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
6868
goto failed;
6969
}
7070
memset(bh->b_data, 0, i_blocksize(inode));
71-
bh->b_bdev = inode->i_sb->s_bdev;
7271
bh->b_blocknr = blocknr;
7372
set_buffer_mapped(bh);
7473
set_buffer_uptodate(bh);
@@ -133,7 +132,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
133132
goto found;
134133
}
135134
set_buffer_mapped(bh);
136-
bh->b_bdev = inode->i_sb->s_bdev;
137135
bh->b_blocknr = pblocknr; /* set block address for read */
138136
bh->b_end_io = end_buffer_read_sync;
139137
get_bh(bh);

fs/nilfs2/gcinode.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,8 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff,
8383
goto out;
8484
}
8585

86-
if (!buffer_mapped(bh)) {
87-
bh->b_bdev = inode->i_sb->s_bdev;
86+
if (!buffer_mapped(bh))
8887
set_buffer_mapped(bh);
89-
}
9088
bh->b_blocknr = pbn;
9189
bh->b_end_io = end_buffer_read_sync;
9290
get_bh(bh);

fs/nilfs2/mdt.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
8989
if (buffer_uptodate(bh))
9090
goto failed_bh;
9191

92-
bh->b_bdev = sb->s_bdev;
9392
err = nilfs_mdt_insert_new_block(inode, block, bh, init_block);
9493
if (likely(!err)) {
9594
get_bh(bh);

fs/nilfs2/page.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ static struct buffer_head *__nilfs_get_folio_block(struct folio *folio,
3939
first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
4040
bh = get_nth_bh(bh, block - first_block);
4141

42-
touch_buffer(bh);
4342
wait_on_buffer(bh);
4443
return bh;
4544
}
@@ -64,6 +63,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
6463
folio_put(folio);
6564
return NULL;
6665
}
66+
bh->b_bdev = inode->i_sb->s_bdev;
6767
return bh;
6868
}
6969

fs/ocfs2/super.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,6 +2319,7 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
23192319
struct ocfs2_blockcheck_stats *stats)
23202320
{
23212321
int status = -EAGAIN;
2322+
u32 blksz_bits;
23222323

23232324
if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
23242325
strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) {
@@ -2333,11 +2334,15 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
23332334
goto out;
23342335
}
23352336
status = -EINVAL;
2336-
if ((1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits)) != blksz) {
2337+
/* Acceptable block sizes are 512 bytes, 1K, 2K and 4K. */
2338+
blksz_bits = le32_to_cpu(di->id2.i_super.s_blocksize_bits);
2339+
if (blksz_bits < 9 || blksz_bits > 12) {
23372340
mlog(ML_ERROR, "found superblock with incorrect block "
2338-
"size: found %u, should be %u\n",
2339-
1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits),
2340-
blksz);
2341+
"size bits: found %u, should be 9, 10, 11, or 12\n",
2342+
blksz_bits);
2343+
} else if ((1 << le32_to_cpu(blksz_bits)) != blksz) {
2344+
mlog(ML_ERROR, "found superblock with incorrect block "
2345+
"size: found %u, should be %u\n", 1 << blksz_bits, blksz);
23412346
} else if (le16_to_cpu(di->id2.i_super.s_major_rev_level) !=
23422347
OCFS2_MAJOR_REV_LEVEL ||
23432348
le16_to_cpu(di->id2.i_super.s_minor_rev_level) !=

include/linux/memcontrol.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,8 +1760,9 @@ static inline int memcg_kmem_id(struct mem_cgroup *memcg)
17601760

17611761
struct mem_cgroup *mem_cgroup_from_slab_obj(void *p);
17621762

1763-
static inline void count_objcg_event(struct obj_cgroup *objcg,
1764-
enum vm_event_item idx)
1763+
static inline void count_objcg_events(struct obj_cgroup *objcg,
1764+
enum vm_event_item idx,
1765+
unsigned long count)
17651766
{
17661767
struct mem_cgroup *memcg;
17671768

@@ -1770,7 +1771,7 @@ static inline void count_objcg_event(struct obj_cgroup *objcg,
17701771

17711772
rcu_read_lock();
17721773
memcg = obj_cgroup_memcg(objcg);
1773-
count_memcg_events(memcg, idx, 1);
1774+
count_memcg_events(memcg, idx, count);
17741775
rcu_read_unlock();
17751776
}
17761777

@@ -1825,8 +1826,9 @@ static inline struct mem_cgroup *mem_cgroup_from_slab_obj(void *p)
18251826
return NULL;
18261827
}
18271828

1828-
static inline void count_objcg_event(struct obj_cgroup *objcg,
1829-
enum vm_event_item idx)
1829+
static inline void count_objcg_events(struct obj_cgroup *objcg,
1830+
enum vm_event_item idx,
1831+
unsigned long count)
18301832
{
18311833
}
18321834

include/linux/vm_event_item.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
134134
#ifdef CONFIG_SWAP
135135
SWAP_RA,
136136
SWAP_RA_HIT,
137+
SWPIN_ZERO,
138+
SWPOUT_ZERO,
137139
#ifdef CONFIG_KSM
138140
KSM_SWPIN_COPY,
139141
#endif

mm/gup.c

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,20 +2273,57 @@ struct page *get_dump_page(unsigned long addr)
22732273
#endif /* CONFIG_ELF_CORE */
22742274

22752275
#ifdef CONFIG_MIGRATION
2276+
2277+
/*
2278+
* An array of either pages or folios ("pofs"). Although it may seem tempting to
2279+
* avoid this complication, by simply interpreting a list of folios as a list of
2280+
* pages, that approach won't work in the longer term, because eventually the
2281+
* layouts of struct page and struct folio will become completely different.
2282+
* Furthermore, this pof approach avoids excessive page_folio() calls.
2283+
*/
2284+
struct pages_or_folios {
2285+
union {
2286+
struct page **pages;
2287+
struct folio **folios;
2288+
void **entries;
2289+
};
2290+
bool has_folios;
2291+
long nr_entries;
2292+
};
2293+
2294+
static struct folio *pofs_get_folio(struct pages_or_folios *pofs, long i)
2295+
{
2296+
if (pofs->has_folios)
2297+
return pofs->folios[i];
2298+
return page_folio(pofs->pages[i]);
2299+
}
2300+
2301+
static void pofs_clear_entry(struct pages_or_folios *pofs, long i)
2302+
{
2303+
pofs->entries[i] = NULL;
2304+
}
2305+
2306+
static void pofs_unpin(struct pages_or_folios *pofs)
2307+
{
2308+
if (pofs->has_folios)
2309+
unpin_folios(pofs->folios, pofs->nr_entries);
2310+
else
2311+
unpin_user_pages(pofs->pages, pofs->nr_entries);
2312+
}
2313+
22762314
/*
22772315
* Returns the number of collected folios. Return value is always >= 0.
22782316
*/
22792317
static unsigned long collect_longterm_unpinnable_folios(
2280-
struct list_head *movable_folio_list,
2281-
unsigned long nr_folios,
2282-
struct folio **folios)
2318+
struct list_head *movable_folio_list,
2319+
struct pages_or_folios *pofs)
22832320
{
22842321
unsigned long i, collected = 0;
22852322
struct folio *prev_folio = NULL;
22862323
bool drain_allow = true;
22872324

2288-
for (i = 0; i < nr_folios; i++) {
2289-
struct folio *folio = folios[i];
2325+
for (i = 0; i < pofs->nr_entries; i++) {
2326+
struct folio *folio = pofs_get_folio(pofs, i);
22902327

22912328
if (folio == prev_folio)
22922329
continue;
@@ -2327,24 +2364,23 @@ static unsigned long collect_longterm_unpinnable_folios(
23272364
* Returns -EAGAIN if all folios were successfully migrated or -errno for
23282365
* failure (or partial success).
23292366
*/
2330-
static int migrate_longterm_unpinnable_folios(
2331-
struct list_head *movable_folio_list,
2332-
unsigned long nr_folios,
2333-
struct folio **folios)
2367+
static int
2368+
migrate_longterm_unpinnable_folios(struct list_head *movable_folio_list,
2369+
struct pages_or_folios *pofs)
23342370
{
23352371
int ret;
23362372
unsigned long i;
23372373

2338-
for (i = 0; i < nr_folios; i++) {
2339-
struct folio *folio = folios[i];
2374+
for (i = 0; i < pofs->nr_entries; i++) {
2375+
struct folio *folio = pofs_get_folio(pofs, i);
23402376

23412377
if (folio_is_device_coherent(folio)) {
23422378
/*
23432379
* Migration will fail if the folio is pinned, so
23442380
* convert the pin on the source folio to a normal
23452381
* reference.
23462382
*/
2347-
folios[i] = NULL;
2383+
pofs_clear_entry(pofs, i);
23482384
folio_get(folio);
23492385
gup_put_folio(folio, 1, FOLL_PIN);
23502386

@@ -2363,8 +2399,8 @@ static int migrate_longterm_unpinnable_folios(
23632399
* calling folio_isolate_lru() which takes a reference so the
23642400
* folio won't be freed if it's migrating.
23652401
*/
2366-
unpin_folio(folios[i]);
2367-
folios[i] = NULL;
2402+
unpin_folio(folio);
2403+
pofs_clear_entry(pofs, i);
23682404
}
23692405

23702406
if (!list_empty(movable_folio_list)) {
@@ -2387,12 +2423,26 @@ static int migrate_longterm_unpinnable_folios(
23872423
return -EAGAIN;
23882424

23892425
err:
2390-
unpin_folios(folios, nr_folios);
2426+
pofs_unpin(pofs);
23912427
putback_movable_pages(movable_folio_list);
23922428

23932429
return ret;
23942430
}
23952431

2432+
static long
2433+
check_and_migrate_movable_pages_or_folios(struct pages_or_folios *pofs)
2434+
{
2435+
LIST_HEAD(movable_folio_list);
2436+
unsigned long collected;
2437+
2438+
collected = collect_longterm_unpinnable_folios(&movable_folio_list,
2439+
pofs);
2440+
if (!collected)
2441+
return 0;
2442+
2443+
return migrate_longterm_unpinnable_folios(&movable_folio_list, pofs);
2444+
}
2445+
23962446
/*
23972447
* Check whether all folios are *allowed* to be pinned indefinitely (long term).
23982448
* Rather confusingly, all folios in the range are required to be pinned via
@@ -2417,16 +2467,13 @@ static int migrate_longterm_unpinnable_folios(
24172467
static long check_and_migrate_movable_folios(unsigned long nr_folios,
24182468
struct folio **folios)
24192469
{
2420-
unsigned long collected;
2421-
LIST_HEAD(movable_folio_list);
2470+
struct pages_or_folios pofs = {
2471+
.folios = folios,
2472+
.has_folios = true,
2473+
.nr_entries = nr_folios,
2474+
};
24222475

2423-
collected = collect_longterm_unpinnable_folios(&movable_folio_list,
2424-
nr_folios, folios);
2425-
if (!collected)
2426-
return 0;
2427-
2428-
return migrate_longterm_unpinnable_folios(&movable_folio_list,
2429-
nr_folios, folios);
2476+
return check_and_migrate_movable_pages_or_folios(&pofs);
24302477
}
24312478

24322479
/*
@@ -2436,22 +2483,13 @@ static long check_and_migrate_movable_folios(unsigned long nr_folios,
24362483
static long check_and_migrate_movable_pages(unsigned long nr_pages,
24372484
struct page **pages)
24382485
{
2439-
struct folio **folios;
2440-
long i, ret;
2486+
struct pages_or_folios pofs = {
2487+
.pages = pages,
2488+
.has_folios = false,
2489+
.nr_entries = nr_pages,
2490+
};
24412491

2442-
folios = kmalloc_array(nr_pages, sizeof(*folios), GFP_KERNEL);
2443-
if (!folios) {
2444-
unpin_user_pages(pages, nr_pages);
2445-
return -ENOMEM;
2446-
}
2447-
2448-
for (i = 0; i < nr_pages; i++)
2449-
folios[i] = page_folio(pages[i]);
2450-
2451-
ret = check_and_migrate_movable_folios(nr_pages, folios);
2452-
2453-
kfree(folios);
2454-
return ret;
2492+
return check_and_migrate_movable_pages_or_folios(&pofs);
24552493
}
24562494
#else
24572495
static long check_and_migrate_movable_pages(unsigned long nr_pages,

mm/huge_memory.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3790,7 +3790,9 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
37903790
* in the case it was underused, then consider it used and
37913791
* don't add it back to split_queue.
37923792
*/
3793-
if (!did_split && !folio_test_partially_mapped(folio)) {
3793+
if (did_split) {
3794+
; /* folio already removed from list */
3795+
} else if (!folio_test_partially_mapped(folio)) {
37943796
list_del_init(&folio->_deferred_list);
37953797
removed++;
37963798
} else {

0 commit comments

Comments
 (0)