All of lore.kernel.org
 help / color / mirror / Atom feed
* [bug report] mm/migrate_device: handle partially mapped folios during collection
@ 2025-09-15  5:50 Dan Carpenter
  0 siblings, 0 replies; only message in thread
From: Dan Carpenter @ 2025-09-15  5:50 UTC (permalink / raw)
  To: Balbir Singh; +Cc: linux-mm

Hello Balbir Singh,

Commit a7e62d34c9bf ("mm/migrate_device: handle partially mapped
folios during collection") from Sep 8, 2025 (linux-next), leads to
the following Smatch static checker warning:

	mm/migrate_device.c:352 migrate_vma_collect_pmd()
	error: we previously assumed 'page' could be null (see line 344)

mm/migrate_device.c
    244 static int migrate_vma_collect_pmd(pmd_t *pmdp,
    245                                    unsigned long start,
    246                                    unsigned long end,
    247                                    struct mm_walk *walk)
    248 {
    249         lazy_mmu_state_t lazy_mmu_state;
    250         struct migrate_vma *migrate = walk->private;
    251         struct vm_area_struct *vma = walk->vma;
    252         struct mm_struct *mm = vma->vm_mm;
    253         unsigned long addr = start, unmapped = 0;
    254         spinlock_t *ptl;
    255         struct folio *fault_folio = migrate->fault_page ?
    256                 page_folio(migrate->fault_page) : NULL;
    257         pte_t *ptep;
    258 
    259 again:
    260         if (pmd_trans_huge(*pmdp) || !pmd_present(*pmdp)) {
    261                 int ret = migrate_vma_collect_huge_pmd(pmdp, start, end, walk, fault_folio);
    262 
    263                 if (ret == -EAGAIN)
    264                         goto again;
    265                 if (ret == 0)
    266                         return 0;
    267         }
    268 
    269         ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
    270         if (!ptep)
    271                 goto again;
    272         lazy_mmu_state = arch_enter_lazy_mmu_mode();
    273 
    274         for (; addr < end; addr += PAGE_SIZE, ptep++) {
    275                 struct dev_pagemap *pgmap;
    276                 unsigned long mpfn = 0, pfn;
    277                 struct folio *folio;
    278                 struct page *page;
    279                 swp_entry_t entry;
    280                 pte_t pte;
    281 
    282                 pte = ptep_get(ptep);
    283 
    284                 if (pte_none(pte)) {
    285                         if (vma_is_anonymous(vma)) {
    286                                 mpfn = MIGRATE_PFN_MIGRATE;
    287                                 migrate->cpages++;
    288                         }
    289                         goto next;
    290                 }
    291 
    292                 if (!pte_present(pte)) {
    293                         /*
    294                          * Only care about unaddressable device page special
    295                          * page table entry. Other special swap entries are not
    296                          * migratable, and we ignore regular swapped page.
    297                          */
    298                         struct folio *folio;
    299 
    300                         entry = pte_to_swp_entry(pte);
    301                         if (!is_device_private_entry(entry))
    302                                 goto next;
    303 
    304                         page = pfn_swap_entry_to_page(entry);
    305                         pgmap = page_pgmap(page);
    306                         if (!(migrate->flags &
    307                                 MIGRATE_VMA_SELECT_DEVICE_PRIVATE) ||
    308                             pgmap->owner != migrate->pgmap_owner)
    309                                 goto next;
    310 
    311                         folio = page_folio(page);
    312                         if (folio_test_large(folio)) {
    313                                 int ret;
    314 
    315                                 pte_unmap_unlock(ptep, ptl);
    316                                 ret = migrate_vma_split_folio(folio,
    317                                                           migrate->fault_page);
    318 
    319                                 if (ret) {
    320                                         ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
    321                                         goto next;
    322                                 }
    323 
    324                                 addr = start;
    325                                 goto again;
    326                         }
    327 
    328                         mpfn = migrate_pfn(page_to_pfn(page)) |
    329                                         MIGRATE_PFN_MIGRATE;
    330                         if (is_writable_device_private_entry(entry))
    331                                 mpfn |= MIGRATE_PFN_WRITE;
    332                 } else {
    333                         pfn = pte_pfn(pte);
    334                         if (is_zero_pfn(pfn) &&
    335                             (migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) {
    336                                 mpfn = MIGRATE_PFN_MIGRATE;
    337                                 migrate->cpages++;
    338                                 goto next;
    339                         }
    340                         page = vm_normal_page(migrate->vma, addr, pte);
    341                         if (page && !is_zone_device_page(page) &&
                                    ^^^^

    342                             !(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) {
    343                                 goto next;
    344                         } else if (page && is_device_coherent_page(page)) {
                                           ^^^^
This code assume page can be NULL

    345                                 pgmap = page_pgmap(page);
    346 
    347                                 if (!(migrate->flags &
    348                                         MIGRATE_VMA_SELECT_DEVICE_COHERENT) ||
    349                                         pgmap->owner != migrate->pgmap_owner)
    350                                         goto next;
    351                         }
--> 352                         folio = page_folio(page);
                                                   ^^^^
Unchecked dereference

    353                         if (folio_test_large(folio)) {
    354                                 int ret;
    355 
    356                                 pte_unmap_unlock(ptep, ptl);
    357                                 ret = migrate_vma_split_folio(folio,
    358                                                           migrate->fault_page);
    359 
    360                                 if (ret) {
    361                                         ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
    362                                         goto next;

regards,
dan carpenter


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-09-15  5:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-15  5:50 [bug report] mm/migrate_device: handle partially mapped folios during collection Dan Carpenter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.