2009-11-26 17:33:47 +03:00
|
|
|
#ifndef QEMU_HW_SCSI_H
|
|
|
|
#define QEMU_HW_SCSI_H
|
2009-10-30 11:54:00 +03:00
|
|
|
|
Include qemu/main-loop.h less
In my "build everything" tree, changing qemu/main-loop.h triggers a
recompile of some 5600 out of 6600 objects (not counting tests and
objects that don't depend on qemu/osdep.h). It includes block/aio.h,
which in turn includes qemu/event_notifier.h, qemu/notify.h,
qemu/processor.h, qemu/qsp.h, qemu/queue.h, qemu/thread-posix.h,
qemu/thread.h, qemu/timer.h, and a few more.
Include qemu/main-loop.h only where it's needed. Touching it now
recompiles only some 1700 objects. For block/aio.h and
qemu/event_notifier.h, these numbers drop from 5600 to 2800. For the
others, they shrink only slightly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20190812052359.30071-21-armbru@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2019-08-12 08:23:50 +03:00
|
|
|
#include "block/aio.h"
|
2013-02-05 20:06:20 +04:00
|
|
|
#include "hw/block/block.h"
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-core.h"
|
2017-08-22 08:08:27 +03:00
|
|
|
#include "scsi/utils.h"
|
2014-09-28 05:48:00 +04:00
|
|
|
#include "qemu/notify.h"
|
2020-09-03 23:43:22 +03:00
|
|
|
#include "qom/object.h"
|
2009-10-30 11:54:00 +03:00
|
|
|
|
2011-01-28 13:21:40 +03:00
|
|
|
#define MAX_SCSI_DEVS 255
|
|
|
|
|
2009-10-30 11:54:00 +03:00
|
|
|
typedef struct SCSIBus SCSIBus;
|
2011-08-13 17:44:45 +04:00
|
|
|
typedef struct SCSIBusInfo SCSIBusInfo;
|
2009-10-30 11:54:00 +03:00
|
|
|
typedef struct SCSIDevice SCSIDevice;
|
2011-04-18 14:35:39 +04:00
|
|
|
typedef struct SCSIRequest SCSIRequest;
|
2011-08-03 12:49:08 +04:00
|
|
|
typedef struct SCSIReqOps SCSIReqOps;
|
2009-10-30 11:54:00 +03:00
|
|
|
|
2014-03-06 12:26:02 +04:00
|
|
|
#define SCSI_SENSE_BUF_SIZE_OLD 96
|
scsi: Change scsi sense buf size to 252
Current buffer size fails the assersion check in like
hw/scsi/scsi-bus.c:1655: assert(req->sense_len <= sizeof(req->sense));
when backend (block/iscsi.c) returns more data then 96.
Exercise the core dump path by booting an Gentoo ISO with scsi-generic
device backed with iscsi (built with libiscsi 1.7.0):
x86_64-softmmu/qemu-system-x86_64 \
-drive file=iscsi://localhost:3260/iqn.foobar/0,if=none,id=drive-disk \
-device virtio-scsi-pci,id=scsi1,bus=pci.0,addr=0x6 \
-device scsi-generic,drive=drive-disk,bus=scsi1.0,id=iscsi-disk \
-boot d \
-cdrom gentoo.iso
qemu-system-x86_64: hw/scsi/scsi-bus.c:1655: scsi_req_complete:
Assertion `req->sense_len <= sizeof(req->sense)' failed.
According to SPC-4, section 4.5.2.1, 252 is the limit of sense data. So
increase the value to fix it.
Also remove duplicated define for the macro.
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-01-24 11:02:24 +04:00
|
|
|
#define SCSI_SENSE_BUF_SIZE 252
|
2011-08-03 12:49:07 +04:00
|
|
|
|
2011-04-18 14:35:39 +04:00
|
|
|
struct SCSIRequest {
|
2009-11-26 17:33:48 +03:00
|
|
|
SCSIBus *bus;
|
|
|
|
SCSIDevice *dev;
|
2011-10-12 14:57:59 +04:00
|
|
|
const SCSIReqOps *ops;
|
2011-04-18 18:01:56 +04:00
|
|
|
uint32_t refcount;
|
2009-11-26 17:33:48 +03:00
|
|
|
uint32_t tag;
|
2009-11-26 17:33:50 +03:00
|
|
|
uint32_t lun;
|
2009-11-26 17:34:00 +03:00
|
|
|
uint32_t status;
|
2014-09-16 11:20:17 +04:00
|
|
|
void *hba_private;
|
2011-07-06 13:55:37 +04:00
|
|
|
size_t resid;
|
2011-08-03 12:49:11 +04:00
|
|
|
SCSICommand cmd;
|
2014-09-28 05:48:00 +04:00
|
|
|
NotifierList cancel_notifiers;
|
2014-09-16 11:20:17 +04:00
|
|
|
|
|
|
|
/* Note:
|
|
|
|
* - fields before sense are initialized by scsi_req_alloc;
|
|
|
|
* - sense[] is uninitialized;
|
|
|
|
* - fields after sense are memset to 0 by scsi_req_alloc.
|
|
|
|
* */
|
|
|
|
|
|
|
|
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
|
|
|
uint32_t sense_len;
|
|
|
|
bool enqueued;
|
|
|
|
bool io_canceled;
|
|
|
|
bool retry;
|
|
|
|
bool dma_started;
|
2014-10-07 15:59:14 +04:00
|
|
|
BlockAIOCB *aiocb;
|
2011-07-06 13:26:47 +04:00
|
|
|
QEMUSGList *sg;
|
2009-11-26 17:33:49 +03:00
|
|
|
QTAILQ_ENTRY(SCSIRequest) next;
|
2011-04-18 14:35:39 +04:00
|
|
|
};
|
2009-11-26 17:33:48 +03:00
|
|
|
|
2011-12-16 00:50:08 +04:00
|
|
|
#define TYPE_SCSI_DEVICE "scsi-device"
|
2020-09-16 21:25:18 +03:00
|
|
|
OBJECT_DECLARE_TYPE(SCSIDevice, SCSIDeviceClass, SCSI_DEVICE)
|
2011-12-16 00:50:08 +04:00
|
|
|
|
2020-09-03 23:43:22 +03:00
|
|
|
struct SCSIDeviceClass {
|
2011-12-16 00:50:08 +04:00
|
|
|
DeviceClass parent_class;
|
2014-08-12 06:12:55 +04:00
|
|
|
void (*realize)(SCSIDevice *dev, Error **errp);
|
qdev: Unrealize must not fail
Devices may have component devices and buses.
Device realization may fail. Realization is recursive: a device's
realize() method realizes its components, and device_set_realized()
realizes its buses (which should in turn realize the devices on that
bus, except bus_set_realized() doesn't implement that, yet).
When realization of a component or bus fails, we need to roll back:
unrealize everything we realized so far. If any of these unrealizes
failed, the device would be left in an inconsistent state. Must not
happen.
device_set_realized() lets it happen: it ignores errors in the roll
back code starting at label child_realize_fail.
Since realization is recursive, unrealization must be recursive, too.
But how could a partly failed unrealize be rolled back? We'd have to
re-realize, which can fail. This design is fundamentally broken.
device_set_realized() does not roll back at all. Instead, it keeps
unrealizing, ignoring further errors.
It can screw up even for a device with no buses: if the lone
dc->unrealize() fails, it still unregisters vmstate, and calls
listeners' unrealize() callback.
bus_set_realized() does not roll back either. Instead, it stops
unrealizing.
Fortunately, no unrealize method can fail, as we'll see below.
To fix the design error, drop parameter @errp from all the unrealize
methods.
Any unrealize method that uses @errp now needs an update. This leads
us to unrealize() methods that can fail. Merely passing it to another
unrealize method cannot cause failure, though. Here are the ones that
do other things with @errp:
* virtio_serial_device_unrealize()
Fails when qbus_set_hotplug_handler() fails, but still does all the
other work. On failure, the device would stay realized with its
resources completely gone. Oops. Can't happen, because
qbus_set_hotplug_handler() can't actually fail here. Pass
&error_abort to qbus_set_hotplug_handler() instead.
* hw/ppc/spapr_drc.c's unrealize()
Fails when object_property_del() fails, but all the other work is
already done. On failure, the device would stay realized with its
vmstate registration gone. Oops. Can't happen, because
object_property_del() can't actually fail here. Pass &error_abort
to object_property_del() instead.
* spapr_phb_unrealize()
Fails and bails out when remove_drcs() fails, but other work is
already done. On failure, the device would stay realized with some
of its resources gone. Oops. remove_drcs() fails only when
chassis_from_bus()'s object_property_get_uint() fails, and it can't
here. Pass &error_abort to remove_drcs() instead.
Therefore, no unrealize method can fail before this patch.
device_set_realized()'s recursive unrealization via bus uses
object_property_set_bool(). Can't drop @errp there, so pass
&error_abort.
We similarly unrealize with object_property_set_bool() elsewhere,
always ignoring errors. Pass &error_abort instead.
Several unrealize methods no longer handle errors from other unrealize
methods: virtio_9p_device_unrealize(),
virtio_input_device_unrealize(), scsi_qdev_unrealize(), ...
Much of the deleted error handling looks wrong anyway.
One unrealize methods no longer ignore such errors:
usb_ehci_pci_exit().
Several realize methods no longer ignore errors when rolling back:
v9fs_device_realize_common(), pci_qdev_unrealize(),
spapr_phb_realize(), usb_qdev_realize(), vfio_ccw_realize(),
virtio_device_realize().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-17-armbru@redhat.com>
2020-05-05 18:29:24 +03:00
|
|
|
void (*unrealize)(SCSIDevice *dev);
|
2014-07-16 12:39:05 +04:00
|
|
|
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
|
|
|
void *hba_private);
|
2011-12-16 00:50:08 +04:00
|
|
|
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
|
|
|
|
uint8_t *buf, void *hba_private);
|
|
|
|
void (*unit_attention_reported)(SCSIDevice *s);
|
2020-09-03 23:43:22 +03:00
|
|
|
};
|
2011-12-16 00:50:08 +04:00
|
|
|
|
2009-10-30 11:54:00 +03:00
|
|
|
struct SCSIDevice
|
|
|
|
{
|
|
|
|
DeviceState qdev;
|
2011-10-25 14:53:36 +04:00
|
|
|
VMChangeStateEntry *vmsentry;
|
|
|
|
QEMUBH *bh;
|
2009-10-30 11:54:00 +03:00
|
|
|
uint32_t id;
|
block: add topology qdev properties
Add three new qdev properties to export block topology information to
the guest. This is needed to get optimal I/O alignment for RAID arrays
or SSDs.
The options are:
- physical_block_size to specify the physical block size of the device,
this is going to increase from 512 bytes to 4096 kilobytes for many
modern storage devices
- min_io_size to specify the minimal I/O size without performance impact,
this is typically set to the RAID chunk size for arrays.
- opt_io_size to specify the optimal sustained I/O size, this is
typically the RAID stripe width for arrays.
I decided to not auto-probe these values from blkid which might easily
be possible as I don't know how to deal with these issues on migration.
Note that we specificly only set the physical_block_size, and not the
logial one which is the unit all I/O is described in. The reason for
that is that IDE does not support increasing the logical block size and
at last for now I want to stick to one meachnisms in queue and allow
for easy switching of transports for a given backing image which would
not be possible if scsi and virtio use real 4k sectors, while ide only
uses the physical block exponent.
To make this more common for the different block drivers introduce a
new BlockConf structure holding all common block properties and a
DEFINE_BLOCK_PROPERTIES macro to add them all together, mirroring
what is done for network drivers. Also switch over all block drivers
to use it, except for the floppy driver which has weird driveA/driveB
properties and probably won't require any advanced block options ever.
Example usage for a virtio device with 4k physical block size and
8k optimal I/O size:
-drive file=scratch.img,media=disk,cache=none,id=scratch \
-device virtio-blk-pci,drive=scratch,physical_block_size=4096,opt_io_size=8192
aliguori: updated patch to take into account BLOCK events
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-02-11 01:37:09 +03:00
|
|
|
BlockConf conf;
|
2011-08-03 12:49:17 +04:00
|
|
|
SCSISense unit_attention;
|
2011-09-13 18:19:53 +04:00
|
|
|
bool sense_is_ua;
|
2011-08-03 12:49:07 +04:00
|
|
|
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
|
|
|
uint32_t sense_len;
|
2009-11-26 17:33:49 +03:00
|
|
|
QTAILQ_HEAD(, SCSIRequest) requests;
|
2011-07-28 01:24:50 +04:00
|
|
|
uint32_t channel;
|
2011-08-03 12:49:12 +04:00
|
|
|
uint32_t lun;
|
2009-11-26 17:33:52 +03:00
|
|
|
int blocksize;
|
2009-11-26 17:33:54 +03:00
|
|
|
int type;
|
2011-10-13 12:39:50 +04:00
|
|
|
uint64_t max_lba;
|
2016-01-12 13:47:00 +03:00
|
|
|
uint64_t wwn;
|
|
|
|
uint64_t port_wwn;
|
2018-04-05 19:09:51 +03:00
|
|
|
int scsi_version;
|
|
|
|
int default_scsi_version;
|
hw/scsi: add VPD Block Limits emulation
The VPD Block Limits Inquiry page is optional, allowing SCSI devices
to not implement it. This is the case for devices like the MegaRAID
SAS 9361-8i and Microsemi PM8069.
In case of SCSI passthrough, the response of this request is used by
the QEMU SCSI layer to set the max_io_sectors that the guest
device will support, based on the value of the max_sectors_kb that
the device has set in the host at that time. Without this response,
the guest kernel is free to assume any value of max_io_sectors
for the SCSI device. If this value is greater than the value from
the host, SCSI Sense errors will occur because the guest will send
read/write requests that are larger than the underlying host device
is configured to support. An example of this behavior can be seen
in [1].
A workaround is to set the max_sectors_kb host value back in the guest
kernel (a process that can be automated using rc.local startup scripts
and the like), but this has several drawbacks:
- it can be troublesome if the guest has many passthrough devices that
needs this tuning;
- if a change in max_sectors_kb is made in the host side, manual change
in the guests will also be required;
- during an OS install it is difficult, and sometimes not possible, to
go to a terminal and change the max_sectors_kb prior to the installation.
This means that the disk can't be used during the install process. The
easiest alternative here is to roll back to scsi-hd, install the guest
and then go back to SCSI passthrough when the installation is done and
max_sectors_kb can be set.
An easier way would be to QEMU handle the absence of the Block Limits
VPD device response, setting max_io_sectors accordingly and allowing
the guest to use the device without the hassle.
This patch adds emulation of the Block Limits VPD response for
SCSI passthrough devices of type TYPE_DISK that doesn't support
it. The following changes were made:
- scsi_handle_inquiry_reply will now check the available VPD
pages from the Inquiry EVPD reply. In case the device does not
- a new function called scsi_generic_set_vpd_bl_emulation,
that is called during device realize, was created to set a
new flag 'needs_vpd_bl_emulation' of the device. This function
retrieves the Inquiry EVPD response of the device to check for
VPD BL support.
- scsi_handle_inquiry_reply will now check the available VPD
pages from the Inquiry EVPD reply in case the device needs
VPD BL emulation, adding the Block Limits page (0xb0) to
the list. This will make the guest kernel aware of the
support that we're now providing by emulation.
- a new function scsi_emulate_block_limits creates the
emulated Block Limits response. This function is called
inside scsi_read_complete in case the device requires
Block Limits VPD emulation and we detected a SCSI Sense
error in the VPD Block Limits reply that was issued
from the guest kernel to the device. This error is
expected: we're reporting support from our side, but
the device isn't aware of it.
With this patch, the guest now queries the Block Limits
page during the device configuration because it is being
advertised in the Supported Pages response. It will either
receive the Block Limits page from the hardware, if it supports
it, or will receive an emulated response from QEMU. At any rate,
the guest now has the information to set the max_sectors_kb
parameter accordingly, sparing the user of SCSI sense errors
that would happen without the emulated response and in the
absence of Block Limits support from the hardware.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1566195
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1566195
Reported-by: Dac Nguyen <dacng@us.ibm.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Message-Id: <20180627172432.11120-4-danielhb413@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2018-06-27 20:24:32 +03:00
|
|
|
bool needs_vpd_bl_emulation;
|
2019-04-26 20:29:47 +03:00
|
|
|
bool hba_supports_iothread;
|
2009-10-30 11:54:00 +03:00
|
|
|
};
|
|
|
|
|
2011-12-02 19:27:02 +04:00
|
|
|
extern const VMStateDescription vmstate_scsi_device;
|
|
|
|
|
|
|
|
#define VMSTATE_SCSI_DEVICE(_field, _state) { \
|
|
|
|
.name = (stringify(_field)), \
|
|
|
|
.size = sizeof(SCSIDevice), \
|
|
|
|
.vmsd = &vmstate_scsi_device, \
|
|
|
|
.flags = VMS_STRUCT, \
|
|
|
|
.offset = vmstate_offset_value(_state, _field, SCSIDevice), \
|
|
|
|
}
|
|
|
|
|
2009-10-30 11:54:00 +03:00
|
|
|
/* cdrom.c */
|
|
|
|
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
|
|
|
|
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
|
|
|
|
|
|
|
|
/* scsi-bus.c */
|
2011-08-03 12:49:08 +04:00
|
|
|
struct SCSIReqOps {
|
|
|
|
size_t size;
|
2011-08-03 12:49:09 +04:00
|
|
|
void (*free_req)(SCSIRequest *req);
|
|
|
|
int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
|
|
|
|
void (*read_data)(SCSIRequest *req);
|
|
|
|
void (*write_data)(SCSIRequest *req);
|
|
|
|
uint8_t *(*get_buf)(SCSIRequest *req);
|
2011-12-02 19:27:02 +04:00
|
|
|
|
|
|
|
void (*save_request)(QEMUFile *f, SCSIRequest *req);
|
|
|
|
void (*load_request)(QEMUFile *f, SCSIRequest *req);
|
2011-08-03 12:49:08 +04:00
|
|
|
};
|
|
|
|
|
2011-08-13 17:44:45 +04:00
|
|
|
struct SCSIBusInfo {
|
2011-08-13 20:55:17 +04:00
|
|
|
int tcq;
|
2011-07-28 01:24:50 +04:00
|
|
|
int max_channel, max_target, max_lun;
|
2014-07-16 12:39:05 +04:00
|
|
|
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
|
|
|
void *hba_private);
|
2011-04-22 14:27:30 +04:00
|
|
|
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
2011-07-06 13:55:37 +04:00
|
|
|
void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
|
2011-04-19 00:53:08 +04:00
|
|
|
void (*cancel)(SCSIRequest *req);
|
2012-07-16 16:22:36 +04:00
|
|
|
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
|
2011-07-06 13:26:47 +04:00
|
|
|
QEMUSGList *(*get_sg_list)(SCSIRequest *req);
|
2011-12-02 19:27:02 +04:00
|
|
|
|
|
|
|
void (*save_request)(QEMUFile *f, SCSIRequest *req);
|
|
|
|
void *(*load_request)(QEMUFile *f, SCSIRequest *req);
|
2012-07-09 14:06:28 +04:00
|
|
|
void (*free_request)(SCSIBus *bus, void *priv);
|
2011-04-18 19:11:14 +04:00
|
|
|
};
|
|
|
|
|
2012-05-02 11:00:20 +04:00
|
|
|
#define TYPE_SCSI_BUS "SCSI"
|
2020-09-16 21:25:19 +03:00
|
|
|
OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS)
|
2012-05-02 11:00:20 +04:00
|
|
|
|
2009-10-30 11:54:00 +03:00
|
|
|
struct SCSIBus {
|
|
|
|
BusState qbus;
|
|
|
|
int busnr;
|
|
|
|
|
2011-08-03 12:49:17 +04:00
|
|
|
SCSISense unit_attention;
|
2011-08-13 17:44:45 +04:00
|
|
|
const SCSIBusInfo *info;
|
2009-10-30 11:54:00 +03:00
|
|
|
};
|
|
|
|
|
2013-08-23 22:30:03 +04:00
|
|
|
void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host,
|
|
|
|
const SCSIBusInfo *info, const char *bus_name);
|
2009-10-30 11:54:00 +03:00
|
|
|
|
|
|
|
static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
|
|
|
|
{
|
|
|
|
return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:18 +04:00
|
|
|
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
|
2013-04-03 14:41:46 +04:00
|
|
|
int unit, bool removable, int bootindex,
|
2018-01-17 03:52:22 +03:00
|
|
|
bool share_rw,
|
2018-06-25 19:39:00 +03:00
|
|
|
BlockdevOnError rerror,
|
|
|
|
BlockdevOnError werror,
|
2013-07-21 14:16:34 +04:00
|
|
|
const char *serial, Error **errp);
|
2018-02-20 13:42:37 +03:00
|
|
|
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
|
2017-02-15 15:18:54 +03:00
|
|
|
void scsi_legacy_handle_cmdline(void);
|
2009-10-30 11:54:00 +03:00
|
|
|
|
2011-10-12 14:57:59 +04:00
|
|
|
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
|
|
|
uint32_t tag, uint32_t lun, void *hba_private);
|
2011-07-11 17:02:24 +04:00
|
|
|
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
2011-08-03 12:49:10 +04:00
|
|
|
uint8_t *buf, void *hba_private);
|
|
|
|
int32_t scsi_req_enqueue(SCSIRequest *req);
|
2011-04-18 18:01:56 +04:00
|
|
|
SCSIRequest *scsi_req_ref(SCSIRequest *req);
|
|
|
|
void scsi_req_unref(SCSIRequest *req);
|
2009-11-26 17:33:58 +03:00
|
|
|
|
2014-07-16 12:39:05 +04:00
|
|
|
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
|
|
|
void *hba_private);
|
2014-07-16 14:22:26 +04:00
|
|
|
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf);
|
2011-08-03 12:49:07 +04:00
|
|
|
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
|
2009-11-26 17:34:01 +03:00
|
|
|
void scsi_req_print(SCSIRequest *req);
|
2011-04-18 17:28:11 +04:00
|
|
|
void scsi_req_continue(SCSIRequest *req);
|
2011-04-18 16:59:13 +04:00
|
|
|
void scsi_req_data(SCSIRequest *req, int len);
|
2011-08-03 12:49:06 +04:00
|
|
|
void scsi_req_complete(SCSIRequest *req, int status);
|
2011-04-21 15:21:02 +04:00
|
|
|
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
2011-04-18 15:36:02 +04:00
|
|
|
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
2014-09-25 06:20:47 +04:00
|
|
|
void scsi_req_cancel_complete(SCSIRequest *req);
|
2011-04-19 00:53:08 +04:00
|
|
|
void scsi_req_cancel(SCSIRequest *req);
|
2014-09-28 05:48:00 +04:00
|
|
|
void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier);
|
2011-10-25 14:53:36 +04:00
|
|
|
void scsi_req_retry(SCSIRequest *req);
|
2011-08-03 12:49:18 +04:00
|
|
|
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
|
2012-07-16 16:18:58 +04:00
|
|
|
void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
|
2012-07-16 16:22:36 +04:00
|
|
|
void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
|
2014-10-29 15:00:11 +03:00
|
|
|
void scsi_device_unit_attention_reported(SCSIDevice *dev);
|
hw/scsi: add VPD Block Limits emulation
The VPD Block Limits Inquiry page is optional, allowing SCSI devices
to not implement it. This is the case for devices like the MegaRAID
SAS 9361-8i and Microsemi PM8069.
In case of SCSI passthrough, the response of this request is used by
the QEMU SCSI layer to set the max_io_sectors that the guest
device will support, based on the value of the max_sectors_kb that
the device has set in the host at that time. Without this response,
the guest kernel is free to assume any value of max_io_sectors
for the SCSI device. If this value is greater than the value from
the host, SCSI Sense errors will occur because the guest will send
read/write requests that are larger than the underlying host device
is configured to support. An example of this behavior can be seen
in [1].
A workaround is to set the max_sectors_kb host value back in the guest
kernel (a process that can be automated using rc.local startup scripts
and the like), but this has several drawbacks:
- it can be troublesome if the guest has many passthrough devices that
needs this tuning;
- if a change in max_sectors_kb is made in the host side, manual change
in the guests will also be required;
- during an OS install it is difficult, and sometimes not possible, to
go to a terminal and change the max_sectors_kb prior to the installation.
This means that the disk can't be used during the install process. The
easiest alternative here is to roll back to scsi-hd, install the guest
and then go back to SCSI passthrough when the installation is done and
max_sectors_kb can be set.
An easier way would be to QEMU handle the absence of the Block Limits
VPD device response, setting max_io_sectors accordingly and allowing
the guest to use the device without the hassle.
This patch adds emulation of the Block Limits VPD response for
SCSI passthrough devices of type TYPE_DISK that doesn't support
it. The following changes were made:
- scsi_handle_inquiry_reply will now check the available VPD
pages from the Inquiry EVPD reply. In case the device does not
- a new function called scsi_generic_set_vpd_bl_emulation,
that is called during device realize, was created to set a
new flag 'needs_vpd_bl_emulation' of the device. This function
retrieves the Inquiry EVPD response of the device to check for
VPD BL support.
- scsi_handle_inquiry_reply will now check the available VPD
pages from the Inquiry EVPD reply in case the device needs
VPD BL emulation, adding the Block Limits page (0xb0) to
the list. This will make the guest kernel aware of the
support that we're now providing by emulation.
- a new function scsi_emulate_block_limits creates the
emulated Block Limits response. This function is called
inside scsi_read_complete in case the device requires
Block Limits VPD emulation and we detected a SCSI Sense
error in the VPD Block Limits reply that was issued
from the guest kernel to the device. This error is
expected: we're reporting support from our side, but
the device isn't aware of it.
With this patch, the guest now queries the Block Limits
page during the device configuration because it is being
advertised in the Supported Pages response. It will either
receive the Block Limits page from the hardware, if it supports
it, or will receive an emulated response from QEMU. At any rate,
the guest now has the information to set the max_sectors_kb
parameter accordingly, sparing the user of SCSI sense errors
that would happen without the emulated response and in the
absence of Block Limits support from the hardware.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1566195
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1566195
Reported-by: Dac Nguyen <dacng@us.ibm.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Message-Id: <20180627172432.11120-4-danielhb413@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2018-06-27 20:24:32 +03:00
|
|
|
void scsi_generic_read_device_inquiry(SCSIDevice *dev);
|
2011-08-03 12:49:07 +04:00
|
|
|
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
|
2018-06-27 20:24:31 +03:00
|
|
|
int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
|
|
|
|
uint8_t *buf, uint8_t buf_size);
|
2011-07-28 01:24:50 +04:00
|
|
|
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
|
2020-10-06 15:39:02 +03:00
|
|
|
SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun);
|
2009-11-26 17:33:50 +03:00
|
|
|
|
2011-10-12 14:54:31 +04:00
|
|
|
/* scsi-generic.c. */
|
|
|
|
extern const SCSIReqOps scsi_generic_req_ops;
|
|
|
|
|
2009-10-30 11:54:00 +03:00
|
|
|
#endif
|