On 1/15/25 1:29 PM, Shin'ichiro Kawasaki wrote: > The current null_blk implementation checks if any bad blocks exist in > the target blocks of each IO. If so, the IO fails and data is not > transferred for all of the IO target blocks. However, when real storage > devices have bad blocks, the devices may transfer data partially up to > the first bad blocks (e.g., SAS drives). Especially, when the IO is a > write operation, such partial IO leaves partially written data on the > device. > > To simulate such partial IO using null_blk, introduce the new parameter > 'badblocks_partial_io'. When this parameter is set, > null_handle_badblocks() returns the number of the sectors for the > partial IO as its third pointer argument. Pass the returned number of > sectors to the following calls to null_handle_memory_backend() in > null_process_cmd() and null_zone_write(). > > Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx> A couple of nits below. Otherwise looks OK to me. Reviewed-by: Damien Le Moal <dlemoal@xxxxxxxxxx> > +/* > + * Check if the command should fail for the badblocks. If so, return > + * BLK_STS_IOERR and return number of partial I/O sectors. ...and return the number of sectors that were read or written, which may be less than the requested number of sectors. > + * > + * @cmd: The command to handle. > + * @sector: The start sector for I/O. > + * @nr_sectors: The caller specifies number of sectors to write or read. > + * Returns number of sectors to be written or read for partial I/O. @nr_sectors: Specifies number of sectors to read or write and returns the number of sectors that were read or written. > + */ > blk_status_t null_handle_badblocks(struct nullb_cmd *cmd, sector_t sector, > - sector_t nr_sectors) > + unsigned int *nr_sectors) > { > 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; > + unsigned int partial_io_sectors = 0; > > - if (!badblocks_check(bb, sector, nr_sectors, &first_bad, &bad_sectors)) > + if (!badblocks_check(bb, sector, *nr_sectors, &first_bad, &bad_sectors)) > return BLK_STS_OK; > > if (cmd->nq->dev->badblocks_once) > badblocks_clear(bb, first_bad, bad_sectors); > > + if (cmd->nq->dev->badblocks_partial_io) { > + if (!IS_ALIGNED(first_bad, block_sectors)) > + first_bad = ALIGN_DOWN(first_bad, block_sectors); > + if (sector < first_bad) > + partial_io_sectors = first_bad - sector; > + } > + *nr_sectors = partial_io_sectors; > + > return BLK_STS_IOERR; > } -- Damien Le Moal Western Digital Research