Hello Matthew Wilcox (Oracle),

Commit 5d895f7beae9 ("f2fs: Use folios in do_garbage_collect()") from
Mar 31, 2025 (linux-next), leads to the following Smatch static
checker warning:

        fs/f2fs/gc.c:1799 do_garbage_collect()
        error: 'sum_folio' dereferencing possible ERR_PTR()

fs/f2fs/gc.c
    1716 static int do_garbage_collect(struct f2fs_sb_info *sbi,
    1717                                 unsigned int start_segno,
    1718                                 struct gc_inode_list *gc_list, int 
gc_type,
    1719                                 bool force_migrate, bool one_time)
    1720 {
    1721         struct blk_plug plug;
    1722         unsigned int segno = start_segno;
    1723         unsigned int end_segno = start_segno + SEGS_PER_SEC(sbi);
    1724         unsigned int sec_end_segno;
    1725         int seg_freed = 0, migrated = 0;
    1726         unsigned char type = IS_DATASEG(get_seg_entry(sbi, 
segno)->type) ?
    1727                                                 SUM_TYPE_DATA : 
SUM_TYPE_NODE;
    1728         unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : 
NODE;
    1729         int submitted = 0;
    1730 
    1731         if (__is_large_section(sbi)) {
    1732                 sec_end_segno = rounddown(end_segno, 
SEGS_PER_SEC(sbi));
    1733 
    1734                 /*
    1735                  * zone-capacity can be less than zone-size in zoned 
devices,
    1736                  * resulting in less than expected usable segments in 
the zone,
    1737                  * calculate the end segno in the zone which can be 
garbage
    1738                  * collected
    1739                  */
    1740                 if (f2fs_sb_has_blkzoned(sbi))
    1741                         sec_end_segno -= SEGS_PER_SEC(sbi) -
    1742                                         f2fs_usable_segs_in_sec(sbi);
    1743 
    1744                 if (gc_type == BG_GC || one_time) {
    1745                         unsigned int window_granularity =
    1746                                 sbi->migration_window_granularity;
    1747 
    1748                         if (f2fs_sb_has_blkzoned(sbi) &&
    1749                                         !has_enough_free_blocks(sbi,
    1750                                         
sbi->gc_thread->boost_zoned_gc_percent))
    1751                                 window_granularity *=
    1752                                         BOOST_GC_MULTIPLE;
    1753 
    1754                         end_segno = start_segno + window_granularity;
    1755                 }
    1756 
    1757                 if (end_segno > sec_end_segno)
    1758                         end_segno = sec_end_segno;
    1759         }
    1760 
    1761         sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
    1762 
    1763         /* readahead multi ssa blocks those have contiguous address */
    1764         if (__is_large_section(sbi))
    1765                 f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
    1766                                         end_segno - segno, META_SSA, 
true);
    1767 
    1768         /* reference all summary page */
    1769         while (segno < end_segno) {
    1770                 struct folio *sum_folio = f2fs_get_sum_folio(sbi, 
segno++);
    1771                 if (IS_ERR(sum_folio)) {
    1772                         int err = PTR_ERR(sum_folio);
    1773 
    1774                         end_segno = segno - 1;
    1775                         for (segno = start_segno; segno < end_segno; 
segno++) {
    1776                                 sum_folio = 
filemap_get_folio(META_MAPPING(sbi),
    1777                                                 GET_SUM_BLOCK(sbi, 
segno));
    1778                                 folio_put_refs(sum_folio, 2);
    1779                         }
    1780                         return err;
    1781                 }
    1782                 folio_unlock(sum_folio);
    1783         }
    1784 
    1785         blk_start_plug(&plug);
    1786 
    1787         for (segno = start_segno; segno < end_segno; segno++) {
    1788                 struct f2fs_summary_block *sum;
    1789 
    1790                 /* find segment summary of victim */
    1791                 struct folio *sum_folio = 
filemap_get_folio(META_MAPPING(sbi),
    1792                                         GET_SUM_BLOCK(sbi, segno));

Smatch gets a bit confused here and thinks filemap_get_folio() can return
a lot of different error pointers, but really filemap_get_folio() can only
return ERR_PTR(-ENOENT).  And possibly in this context, it can't even
return that?

One time email warning etc.  I could also mark filemap_get_folio() as
a no fail function to prevent false positives.

    1793 
    1794                 if (get_valid_blocks(sbi, segno, false) == 0)
    1795                         goto freed;
    1796                 if (gc_type == BG_GC && __is_large_section(sbi) &&
    1797                                 migrated >= sbi->migration_granularity)
    1798                         goto skip;
--> 1799                 if (!folio_test_uptodate(sum_folio) ||
                                                  ^^^^^^^^^
Dereferenced here.

    1800                     unlikely(f2fs_cp_error(sbi)))
    1801                         goto skip;
    1802 

regards,
dan carpenter


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to