[bug report] mm/huge_memory: add two new (not yet used) functions for folio_split()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux