mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
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: 9e0e252a04 ("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>
This commit is contained in:
parent
7e5102dd99
commit
d301f164c3
|
|
@ -836,7 +836,7 @@ static bool try_adjacent_combine(struct badblocks *bb, int prev)
|
|||
}
|
||||
|
||||
/* Do exact work to set bad block range into the bad block table */
|
||||
static bool _badblocks_set(struct badblocks *bb, sector_t s, int sectors,
|
||||
static bool _badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors,
|
||||
int acknowledged)
|
||||
{
|
||||
int len = 0, added = 0;
|
||||
|
|
@ -956,8 +956,6 @@ static bool _badblocks_set(struct badblocks *bb, sector_t s, int sectors,
|
|||
if (sectors > 0)
|
||||
goto re_insert;
|
||||
|
||||
WARN_ON(sectors < 0);
|
||||
|
||||
/*
|
||||
* Check whether the following already set range can be
|
||||
* merged. (prev < 0) condition is not handled here,
|
||||
|
|
@ -1048,7 +1046,7 @@ static int front_splitting_clear(struct badblocks *bb, int prev,
|
|||
}
|
||||
|
||||
/* Do the exact work to clear bad block range from the bad block table */
|
||||
static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
|
||||
static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors)
|
||||
{
|
||||
struct badblocks_context bad;
|
||||
int prev = -1, hint = -1;
|
||||
|
|
@ -1171,8 +1169,6 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
|
|||
if (sectors > 0)
|
||||
goto re_clear;
|
||||
|
||||
WARN_ON(sectors < 0);
|
||||
|
||||
if (cleared) {
|
||||
badblocks_update_acked(bb);
|
||||
set_changed(bb);
|
||||
|
|
@ -1187,8 +1183,8 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
|
|||
}
|
||||
|
||||
/* Do the exact work to check bad blocks range from the bad block table */
|
||||
static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
|
||||
sector_t *first_bad, int *bad_sectors)
|
||||
static int _badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors,
|
||||
sector_t *first_bad, sector_t *bad_sectors)
|
||||
{
|
||||
int prev = -1, hint = -1, set = 0;
|
||||
struct badblocks_context bad;
|
||||
|
|
@ -1298,8 +1294,8 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
|
|||
* -1: there are bad blocks which have not yet been acknowledged in metadata.
|
||||
* plus the start/length of the first bad section we overlap.
|
||||
*/
|
||||
int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
|
||||
sector_t *first_bad, int *bad_sectors)
|
||||
int badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors,
|
||||
sector_t *first_bad, sector_t *bad_sectors)
|
||||
{
|
||||
unsigned int seq;
|
||||
int rv;
|
||||
|
|
@ -1341,7 +1337,7 @@ EXPORT_SYMBOL_GPL(badblocks_check);
|
|||
* false: failed to set badblocks (out of space). Parital setting will be
|
||||
* treated as failure.
|
||||
*/
|
||||
bool badblocks_set(struct badblocks *bb, sector_t s, int sectors,
|
||||
bool badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors,
|
||||
int acknowledged)
|
||||
{
|
||||
return _badblocks_set(bb, s, sectors, acknowledged);
|
||||
|
|
@ -1362,7 +1358,7 @@ EXPORT_SYMBOL_GPL(badblocks_set);
|
|||
* true: success
|
||||
* false: failed to clear badblocks
|
||||
*/
|
||||
bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
|
||||
bool badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors)
|
||||
{
|
||||
return _badblocks_clear(bb, s, sectors);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1339,8 +1339,7 @@ blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector,
|
|||
struct badblocks *bb = &cmd->nq->dev->badblocks;
|
||||
struct nullb_device *dev = cmd->nq->dev;
|
||||
unsigned int block_sectors = dev->blocksize >> SECTOR_SHIFT;
|
||||
sector_t first_bad;
|
||||
int bad_sectors;
|
||||
sector_t first_bad, bad_sectors;
|
||||
unsigned int partial_io_sectors = 0;
|
||||
|
||||
if (!badblocks_check(bb, sector, *nr_sectors, &first_bad, &bad_sectors))
|
||||
|
|
|
|||
|
|
@ -266,8 +266,8 @@ enum flag_bits {
|
|||
Nonrot, /* non-rotational device (SSD) */
|
||||
};
|
||||
|
||||
static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
|
||||
sector_t *first_bad, int *bad_sectors)
|
||||
static inline int is_badblock(struct md_rdev *rdev, sector_t s, sector_t sectors,
|
||||
sector_t *first_bad, sector_t *bad_sectors)
|
||||
{
|
||||
if (unlikely(rdev->badblocks.count)) {
|
||||
int rv = badblocks_check(&rdev->badblocks, rdev->data_offset + s,
|
||||
|
|
@ -284,7 +284,7 @@ static inline int rdev_has_badblock(struct md_rdev *rdev, sector_t s,
|
|||
int sectors)
|
||||
{
|
||||
sector_t first_bad;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
|
||||
return is_badblock(rdev, s, sectors, &first_bad, &bad_sectors);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ static inline int raid1_check_read_range(struct md_rdev *rdev,
|
|||
sector_t this_sector, int *len)
|
||||
{
|
||||
sector_t first_bad;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
|
||||
/* no bad block overlap */
|
||||
if (!is_badblock(rdev, this_sector, *len, &first_bad, &bad_sectors))
|
||||
|
|
|
|||
|
|
@ -1537,7 +1537,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
|
|||
atomic_inc(&rdev->nr_pending);
|
||||
if (test_bit(WriteErrorSeen, &rdev->flags)) {
|
||||
sector_t first_bad;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
int is_bad;
|
||||
|
||||
is_bad = is_badblock(rdev, r1_bio->sector, max_sectors,
|
||||
|
|
@ -2886,7 +2886,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
} else {
|
||||
/* may need to read from here */
|
||||
sector_t first_bad = MaxSector;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
|
||||
if (is_badblock(rdev, sector_nr, good_sectors,
|
||||
&first_bad, &bad_sectors)) {
|
||||
|
|
|
|||
|
|
@ -747,7 +747,7 @@ static struct md_rdev *read_balance(struct r10conf *conf,
|
|||
|
||||
for (slot = 0; slot < conf->copies ; slot++) {
|
||||
sector_t first_bad;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
sector_t dev_sector;
|
||||
unsigned int pending;
|
||||
bool nonrot;
|
||||
|
|
@ -1438,7 +1438,7 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
|
|||
if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
|
||||
sector_t first_bad;
|
||||
sector_t dev_sector = r10_bio->devs[i].addr;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
int is_bad;
|
||||
|
||||
is_bad = is_badblock(rdev, dev_sector, max_sectors,
|
||||
|
|
@ -3413,7 +3413,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
sector_t from_addr, to_addr;
|
||||
struct md_rdev *rdev = conf->mirrors[d].rdev;
|
||||
sector_t sector, first_bad;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
if (!rdev ||
|
||||
!test_bit(In_sync, &rdev->flags))
|
||||
continue;
|
||||
|
|
@ -3609,7 +3609,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
|||
for (i = 0; i < conf->copies; i++) {
|
||||
int d = r10_bio->devs[i].devnum;
|
||||
sector_t first_bad, sector;
|
||||
int bad_sectors;
|
||||
sector_t bad_sectors;
|
||||
struct md_rdev *rdev;
|
||||
|
||||
if (r10_bio->devs[i].repl_bio)
|
||||
|
|
|
|||
|
|
@ -673,7 +673,7 @@ static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector,
|
|||
{
|
||||
if (bb->count) {
|
||||
sector_t first_bad;
|
||||
int num_bad;
|
||||
sector_t num_bad;
|
||||
|
||||
return !!badblocks_check(bb, sector, len / 512, &first_bad,
|
||||
&num_bad);
|
||||
|
|
|
|||
|
|
@ -367,9 +367,10 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
|
|||
struct nd_namespace_common *ndns = nd_pfn->ndns;
|
||||
void *zero_page = page_address(ZERO_PAGE(0));
|
||||
struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
|
||||
int num_bad, meta_num, rc, bb_present;
|
||||
int meta_num, rc, bb_present;
|
||||
sector_t first_bad, meta_start;
|
||||
struct nd_namespace_io *nsio;
|
||||
sector_t num_bad;
|
||||
|
||||
if (nd_pfn->mode != PFN_MODE_PMEM)
|
||||
return 0;
|
||||
|
|
@ -394,7 +395,7 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
|
|||
bb_present = badblocks_check(&nd_region->bb, meta_start,
|
||||
meta_num, &first_bad, &num_bad);
|
||||
if (bb_present) {
|
||||
dev_dbg(&nd_pfn->dev, "meta: %x badblocks at %llx\n",
|
||||
dev_dbg(&nd_pfn->dev, "meta: %llx badblocks at %llx\n",
|
||||
num_bad, first_bad);
|
||||
nsoff = ALIGN_DOWN((nd_region->ndr_start
|
||||
+ (first_bad << 9)) - nsio->res.start,
|
||||
|
|
@ -413,7 +414,7 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
|
|||
}
|
||||
if (rc) {
|
||||
dev_err(&nd_pfn->dev,
|
||||
"error clearing %x badblocks at %llx\n",
|
||||
"error clearing %llx badblocks at %llx\n",
|
||||
num_bad, first_bad);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
|
|||
unsigned int num = PFN_PHYS(nr_pages) >> SECTOR_SHIFT;
|
||||
struct badblocks *bb = &pmem->bb;
|
||||
sector_t first_bad;
|
||||
int num_bad;
|
||||
sector_t num_bad;
|
||||
|
||||
if (kaddr)
|
||||
*kaddr = pmem->virt_addr + offset;
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ struct badblocks_context {
|
|||
int ack;
|
||||
};
|
||||
|
||||
int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
|
||||
sector_t *first_bad, int *bad_sectors);
|
||||
bool badblocks_set(struct badblocks *bb, sector_t s, int sectors,
|
||||
int badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors,
|
||||
sector_t *first_bad, sector_t *bad_sectors);
|
||||
bool badblocks_set(struct badblocks *bb, sector_t s, sector_t sectors,
|
||||
int acknowledged);
|
||||
bool badblocks_clear(struct badblocks *bb, sector_t s, int sectors);
|
||||
bool badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors);
|
||||
void ack_all_badblocks(struct badblocks *bb);
|
||||
ssize_t badblocks_show(struct badblocks *bb, char *page, int unack);
|
||||
ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user