continue;
 
                entry = radix_to_swp_entry(folio);
+               /*
+                * swapin error entries can be found in the mapping. But they're
+                * deliberately ignored here as we've done everything we can do.
+                */
                if (swp_type(entry) != type)
                        continue;
 
        return error;
 }
 
+static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index,
+                                        struct folio *folio, swp_entry_t swap)
+{
+       struct address_space *mapping = inode->i_mapping;
+       struct shmem_inode_info *info = SHMEM_I(inode);
+       swp_entry_t swapin_error;
+       void *old;
+
+       swapin_error = make_swapin_error_entry(&folio->page);
+       old = xa_cmpxchg_irq(&mapping->i_pages, index,
+                            swp_to_radix_entry(swap),
+                            swp_to_radix_entry(swapin_error), 0);
+       if (old != swp_to_radix_entry(swap))
+               return;
+
+       folio_wait_writeback(folio);
+       delete_from_swap_cache(&folio->page);
+       spin_lock_irq(&info->lock);
+       /*
+        * Don't treat swapin error folio as alloced. Otherwise inode->i_blocks won't
+        * be 0 when inode is released and thus trigger WARN_ON(inode->i_blocks) in
+        * shmem_evict_inode.
+        */
+       info->alloced--;
+       info->swapped--;
+       shmem_recalc_inode(inode);
+       spin_unlock_irq(&info->lock);
+       swap_free(swap);
+}
+
 /*
  * Swap in the page pointed to by *pagep.
  * Caller has to make sure that *pagep contains a valid swapped page.
        swap = radix_to_swp_entry(*foliop);
        *foliop = NULL;
 
+       if (is_swapin_error_entry(swap))
+               return -EIO;
+
        /* Look it up and read it in.. */
        page = lookup_swap_cache(swap, NULL, 0);
        if (!page) {
 failed:
        if (!shmem_confirm_swap(mapping, index, swap))
                error = -EEXIST;
+       if (error == -EIO)
+               shmem_set_folio_swapin_error(inode, index, folio, swap);
 unlock:
        if (folio) {
                folio_unlock(folio);