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
next 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.