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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel