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: use sector_t instead of int to avoid truncation of badblocks length

There is a truncation of badblocks length issue when set badblocks as
follow:

echo "2055 4294967299" > bad_blocks
cat bad_blocks
2055 3

Change 'sectors' argument type from 'int' to 'sector_t'.

This change avoids truncation of badblocks length for large sectors by
replacing 'int' with 'sector_t' (u64), enabling proper handling of larger
disk sizes and ensuring compatibility with 64-bit sector addressing.

Fixes: 9e0e252a048b ("badblocks: Add core badblock management code")
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-13-zhengqixing@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Zheng Qixing and committed by
Jens Axboe
d301f164 7e5102dd

+29 -33
+8 -12
block/badblocks.c
··· 836 836 } 837 837 838 838 /* Do exact work to set bad block range into the bad block table */ 839 - static bool _badblocks_set(struct badblocks *bb, sector_t s, int sectors, 839 + static bool _badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors, 840 840 int acknowledged) 841 841 { 842 842 int len = 0, added = 0; ··· 956 956 if (sectors > 0) 957 957 goto re_insert; 958 958 959 - WARN_ON(sectors < 0); 960 - 961 959 /* 962 960 * Check whether the following already set range can be 963 961 * merged. (prev < 0) condition is not handled here, ··· 1046 1048 } 1047 1049 1048 1050 /* Do the exact work to clear bad block range from the bad block table */ 1049 - static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) 1051 + static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors) 1050 1052 { 1051 1053 struct badblocks_context bad; 1052 1054 int prev = -1, hint = -1; ··· 1169 1171 if (sectors > 0) 1170 1172 goto re_clear; 1171 1173 1172 - WARN_ON(sectors < 0); 1173 - 1174 1174 if (cleared) { 1175 1175 badblocks_update_acked(bb); 1176 1176 set_changed(bb); ··· 1183 1187 } 1184 1188 1185 1189 /* Do the exact work to check bad blocks range from the bad block table */ 1186 - static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, 1187 - sector_t *first_bad, int *bad_sectors) 1190 + static int _badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, 1191 + sector_t *first_bad, sector_t *bad_sectors) 1188 1192 { 1189 1193 int prev = -1, hint = -1, set = 0; 1190 1194 struct badblocks_context bad; ··· 1294 1298 * -1: there are bad blocks which have not yet been acknowledged in metadata. 1295 1299 * plus the start/length of the first bad section we overlap. 1296 1300 */ 1297 - int badblocks_check(struct badblocks *bb, sector_t s, int sectors, 1298 - sector_t *first_bad, int *bad_sectors) 1301 + int badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, 1302 + sector_t *first_bad, sector_t *bad_sectors) 1299 1303 { 1300 1304 unsigned int seq; 1301 1305 int rv; ··· 1337 1341 * false: failed to set badblocks (out of space). Parital setting will be 1338 1342 * treated as failure. 1339 1343 */ 1340 - bool badblocks_set(struct badblocks *bb, sector_t s, int sectors, 1344 + bool badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors, 1341 1345 int acknowledged) 1342 1346 { 1343 1347 return _badblocks_set(bb, s, sectors, acknowledged); ··· 1358 1362 * true: success 1359 1363 * false: failed to clear badblocks 1360 1364 */ 1361 - bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors) 1365 + bool badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors) 1362 1366 { 1363 1367 return _badblocks_clear(bb, s, sectors); 1364 1368 }
+1 -2
drivers/block/null_blk/main.c
··· 1339 1339 struct badblocks *bb = &cmd->nq->dev->badblocks; 1340 1340 struct nullb_device *dev = cmd->nq->dev; 1341 1341 unsigned int block_sectors = dev->blocksize >> SECTOR_SHIFT; 1342 - sector_t first_bad; 1343 - int bad_sectors; 1342 + sector_t first_bad, bad_sectors; 1344 1343 unsigned int partial_io_sectors = 0; 1345 1344 1346 1345 if (!badblocks_check(bb, sector, *nr_sectors, &first_bad, &bad_sectors))
+3 -3
drivers/md/md.h
··· 266 266 Nonrot, /* non-rotational device (SSD) */ 267 267 }; 268 268 269 - static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors, 270 - sector_t *first_bad, int *bad_sectors) 269 + static inline int is_badblock(struct md_rdev *rdev, sector_t s, sector_t sectors, 270 + sector_t *first_bad, sector_t *bad_sectors) 271 271 { 272 272 if (unlikely(rdev->badblocks.count)) { 273 273 int rv = badblocks_check(&rdev->badblocks, rdev->data_offset + s, ··· 284 284 int sectors) 285 285 { 286 286 sector_t first_bad; 287 - int bad_sectors; 287 + sector_t bad_sectors; 288 288 289 289 return is_badblock(rdev, s, sectors, &first_bad, &bad_sectors); 290 290 }
+1 -1
drivers/md/raid1-10.c
··· 247 247 sector_t this_sector, int *len) 248 248 { 249 249 sector_t first_bad; 250 - int bad_sectors; 250 + sector_t bad_sectors; 251 251 252 252 /* no bad block overlap */ 253 253 if (!is_badblock(rdev, this_sector, *len, &first_bad, &bad_sectors))
+2 -2
drivers/md/raid1.c
··· 1537 1537 atomic_inc(&rdev->nr_pending); 1538 1538 if (test_bit(WriteErrorSeen, &rdev->flags)) { 1539 1539 sector_t first_bad; 1540 - int bad_sectors; 1540 + sector_t bad_sectors; 1541 1541 int is_bad; 1542 1542 1543 1543 is_bad = is_badblock(rdev, r1_bio->sector, max_sectors, ··· 2886 2886 } else { 2887 2887 /* may need to read from here */ 2888 2888 sector_t first_bad = MaxSector; 2889 - int bad_sectors; 2889 + sector_t bad_sectors; 2890 2890 2891 2891 if (is_badblock(rdev, sector_nr, good_sectors, 2892 2892 &first_bad, &bad_sectors)) {
+4 -4
drivers/md/raid10.c
··· 747 747 748 748 for (slot = 0; slot < conf->copies ; slot++) { 749 749 sector_t first_bad; 750 - int bad_sectors; 750 + sector_t bad_sectors; 751 751 sector_t dev_sector; 752 752 unsigned int pending; 753 753 bool nonrot; ··· 1438 1438 if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { 1439 1439 sector_t first_bad; 1440 1440 sector_t dev_sector = r10_bio->devs[i].addr; 1441 - int bad_sectors; 1441 + sector_t bad_sectors; 1442 1442 int is_bad; 1443 1443 1444 1444 is_bad = is_badblock(rdev, dev_sector, max_sectors, ··· 3413 3413 sector_t from_addr, to_addr; 3414 3414 struct md_rdev *rdev = conf->mirrors[d].rdev; 3415 3415 sector_t sector, first_bad; 3416 - int bad_sectors; 3416 + sector_t bad_sectors; 3417 3417 if (!rdev || 3418 3418 !test_bit(In_sync, &rdev->flags)) 3419 3419 continue; ··· 3609 3609 for (i = 0; i < conf->copies; i++) { 3610 3610 int d = r10_bio->devs[i].devnum; 3611 3611 sector_t first_bad, sector; 3612 - int bad_sectors; 3612 + sector_t bad_sectors; 3613 3613 struct md_rdev *rdev; 3614 3614 3615 3615 if (r10_bio->devs[i].repl_bio)
+1 -1
drivers/nvdimm/nd.h
··· 673 673 { 674 674 if (bb->count) { 675 675 sector_t first_bad; 676 - int num_bad; 676 + sector_t num_bad; 677 677 678 678 return !!badblocks_check(bb, sector, len / 512, &first_bad, 679 679 &num_bad);
+4 -3
drivers/nvdimm/pfn_devs.c
··· 367 367 struct nd_namespace_common *ndns = nd_pfn->ndns; 368 368 void *zero_page = page_address(ZERO_PAGE(0)); 369 369 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; 370 - int num_bad, meta_num, rc, bb_present; 370 + int meta_num, rc, bb_present; 371 371 sector_t first_bad, meta_start; 372 372 struct nd_namespace_io *nsio; 373 + sector_t num_bad; 373 374 374 375 if (nd_pfn->mode != PFN_MODE_PMEM) 375 376 return 0; ··· 395 394 bb_present = badblocks_check(&nd_region->bb, meta_start, 396 395 meta_num, &first_bad, &num_bad); 397 396 if (bb_present) { 398 - dev_dbg(&nd_pfn->dev, "meta: %x badblocks at %llx\n", 397 + dev_dbg(&nd_pfn->dev, "meta: %llx badblocks at %llx\n", 399 398 num_bad, first_bad); 400 399 nsoff = ALIGN_DOWN((nd_region->ndr_start 401 400 + (first_bad << 9)) - nsio->res.start, ··· 414 413 } 415 414 if (rc) { 416 415 dev_err(&nd_pfn->dev, 417 - "error clearing %x badblocks at %llx\n", 416 + "error clearing %llx badblocks at %llx\n", 418 417 num_bad, first_bad); 419 418 return rc; 420 419 }
+1 -1
drivers/nvdimm/pmem.c
··· 249 249 unsigned int num = PFN_PHYS(nr_pages) >> SECTOR_SHIFT; 250 250 struct badblocks *bb = &pmem->bb; 251 251 sector_t first_bad; 252 - int num_bad; 252 + sector_t num_bad; 253 253 254 254 if (kaddr) 255 255 *kaddr = pmem->virt_addr + offset;
+4 -4
include/linux/badblocks.h
··· 48 48 int ack; 49 49 }; 50 50 51 - int badblocks_check(struct badblocks *bb, sector_t s, int sectors, 52 - sector_t *first_bad, int *bad_sectors); 53 - bool badblocks_set(struct badblocks *bb, sector_t s, int sectors, 51 + int badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, 52 + sector_t *first_bad, sector_t *bad_sectors); 53 + bool badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors, 54 54 int acknowledged); 55 - bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors); 55 + bool badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors); 56 56 void ack_all_badblocks(struct badblocks *bb); 57 57 ssize_t badblocks_show(struct badblocks *bb, char *page, int unack); 58 58 ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len,