Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

badblocks: fix missing bad blocks on retry in _badblocks_check()

The bad blocks check would miss bad blocks when retrying under contention,
as checking parameters are not reset. These stale values from the previous
attempt could lead to incorrect scanning in the subsequent retry.

Move seqlock to outer function and reinitialize checking state for each
retry. This ensures a clean state for each check attempt, preventing any
missed bad blocks.

Fixes: 3ea3354cb9f0 ("badblocks: improve badblocks_check() for multiple ranges handling")
Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Acked-by: Coly Li <colyli@kernel.org>
Link: https://lore.kernel.org/r/20250227075507.151331-10-zhengqixing@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Zheng Qixing and committed by
Jens Axboe
5236f041 9ec65dec

+24 -26
+24 -26
block/badblocks.c
··· 1191 1191 static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, 1192 1192 sector_t *first_bad, int *bad_sectors) 1193 1193 { 1194 - int unacked_badblocks, acked_badblocks; 1195 1194 int prev = -1, hint = -1, set = 0; 1196 1195 struct badblocks_context bad; 1197 - unsigned int seq; 1196 + int unacked_badblocks = 0; 1197 + int acked_badblocks = 0; 1198 + u64 *p = bb->page; 1198 1199 int len, rv; 1199 - u64 *p; 1200 - 1201 - WARN_ON(bb->shift < 0 || sectors == 0); 1202 - 1203 - if (bb->shift > 0) { 1204 - sector_t target; 1205 - 1206 - /* round the start down, and the end up */ 1207 - target = s + sectors; 1208 - rounddown(s, 1 << bb->shift); 1209 - roundup(target, 1 << bb->shift); 1210 - sectors = target - s; 1211 - } 1212 - 1213 - retry: 1214 - seq = read_seqbegin(&bb->lock); 1215 - 1216 - p = bb->page; 1217 - unacked_badblocks = 0; 1218 - acked_badblocks = 0; 1219 1200 1220 1201 re_check: 1221 1202 bad.start = s; ··· 1262 1281 else 1263 1282 rv = 0; 1264 1283 1265 - if (read_seqretry(&bb->lock, seq)) 1266 - goto retry; 1267 - 1268 1284 return rv; 1269 1285 } 1270 1286 ··· 1302 1324 int badblocks_check(struct badblocks *bb, sector_t s, int sectors, 1303 1325 sector_t *first_bad, int *bad_sectors) 1304 1326 { 1305 - return _badblocks_check(bb, s, sectors, first_bad, bad_sectors); 1327 + unsigned int seq; 1328 + int rv; 1329 + 1330 + WARN_ON(bb->shift < 0 || sectors == 0); 1331 + 1332 + if (bb->shift > 0) { 1333 + /* round the start down, and the end up */ 1334 + sector_t target = s + sectors; 1335 + 1336 + rounddown(s, 1 << bb->shift); 1337 + roundup(target, 1 << bb->shift); 1338 + sectors = target - s; 1339 + } 1340 + 1341 + retry: 1342 + seq = read_seqbegin(&bb->lock); 1343 + rv = _badblocks_check(bb, s, sectors, first_bad, bad_sectors); 1344 + if (read_seqretry(&bb->lock, seq)) 1345 + goto retry; 1346 + 1347 + return rv; 1306 1348 } 1307 1349 EXPORT_SYMBOL_GPL(badblocks_check); 1308 1350