From: Dan Carpenter <dan.carpenter@linaro.org>
To: Zi Yan <ziy@nvidia.com>
Cc: linux-mm@kvack.org
Subject: [bug report] mm/huge_memory: add two new (not yet used) functions for folio_split()
Date: Wed, 12 Feb 2025 18:13:16 +0300 [thread overview]
Message-ID: <2afe3d59-aca5-40f7-82a3-a6d976fb0f4f@stanley.mountain> (raw)
Hello Zi Yan,
Commit 1b7b0bed44e4 ("mm/huge_memory: add two new (not yet used)
functions for folio_split()") from Feb 4, 2025 (linux-next), leads to
the following Smatch static checker warning:
mm/huge_memory.c:3611 __split_unmapped_folio()
error: we previously assumed 'mapping' could be null (see line 3512)
mm/huge_memory.c
3459 static int __split_unmapped_folio(struct folio *folio, int new_order,
3460 struct page *page, struct list_head *list, pgoff_t end,
3461 struct xa_state *xas, struct address_space *mapping,
3462 bool uniform_split)
3463 {
3464 struct lruvec *lruvec;
3465 struct address_space *swap_cache = NULL;
3466 struct folio *origin_folio = folio;
3467 struct folio *next_folio = folio_next(folio);
3468 struct folio *new_folio;
3469 struct folio *next;
3470 int order = folio_order(folio);
3471 int split_order;
3472 int start_order = uniform_split ? new_order : order - 1;
3473 int nr_dropped = 0;
3474 int ret = 0;
3475 bool stop_split = false;
3476
3477 if (folio_test_anon(folio) && folio_test_swapcache(folio)) {
3478 /* a swapcache folio can only be uniformly split to order-0 */
3479 if (!uniform_split || new_order != 0)
3480 return -EINVAL;
3481
3482 swap_cache = swap_address_space(folio->swap);
3483 xa_lock(&swap_cache->i_pages);
3484 }
3485
3486 if (folio_test_anon(folio))
3487 mod_mthp_stat(order, MTHP_STAT_NR_ANON, -1);
3488
3489 /* lock lru list/PageCompound, ref frozen by page_ref_freeze */
3490 lruvec = folio_lruvec_lock(folio);
3491
3492 folio_clear_has_hwpoisoned(folio);
3493
3494 /*
3495 * split to new_order one order at a time. For uniform split,
3496 * folio is split to new_order directly.
3497 */
3498 for (split_order = start_order;
3499 split_order >= new_order && !stop_split;
3500 split_order--) {
3501 int old_order = folio_order(folio);
3502 struct folio *release;
3503 struct folio *end_folio = folio_next(folio);
3504 int status;
3505
3506 /* order-1 anonymous folio is not supported */
3507 if (folio_test_anon(folio) && split_order == 1)
3508 continue;
3509 if (uniform_split && split_order != new_order)
3510 continue;
3511
3512 if (mapping) {
^^^^^^^
Here we assume mapping can be NULL.
3513 /*
3514 * uniform split has xas_split_alloc() called before
3515 * irq is disabled, since xas_nomem() might not be
3516 * able to allocate enough memory.
3517 */
3518 if (uniform_split)
3519 xas_split(xas, folio, old_order);
3520 else {
3521 xas_set_order(xas, folio->index, split_order);
3522 xas_split_alloc(xas, folio, folio_order(folio),
3523 GFP_NOWAIT);
3524 if (xas_error(xas)) {
3525 ret = xas_error(xas);
3526 stop_split = true;
3527 goto after_split;
3528 }
3529 xas_split(xas, folio, old_order);
3530 }
3531 }
3532
3533 /* complete memcg works before add pages to LRU */
3534 split_page_memcg(&folio->page, old_order, split_order);
3535 split_page_owner(&folio->page, old_order, split_order);
3536 pgalloc_tag_split(folio, old_order, split_order);
3537
3538 status = __split_folio_to_order(folio, split_order);
3539
3540 if (status < 0) {
3541 stop_split = true;
3542 ret = -EINVAL;
3543 }
3544
3545 after_split:
3546 /*
3547 * Iterate through after-split folios and perform related
3548 * operations. But in buddy allocator like split, the folio
3549 * containing the specified page is skipped until its order
3550 * is new_order, since the folio will be worked on in next
3551 * iteration.
3552 */
3553 for (release = folio, next = folio_next(folio);
3554 release != end_folio;
3555 release = next, next = folio_next(next)) {
3556 /*
3557 * for buddy allocator like split, the folio containing
3558 * page will be split next and should not be released,
3559 * until the folio's order is new_order or stop_split
3560 * is set to true by the above xas_split() failure.
3561 */
3562 if (release == page_folio(page)) {
3563 folio = release;
3564 if (split_order != new_order && !stop_split)
3565 continue;
3566 }
3567 if (folio_test_anon(release)) {
3568 mod_mthp_stat(folio_order(release),
3569 MTHP_STAT_NR_ANON, 1);
3570 }
3571
3572 /*
3573 * Unfreeze refcount first. Additional reference from
3574 * page cache.
3575 */
3576 folio_ref_unfreeze(release,
3577 1 + ((!folio_test_anon(origin_folio) ||
3578 folio_test_swapcache(origin_folio)) ?
3579 folio_nr_pages(release) : 0));
3580
3581 if (release != origin_folio)
3582 lru_add_page_tail(origin_folio, &release->page,
3583 lruvec, list);
3584
3585 /* Some pages can be beyond EOF: drop them from page cache */
3586 if (release->index >= end) {
3587 if (shmem_mapping(origin_folio->mapping))
3588 nr_dropped += folio_nr_pages(release);
3589 else if (folio_test_clear_dirty(release))
3590 folio_account_cleaned(release,
3591 inode_to_wb(origin_folio->mapping->host));
3592 __filemap_remove_folio(release, NULL);
3593 folio_put(release);
3594 } else if (!folio_test_anon(release)) {
3595 __xa_store(&origin_folio->mapping->i_pages,
3596 release->index, &release->page, 0);
3597 } else if (swap_cache) {
3598 __xa_store(&swap_cache->i_pages,
3599 swap_cache_index(release->swap),
3600 &release->page, 0);
3601 }
3602 }
3603 }
3604
3605 unlock_page_lruvec(lruvec);
3606
3607 if (folio_test_anon(origin_folio)) {
3608 if (folio_test_swapcache(origin_folio))
3609 xa_unlock(&swap_cache->i_pages);
3610 } else
--> 3611 xa_unlock(&mapping->i_pages);
Dereferenced without checking.
3612
3613 /* Caller disabled irqs, so they are still disabled here */
3614 local_irq_enable();
3615
3616 if (nr_dropped)
3617 shmem_uncharge(mapping->host, nr_dropped);
^^^^^^^^^^^^^
Here too.
3618
3619 remap_page(origin_folio, 1 << order,
3620 folio_test_anon(origin_folio) ?
3621 RMP_USE_SHARED_ZEROPAGE : 0);
regards,
dan carpenter
next reply other threads:[~2025-02-12 15:13 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-12 15:13 Dan Carpenter [this message]
2025-02-12 15:30 ` Zi Yan
2025-02-12 15:32 ` Dan Carpenter
2025-02-12 15:41 ` Zi Yan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2afe3d59-aca5-40f7-82a3-a6d976fb0f4f@stanley.mountain \
--to=dan.carpenter@linaro.org \
--cc=linux-mm@kvack.org \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox