Skip to content

Commit

Permalink
block: consolidate blocksize properties consistency checks
Browse files Browse the repository at this point in the history
Several block device properties related to blocksize configuration must
be in certain relationship WRT each other: physical block must be no
smaller than logical block; min_io_size, opt_io_size, and
discard_granularity must be a multiple of a logical block.

To ensure these requirements are met, add corresponding consistency
checks to blkconf_blocksizes, adjusting its signature to communicate
possible error to the caller.  Also remove the now redundant consistency
checks from the specific devices.

Signed-off-by: Roman Kagan <rvkagan@yandex-team.ru>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paul Durrant <paul@xen.org>
Message-Id: <20200528225516.1676602-3-rvkagan@yandex-team.ru>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
rvka authored and kevmw committed Jun 17, 2020
1 parent 6abee26 commit c56ee92
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 26 deletions.
30 changes: 29 additions & 1 deletion hw/block/block.c
Expand Up @@ -61,7 +61,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
return true;
}

void blkconf_blocksizes(BlockConf *conf)
bool blkconf_blocksizes(BlockConf *conf, Error **errp)
{
BlockBackend *blk = conf->blk;
BlockSizes blocksizes;
Expand All @@ -83,6 +83,34 @@ void blkconf_blocksizes(BlockConf *conf)
conf->logical_block_size = BDRV_SECTOR_SIZE;
}
}

if (conf->logical_block_size > conf->physical_block_size) {
error_setg(errp,
"logical_block_size > physical_block_size not supported");
return false;
}

if (!QEMU_IS_ALIGNED(conf->min_io_size, conf->logical_block_size)) {
error_setg(errp,
"min_io_size must be a multiple of logical_block_size");
return false;
}

if (!QEMU_IS_ALIGNED(conf->opt_io_size, conf->logical_block_size)) {
error_setg(errp,
"opt_io_size must be a multiple of logical_block_size");
return false;
}

if (conf->discard_granularity != -1 &&
!QEMU_IS_ALIGNED(conf->discard_granularity,
conf->logical_block_size)) {
error_setg(errp, "discard_granularity must be "
"a multiple of logical_block_size");
return false;
}

return true;
}

bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
Expand Down
5 changes: 4 additions & 1 deletion hw/block/fdc.c
Expand Up @@ -554,7 +554,10 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
read_only = !blk_bs(dev->conf.blk) || blk_is_read_only(dev->conf.blk);
}

blkconf_blocksizes(&dev->conf);
if (!blkconf_blocksizes(&dev->conf, errp)) {
return;
}

if (dev->conf.logical_block_size != 512 ||
dev->conf.physical_block_size != 512)
{
Expand Down
4 changes: 3 additions & 1 deletion hw/block/nvme.c
Expand Up @@ -1425,7 +1425,9 @@ static void nvme_init_state(NvmeCtrl *n)

static void nvme_init_blk(NvmeCtrl *n, Error **errp)
{
blkconf_blocksizes(&n->conf);
if (!blkconf_blocksizes(&n->conf, errp)) {
return;
}
blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
false, errp);
}
Expand Down
5 changes: 4 additions & 1 deletion hw/block/swim.c
Expand Up @@ -189,7 +189,10 @@ static void swim_drive_realize(DeviceState *qdev, Error **errp)
assert(ret == 0);
}

blkconf_blocksizes(&dev->conf);
if (!blkconf_blocksizes(&dev->conf, errp)) {
return;
}

if (dev->conf.logical_block_size != 512 ||
dev->conf.physical_block_size != 512)
{
Expand Down
7 changes: 1 addition & 6 deletions hw/block/virtio-blk.c
Expand Up @@ -1174,12 +1174,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
return;
}

blkconf_blocksizes(&conf->conf);

if (conf->conf.logical_block_size >
conf->conf.physical_block_size) {
error_setg(errp,
"logical_block_size > physical_block_size not supported");
if (!blkconf_blocksizes(&conf->conf, errp)) {
return;
}

Expand Down
6 changes: 1 addition & 5 deletions hw/block/xen-block.c
Expand Up @@ -239,11 +239,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
return;
}

blkconf_blocksizes(conf);

if (conf->logical_block_size > conf->physical_block_size) {
error_setg(
errp, "logical_block_size > physical_block_size not supported");
if (!blkconf_blocksizes(conf, errp)) {
return;
}

Expand Down
5 changes: 4 additions & 1 deletion hw/ide/qdev.c
Expand Up @@ -187,7 +187,10 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
return;
}

blkconf_blocksizes(&dev->conf);
if (!blkconf_blocksizes(&dev->conf, errp)) {
return;
}

if (dev->conf.logical_block_size != 512) {
error_setg(errp, "logical_block_size must be 512 for IDE");
return;
Expand Down
12 changes: 5 additions & 7 deletions hw/scsi/scsi-disk.c
Expand Up @@ -2346,12 +2346,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
return;
}

blkconf_blocksizes(&s->qdev.conf);

if (s->qdev.conf.logical_block_size >
s->qdev.conf.physical_block_size) {
error_setg(errp,
"logical_block_size > physical_block_size not supported");
if (!blkconf_blocksizes(&s->qdev.conf, errp)) {
return;
}

Expand Down Expand Up @@ -2436,14 +2431,17 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
if (s->qdev.conf.blk) {
ctx = blk_get_aio_context(s->qdev.conf.blk);
aio_context_acquire(ctx);
blkconf_blocksizes(&s->qdev.conf);
if (!blkconf_blocksizes(&s->qdev.conf, errp)) {
goto out;
}
}
s->qdev.blocksize = s->qdev.conf.logical_block_size;
s->qdev.type = TYPE_DISK;
if (!s->product) {
s->product = g_strdup("QEMU HARDDISK");
}
scsi_realize(&s->qdev, errp);
out:
if (ctx) {
aio_context_release(ctx);
}
Expand Down
5 changes: 4 additions & 1 deletion hw/usb/dev-storage.c
Expand Up @@ -612,7 +612,10 @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
return;
}

blkconf_blocksizes(&s->conf);
if (!blkconf_blocksizes(&s->conf, errp)) {
return;
}

if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
errp)) {
return;
Expand Down
2 changes: 1 addition & 1 deletion include/hw/block/block.h
Expand Up @@ -87,7 +87,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
bool blkconf_geometry(BlockConf *conf, int *trans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
Error **errp);
void blkconf_blocksizes(BlockConf *conf);
bool blkconf_blocksizes(BlockConf *conf, Error **errp);
bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
bool resizable, Error **errp);

Expand Down
2 changes: 1 addition & 1 deletion tests/qemu-iotests/172.out
Expand Up @@ -1204,7 +1204,7 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
drive-type = "144"

Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical_block_size=4096
QEMU_PROG: -device floppy,drive=none0,logical_block_size=4096: Physical and logical block size must be 512 for floppy
QEMU_PROG: -device floppy,drive=none0,logical_block_size=4096: logical_block_size > physical_block_size not supported

Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physical_block_size=1024
QEMU_PROG: -device floppy,drive=none0,physical_block_size=1024: Physical and logical block size must be 512 for floppy
Expand Down

0 comments on commit c56ee92

Please sign in to comment.