All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <error27@gmail.com>
To: Namjae Jeon <linkinjeon@kernel.org>
Cc: linux-fsdevel@vger.kernel.org
Subject: [bug report] ntfs: update runlist handling and cluster allocator
Date: Tue, 28 Apr 2026 09:43:25 +0300	[thread overview]
Message-ID: <afBXDaMfpS1mao5_@stanley.mountain> (raw)

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

             reply	other threads:[~2026-04-28  6:43 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28  6:43 Dan Carpenter [this message]
2026-04-28 12:53 ` [bug report] ntfs: update runlist handling and cluster allocator Namjae Jeon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afBXDaMfpS1mao5_@stanley.mountain \
    --to=error27@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.