Linux filesystem development
 help / color / mirror / Atom feed
* [bug report] ntfs: update runlist handling and cluster allocator
@ 2026-04-28  6:43 Dan Carpenter
  2026-04-28 12:53 ` Namjae Jeon
  0 siblings, 1 reply; 2+ messages in thread
From: Dan Carpenter @ 2026-04-28  6:43 UTC (permalink / raw)
  To: Namjae Jeon; +Cc: linux-fsdevel

Hello Namjae Jeon,

Commit 11ccc9107dc4 ("ntfs: update runlist handling and cluster
allocator") from Feb 13, 2026 (linux-next), leads to the following
Smatch static checker warning:

	fs/ntfs/bitmap.c:268 __ntfs_bitmap_set_bits_in_run()
	warn: passing a valid pointer to 'PTR_ERR'

fs/ntfs/bitmap.c
    120 int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
    121                 const s64 count, const u8 value, const bool is_rollback)
    122 {
    123         s64 cnt = count;
    124         pgoff_t index, end_index;
    125         struct address_space *mapping;
    126         struct folio *folio;
    127         u8 *kaddr;
    128         int pos, len;
    129         u8 bit;
    130         struct ntfs_inode *ni = NTFS_I(vi);
    131         struct ntfs_volume *vol = ni->vol;
    132 
    133         ntfs_debug("Entering for i_ino 0x%llx, start_bit 0x%llx, count 0x%llx, value %u.%s",
    134                         ni->mft_no, (unsigned long long)start_bit,
    135                         (unsigned long long)cnt, (unsigned int)value,
    136                         is_rollback ? " (rollback)" : "");
    137 
    138         if (start_bit < 0 || cnt < 0 || value > 1)
    139                 return -EINVAL;
    140 
    141         /*
    142          * Calculate the indices for the pages containing the first and last
    143          * bits, i.e. @start_bit and @start_bit + @cnt - 1, respectively.
    144          */
    145         index = start_bit >> (3 + PAGE_SHIFT);
    146         end_index = (start_bit + cnt - 1) >> (3 + PAGE_SHIFT);
    147 
    148         /* Get the page containing the first bit (@start_bit). */
    149         mapping = vi->i_mapping;
    150         folio = read_mapping_folio(mapping, index, NULL);
    151         if (IS_ERR(folio)) {
    152                 if (!is_rollback)
    153                         ntfs_error(vi->i_sb,
    154                                 "Failed to map first page (error %li), aborting.",
    155                                 PTR_ERR(folio));
    156                 return PTR_ERR(folio);
    157         }
    158 
    159         folio_lock(folio);
    160         kaddr = kmap_local_folio(folio, 0);
    161 
    162         /* Set @pos to the position of the byte containing @start_bit. */
    163         pos = (start_bit >> 3) & ~PAGE_MASK;
    164 
    165         /* Calculate the position of @start_bit in the first byte. */
    166         bit = start_bit & 7;
    167 
    168         /* If the first byte is partial, modify the appropriate bits in it. */
    169         if (bit) {
    170                 u8 *byte = kaddr + pos;
    171 
    172                 if (ni->mft_no == FILE_Bitmap)
    173                         ntfs_set_lcn_empty_bits(vol, index, value, min_t(s64, 8 - bit, cnt));
    174                 while ((bit & 7) && cnt) {
    175                         cnt--;
    176                         if (value)
    177                                 *byte |= 1 << bit++;
    178                         else
    179                                 *byte &= ~(1 << bit++);
    180                 }
    181                 /* If we are done, unmap the page and return success. */
    182                 if (!cnt)
    183                         goto done;
    184 
    185                 /* Update @pos to the new position. */
    186                 pos++;
    187         }
    188         /*
    189          * Depending on @value, modify all remaining whole bytes in the page up
    190          * to @cnt.
    191          */
    192         len = min_t(s64, cnt >> 3, PAGE_SIZE - pos);
    193         memset(kaddr + pos, value ? 0xff : 0, len);
    194         cnt -= len << 3;
    195         if (ni->mft_no == FILE_Bitmap)
    196                 ntfs_set_lcn_empty_bits(vol, index, value, len << 3);
    197 
    198         /* Update @len to point to the first not-done byte in the page. */
    199         if (cnt < 8)
    200                 len += pos;
    201 
    202         /* If we are not in the last page, deal with all subsequent pages. */
    203         while (index < end_index) {
    204                 if (cnt <= 0)
    205                         goto rollback;

When we hit this goto then "folio" isn't set to an error pointer.

    206 
    207                 /* Update @index and get the next folio. */
    208                 folio_mark_dirty(folio);
    209                 folio_unlock(folio);
    210                 kunmap_local(kaddr);
    211                 folio_put(folio);
    212                 folio = read_mapping_folio(mapping, ++index, NULL);
    213                 if (IS_ERR(folio)) {
    214                         ntfs_error(vi->i_sb,
    215                                    "Failed to map subsequent page (error %li), aborting.",
    216                                    PTR_ERR(folio));
    217                         goto rollback;
    218                 }
    219 
    220                 folio_lock(folio);
    221                 kaddr = kmap_local_folio(folio, 0);
    222                 /*
    223                  * Depending on @value, modify all remaining whole bytes in the
    224                  * page up to @cnt.
    225                  */
    226                 len = min_t(s64, cnt >> 3, PAGE_SIZE);
    227                 memset(kaddr, value ? 0xff : 0, len);
    228                 cnt -= len << 3;
    229                 if (ni->mft_no == FILE_Bitmap)
    230                         ntfs_set_lcn_empty_bits(vol, index, value, len << 3);
    231         }
    232         /*
    233          * The currently mapped page is the last one.  If the last byte is
    234          * partial, modify the appropriate bits in it.  Note, @len is the
    235          * position of the last byte inside the page.
    236          */
    237         if (cnt) {
    238                 u8 *byte;
    239 
    240                 WARN_ON(cnt > 7);
    241 
    242                 bit = cnt;
    243                 byte = kaddr + len;
    244                 if (ni->mft_no == FILE_Bitmap)
    245                         ntfs_set_lcn_empty_bits(vol, index, value, bit);
    246                 while (bit--) {
    247                         if (value)
    248                                 *byte |= 1 << bit;
    249                         else
    250                                 *byte &= ~(1 << bit);
    251                 }
    252         }
    253 done:
    254         /* We are done.  Unmap the folio and return success. */
    255         folio_mark_dirty(folio);
    256         folio_unlock(folio);
    257         kunmap_local(kaddr);
    258         folio_put(folio);
    259         ntfs_debug("Done.");
    260         return 0;
    261 rollback:
    262         /*
    263          * Current state:
    264          *        - no pages are mapped
    265          *        - @count - @cnt is the number of bits that have been modified
    266          */
    267         if (is_rollback)
--> 268                 return PTR_ERR(folio);
                               ^^^^^^^^^^^^^^^
Warning here.

    269         if (count != cnt)
    270                 pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
    271                                 value ? 0 : 1, true);
    272         else
    273                 pos = 0;
    274         if (!pos) {
    275                 /* Rollback was successful. */
    276                 ntfs_error(vi->i_sb,
    277                         "Failed to map subsequent page (error %li), aborting.",
    278                         PTR_ERR(folio));
    279         } else {
    280                 /* Rollback failed. */
    281                 ntfs_error(vi->i_sb,
    282                         "Failed to map subsequent page (error %li) and rollback failed (error %i). Aborting and leaving inconsistent metadata. Unmount and run chkdsk.",
    283                         PTR_ERR(folio), pos);
    284                 NVolSetErrors(NTFS_SB(vi->i_sb));
    285         }
    286         return PTR_ERR(folio);
    287 }

This email is a free service from the Smatch-CI project [smatch.sf.net].

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [bug report] ntfs: update runlist handling and cluster allocator
  2026-04-28  6:43 [bug report] ntfs: update runlist handling and cluster allocator Dan Carpenter
@ 2026-04-28 12:53 ` Namjae Jeon
  0 siblings, 0 replies; 2+ messages in thread
From: Namjae Jeon @ 2026-04-28 12:53 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: linux-fsdevel

On Tue, Apr 28, 2026 at 3:43 PM Dan Carpenter <error27@gmail.com> wrote:
>
> Hello Namjae Jeon,
Hi Dan,
>
> Commit 11ccc9107dc4 ("ntfs: update runlist handling and cluster
> allocator") from Feb 13, 2026 (linux-next), leads to the following
> Smatch static checker warning:
>
>         fs/ntfs/bitmap.c:268 __ntfs_bitmap_set_bits_in_run()
>         warn: passing a valid pointer to 'PTR_ERR'
I will fix it. Thanks for the report!

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-28 12:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28  6:43 [bug report] ntfs: update runlist handling and cluster allocator Dan Carpenter
2026-04-28 12:53 ` Namjae Jeon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox