mirror of https://github.com/xemu-project/xemu.git
Block patches for 2.3
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJUwoqCAAoJEH8JsnLIjy/Wy0AP+gJTqWbqdA530k0ftmBQ0nE5 gLin9iBvIgn2mx75RuertJ81B+fQTsqHM72fBY8q4vny3Vy40f08bCqtTBKoB9tp ekJq9UIX3S72WRfQ9e9/ZT33GIMP2+k4utbkYdOoM/9f61rIuaZb5EGn1KXgaztQ kVcnrcFpNcDZK3MwRsB2aCH43np2Q8a1zVEdczClbLg3ntVcXnWNcLc18UzJB8yi k5wOOe2PMoDBch9UNVEcC9ffFpZaXWdvrVLQPK0HYLzV0iNr3y8uRCkIVr53o/uL 4GApyK4ZFmSTONUWc5wOg4/614V+IsMLsNezPbKqraL0d+/BwzMxmK6nqa0xyKKM cHdQaqrs5SSo18DmFhKbE9qhLYJBN3DSigAl2Q+bBRdIM5V95pF7Z15yK6oBHwrL Anpy9nnA7O/R3fylaxKc1sxKW63ZlFzF/lbXpDA9EDWm2UEPR7RCFYdHVtqb53fl buWkI0JSmGT7m7vRGyCvQiF9SywvzMvjstyodGi7zg9FIn3NhkUxSIlZOogn7wF0 Aa4kBLe5yNz+YMUv/7Hnf16jCOMacR4GgK+5AYyJt44psEbItFrPl7sbba+bkSMI 419AYZEAEKZfRsBC0pyDifchgWBxKRQdUPebbi0qzhKxq44KK96ueCDyEqHPsrqX TwbIrHlTa2ozDvNqmrol =rYNq -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block patches for 2.3 # gpg: Signature made Fri 23 Jan 2015 17:53:06 GMT using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: iotests: Lower 064's memory usage block: vhdx - force FileOffsetMB field to '0' for certain block states block: update string sizes for filename,backing_file,exact_filename block: mirror - change string allocation to 2-bytes block: remove unused variable in bdrv_commit block: qapi - move string allocation from stack to the heap block: vmdk - move string allocations from stack to the heap block: vmdk - make ret variable usage clear iotests: Add tests for more corruption cases qcow2: Add two more unalignment checks virtio-blk: Use blk_aio_ioctl virtio-blk: Pass req to virtio_blk_handle_scsi_req Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d109f80af3
3
block.c
3
block.c
|
@ -2207,7 +2207,6 @@ int bdrv_commit(BlockDriverState *bs)
|
|||
int n, ro, open_flags;
|
||||
int ret = 0;
|
||||
uint8_t *buf = NULL;
|
||||
char filename[PATH_MAX];
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
@ -2222,8 +2221,6 @@ int bdrv_commit(BlockDriverState *bs)
|
|||
}
|
||||
|
||||
ro = bs->backing_hd->read_only;
|
||||
/* Use pstrcpy (not strncpy): filename must be NUL-terminated. */
|
||||
pstrcpy(filename, sizeof(filename), bs->backing_hd->filename);
|
||||
open_flags = bs->backing_hd->open_flags;
|
||||
|
||||
if (ro) {
|
||||
|
|
|
@ -378,7 +378,8 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||
int64_t sector_num, end, sectors_per_chunk, length;
|
||||
uint64_t last_pause_ns;
|
||||
BlockDriverInfo bdi;
|
||||
char backing_filename[1024];
|
||||
char backing_filename[2]; /* we only need 2 characters because we are only
|
||||
checking for a NULL string */
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
|
|
|
@ -175,7 +175,6 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
|||
{
|
||||
int64_t size;
|
||||
const char *backing_filename;
|
||||
char backing_filename2[1024];
|
||||
BlockDriverInfo bdi;
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
|
@ -211,13 +210,14 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
|||
|
||||
backing_filename = bs->backing_file;
|
||||
if (backing_filename[0] != '\0') {
|
||||
char *backing_filename2 = g_malloc0(PATH_MAX);
|
||||
info->backing_filename = g_strdup(backing_filename);
|
||||
info->has_backing_filename = true;
|
||||
bdrv_get_full_backing_filename(bs, backing_filename2,
|
||||
sizeof(backing_filename2), &err);
|
||||
bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
qapi_free_ImageInfo(info);
|
||||
g_free(backing_filename2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -231,6 +231,7 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
|||
info->backing_filename_format = g_strdup(bs->backing_format);
|
||||
info->has_backing_filename_format = true;
|
||||
}
|
||||
g_free(backing_filename2);
|
||||
}
|
||||
|
||||
ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err);
|
||||
|
|
|
@ -215,7 +215,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
/* read the backing file name */
|
||||
if (header.backing_file_offset != 0) {
|
||||
len = header.backing_file_size;
|
||||
if (len > 1023) {
|
||||
if (len > 1023 || len > sizeof(bs->backing_file)) {
|
||||
error_setg(errp, "Backing file name too long");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
|
|
@ -1651,6 +1651,14 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (offset_into_cluster(s, l2_offset)) {
|
||||
qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#"
|
||||
PRIx64 " unaligned (L1 index: %#x)",
|
||||
l2_offset, i);
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_active_l1) {
|
||||
/* get active L2 tables from cache */
|
||||
ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
|
||||
|
@ -1709,6 +1717,19 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
|||
}
|
||||
}
|
||||
|
||||
if (offset_into_cluster(s, offset)) {
|
||||
qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset "
|
||||
"%#" PRIx64 " unaligned (L2 offset: %#"
|
||||
PRIx64 ", L2 index: %#x)", offset,
|
||||
l2_offset, j);
|
||||
if (!preallocated) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
QCOW2_DISCARD_ALWAYS);
|
||||
}
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
|
||||
if (ret < 0) {
|
||||
if (!preallocated) {
|
||||
|
|
|
@ -868,7 +868,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
/* read the backing file name */
|
||||
if (header.backing_file_offset != 0) {
|
||||
len = header.backing_file_size;
|
||||
if (len > MIN(1023, s->cluster_size - header.backing_file_offset)) {
|
||||
if (len > MIN(1023, s->cluster_size - header.backing_file_offset) ||
|
||||
len > sizeof(bs->backing_file)) {
|
||||
error_setg(errp, "Backing file name too long");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
|
13
block/vhdx.c
13
block/vhdx.c
|
@ -1174,7 +1174,18 @@ static void vhdx_update_bat_table_entry(BlockDriverState *bs, BDRVVHDXState *s,
|
|||
{
|
||||
/* The BAT entry is a uint64, with 44 bits for the file offset in units of
|
||||
* 1MB, and 3 bits for the block state. */
|
||||
s->bat[sinfo->bat_idx] = sinfo->file_offset;
|
||||
if ((state == PAYLOAD_BLOCK_ZERO) ||
|
||||
(state == PAYLOAD_BLOCK_UNDEFINED) ||
|
||||
(state == PAYLOAD_BLOCK_NOT_PRESENT) ||
|
||||
(state == PAYLOAD_BLOCK_UNMAPPED)) {
|
||||
s->bat[sinfo->bat_idx] = 0; /* For PAYLOAD_BLOCK_ZERO, the
|
||||
FileOffsetMB field is denoted as
|
||||
'reserved' in the v1.0 spec. If it is
|
||||
non-zero, MS Hyper-V will fail to read
|
||||
the disk image */
|
||||
} else {
|
||||
s->bat[sinfo->bat_idx] = sinfo->file_offset;
|
||||
}
|
||||
|
||||
s->bat[sinfo->bat_idx] |= state & VHDX_BAT_STATE_BIT_MASK;
|
||||
|
||||
|
|
51
block/vmdk.c
51
block/vmdk.c
|
@ -785,13 +785,14 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|||
const char *desc_file_path, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
int matches;
|
||||
char access[11];
|
||||
char type[11];
|
||||
char fname[512];
|
||||
const char *p = desc;
|
||||
int64_t sectors = 0;
|
||||
int64_t flat_offset;
|
||||
char extent_path[PATH_MAX];
|
||||
char *extent_path;
|
||||
BlockDriverState *extent_file;
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
VmdkExtent *extent;
|
||||
|
@ -805,23 +806,23 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|||
* RW [size in sectors] VMFSSPARSE "file-name.vmdk"
|
||||
*/
|
||||
flat_offset = -1;
|
||||
ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
|
||||
access, §ors, type, fname, &flat_offset);
|
||||
if (ret < 4 || strcmp(access, "RW")) {
|
||||
matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
|
||||
access, §ors, type, fname, &flat_offset);
|
||||
if (matches < 4 || strcmp(access, "RW")) {
|
||||
goto next_line;
|
||||
} else if (!strcmp(type, "FLAT")) {
|
||||
if (ret != 5 || flat_offset < 0) {
|
||||
if (matches != 5 || flat_offset < 0) {
|
||||
error_setg(errp, "Invalid extent lines: \n%s", p);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(type, "VMFS")) {
|
||||
if (ret == 4) {
|
||||
if (matches == 4) {
|
||||
flat_offset = 0;
|
||||
} else {
|
||||
error_setg(errp, "Invalid extent lines:\n%s", p);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (ret != 4) {
|
||||
} else if (matches != 4) {
|
||||
error_setg(errp, "Invalid extent lines:\n%s", p);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -841,11 +842,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
extent_path = g_malloc0(PATH_MAX);
|
||||
path_combine(extent_path, sizeof(extent_path),
|
||||
desc_file_path, fname);
|
||||
extent_file = NULL;
|
||||
ret = bdrv_open(&extent_file, extent_path, NULL, NULL,
|
||||
bs->open_flags | BDRV_O_PROTOCOL, NULL, errp);
|
||||
g_free(extent_path);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1795,10 +1798,15 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||
int ret = 0;
|
||||
bool flat, split, compress;
|
||||
GString *ext_desc_lines;
|
||||
char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
|
||||
char *path = g_malloc0(PATH_MAX);
|
||||
char *prefix = g_malloc0(PATH_MAX);
|
||||
char *postfix = g_malloc0(PATH_MAX);
|
||||
char *desc_line = g_malloc0(BUF_SIZE);
|
||||
char *ext_filename = g_malloc0(PATH_MAX);
|
||||
char *desc_filename = g_malloc0(PATH_MAX);
|
||||
const int64_t split_size = 0x80000000; /* VMDK has constant split size */
|
||||
const char *desc_extent_line;
|
||||
char parent_desc_line[BUF_SIZE] = "";
|
||||
char *parent_desc_line = g_malloc0(BUF_SIZE);
|
||||
uint32_t parent_cid = 0xffffffff;
|
||||
uint32_t number_heads = 16;
|
||||
bool zeroed_grain = false;
|
||||
|
@ -1914,33 +1922,27 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||
}
|
||||
parent_cid = vmdk_read_cid(bs, 0);
|
||||
bdrv_unref(bs);
|
||||
snprintf(parent_desc_line, sizeof(parent_desc_line),
|
||||
snprintf(parent_desc_line, BUF_SIZE,
|
||||
"parentFileNameHint=\"%s\"", backing_file);
|
||||
}
|
||||
|
||||
/* Create extents */
|
||||
filesize = total_size;
|
||||
while (filesize > 0) {
|
||||
char desc_line[BUF_SIZE];
|
||||
char ext_filename[PATH_MAX];
|
||||
char desc_filename[PATH_MAX];
|
||||
int64_t size = filesize;
|
||||
|
||||
if (split && size > split_size) {
|
||||
size = split_size;
|
||||
}
|
||||
if (split) {
|
||||
snprintf(desc_filename, sizeof(desc_filename), "%s-%c%03d%s",
|
||||
snprintf(desc_filename, PATH_MAX, "%s-%c%03d%s",
|
||||
prefix, flat ? 'f' : 's', ++idx, postfix);
|
||||
} else if (flat) {
|
||||
snprintf(desc_filename, sizeof(desc_filename), "%s-flat%s",
|
||||
prefix, postfix);
|
||||
snprintf(desc_filename, PATH_MAX, "%s-flat%s", prefix, postfix);
|
||||
} else {
|
||||
snprintf(desc_filename, sizeof(desc_filename), "%s%s",
|
||||
prefix, postfix);
|
||||
snprintf(desc_filename, PATH_MAX, "%s%s", prefix, postfix);
|
||||
}
|
||||
snprintf(ext_filename, sizeof(ext_filename), "%s%s",
|
||||
path, desc_filename);
|
||||
snprintf(ext_filename, PATH_MAX, "%s%s", path, desc_filename);
|
||||
|
||||
if (vmdk_create_extent(ext_filename, size,
|
||||
flat, compress, zeroed_grain, opts, errp)) {
|
||||
|
@ -1950,7 +1952,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||
filesize -= size;
|
||||
|
||||
/* Format description line */
|
||||
snprintf(desc_line, sizeof(desc_line),
|
||||
snprintf(desc_line, BUF_SIZE,
|
||||
desc_extent_line, size / BDRV_SECTOR_SIZE, desc_filename);
|
||||
g_string_append(ext_desc_lines, desc_line);
|
||||
}
|
||||
|
@ -2005,6 +2007,13 @@ exit:
|
|||
g_free(backing_file);
|
||||
g_free(fmt);
|
||||
g_free(desc);
|
||||
g_free(path);
|
||||
g_free(prefix);
|
||||
g_free(postfix);
|
||||
g_free(desc_line);
|
||||
g_free(ext_filename);
|
||||
g_free(desc_filename);
|
||||
g_free(parent_desc_line);
|
||||
g_string_free(ext_desc_lines, true);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2909,8 +2909,8 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
|||
|
||||
array_init(&(s->commits), sizeof(commit_t));
|
||||
|
||||
s->qcow_filename = g_malloc(1024);
|
||||
ret = get_tmp_filename(s->qcow_filename, 1024);
|
||||
s->qcow_filename = g_malloc(PATH_MAX);
|
||||
ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "can't create temporary file");
|
||||
goto err;
|
||||
|
|
|
@ -115,6 +115,56 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
|
|||
virtio_blk_free_request(req);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
typedef struct {
|
||||
VirtIOBlockReq *req;
|
||||
struct sg_io_hdr hdr;
|
||||
} VirtIOBlockIoctlReq;
|
||||
|
||||
static void virtio_blk_ioctl_complete(void *opaque, int status)
|
||||
{
|
||||
VirtIOBlockIoctlReq *ioctl_req = opaque;
|
||||
VirtIOBlockReq *req = ioctl_req->req;
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
|
||||
struct virtio_scsi_inhdr *scsi;
|
||||
struct sg_io_hdr *hdr;
|
||||
|
||||
scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
|
||||
|
||||
if (status) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
virtio_stl_p(vdev, &scsi->errors, 255);
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = &ioctl_req->hdr;
|
||||
/*
|
||||
* From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi)
|
||||
* clear the masked_status field [hence status gets cleared too, see
|
||||
* block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED
|
||||
* status has occurred. However they do set DRIVER_SENSE in driver_status
|
||||
* field. Also a (sb_len_wr > 0) indicates there is a sense buffer.
|
||||
*/
|
||||
if (hdr->status == 0 && hdr->sb_len_wr > 0) {
|
||||
hdr->status = CHECK_CONDITION;
|
||||
}
|
||||
|
||||
virtio_stl_p(vdev, &scsi->errors,
|
||||
hdr->status | (hdr->msg_status << 8) |
|
||||
(hdr->host_status << 16) | (hdr->driver_status << 24));
|
||||
virtio_stl_p(vdev, &scsi->residual, hdr->resid);
|
||||
virtio_stl_p(vdev, &scsi->sense_len, hdr->sb_len_wr);
|
||||
virtio_stl_p(vdev, &scsi->data_len, hdr->dxfer_len);
|
||||
|
||||
out:
|
||||
virtio_blk_req_complete(req, status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(ioctl_req);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
|
||||
{
|
||||
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
|
||||
|
@ -127,16 +177,17 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
|
|||
return req;
|
||||
}
|
||||
|
||||
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
|
||||
VirtQueueElement *elem)
|
||||
static int virtio_blk_handle_scsi_req(VirtIOBlockReq *req)
|
||||
{
|
||||
int status = VIRTIO_BLK_S_OK;
|
||||
struct virtio_scsi_inhdr *scsi = NULL;
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(blk);
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
|
||||
VirtQueueElement *elem = &req->elem;
|
||||
VirtIOBlock *blk = req->dev;
|
||||
|
||||
#ifdef __linux__
|
||||
int i;
|
||||
struct sg_io_hdr hdr;
|
||||
VirtIOBlockIoctlReq *ioctl_req;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -171,71 +222,52 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
|
|||
}
|
||||
|
||||
#ifdef __linux__
|
||||
memset(&hdr, 0, sizeof(struct sg_io_hdr));
|
||||
hdr.interface_id = 'S';
|
||||
hdr.cmd_len = elem->out_sg[1].iov_len;
|
||||
hdr.cmdp = elem->out_sg[1].iov_base;
|
||||
hdr.dxfer_len = 0;
|
||||
ioctl_req = g_new0(VirtIOBlockIoctlReq, 1);
|
||||
ioctl_req->req = req;
|
||||
ioctl_req->hdr.interface_id = 'S';
|
||||
ioctl_req->hdr.cmd_len = elem->out_sg[1].iov_len;
|
||||
ioctl_req->hdr.cmdp = elem->out_sg[1].iov_base;
|
||||
ioctl_req->hdr.dxfer_len = 0;
|
||||
|
||||
if (elem->out_num > 2) {
|
||||
/*
|
||||
* If there are more than the minimally required 2 output segments
|
||||
* there is write payload starting from the third iovec.
|
||||
*/
|
||||
hdr.dxfer_direction = SG_DXFER_TO_DEV;
|
||||
hdr.iovec_count = elem->out_num - 2;
|
||||
ioctl_req->hdr.dxfer_direction = SG_DXFER_TO_DEV;
|
||||
ioctl_req->hdr.iovec_count = elem->out_num - 2;
|
||||
|
||||
for (i = 0; i < hdr.iovec_count; i++)
|
||||
hdr.dxfer_len += elem->out_sg[i + 2].iov_len;
|
||||
for (i = 0; i < ioctl_req->hdr.iovec_count; i++) {
|
||||
ioctl_req->hdr.dxfer_len += elem->out_sg[i + 2].iov_len;
|
||||
}
|
||||
|
||||
hdr.dxferp = elem->out_sg + 2;
|
||||
ioctl_req->hdr.dxferp = elem->out_sg + 2;
|
||||
|
||||
} else if (elem->in_num > 3) {
|
||||
/*
|
||||
* If we have more than 3 input segments the guest wants to actually
|
||||
* read data.
|
||||
*/
|
||||
hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
hdr.iovec_count = elem->in_num - 3;
|
||||
for (i = 0; i < hdr.iovec_count; i++)
|
||||
hdr.dxfer_len += elem->in_sg[i].iov_len;
|
||||
ioctl_req->hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
ioctl_req->hdr.iovec_count = elem->in_num - 3;
|
||||
for (i = 0; i < ioctl_req->hdr.iovec_count; i++) {
|
||||
ioctl_req->hdr.dxfer_len += elem->in_sg[i].iov_len;
|
||||
}
|
||||
|
||||
hdr.dxferp = elem->in_sg;
|
||||
ioctl_req->hdr.dxferp = elem->in_sg;
|
||||
} else {
|
||||
/*
|
||||
* Some SCSI commands don't actually transfer any data.
|
||||
*/
|
||||
hdr.dxfer_direction = SG_DXFER_NONE;
|
||||
ioctl_req->hdr.dxfer_direction = SG_DXFER_NONE;
|
||||
}
|
||||
|
||||
hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base;
|
||||
hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len;
|
||||
ioctl_req->hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base;
|
||||
ioctl_req->hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len;
|
||||
|
||||
status = blk_ioctl(blk->blk, SG_IO, &hdr);
|
||||
if (status) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi)
|
||||
* clear the masked_status field [hence status gets cleared too, see
|
||||
* block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED
|
||||
* status has occurred. However they do set DRIVER_SENSE in driver_status
|
||||
* field. Also a (sb_len_wr > 0) indicates there is a sense buffer.
|
||||
*/
|
||||
if (hdr.status == 0 && hdr.sb_len_wr > 0) {
|
||||
hdr.status = CHECK_CONDITION;
|
||||
}
|
||||
|
||||
virtio_stl_p(vdev, &scsi->errors,
|
||||
hdr.status | (hdr.msg_status << 8) |
|
||||
(hdr.host_status << 16) | (hdr.driver_status << 24));
|
||||
virtio_stl_p(vdev, &scsi->residual, hdr.resid);
|
||||
virtio_stl_p(vdev, &scsi->sense_len, hdr.sb_len_wr);
|
||||
virtio_stl_p(vdev, &scsi->data_len, hdr.dxfer_len);
|
||||
|
||||
return status;
|
||||
blk_aio_ioctl(blk->blk, SG_IO, &ioctl_req->hdr,
|
||||
virtio_blk_ioctl_complete, ioctl_req);
|
||||
return -EINPROGRESS;
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
|
@ -252,9 +284,11 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
|||
{
|
||||
int status;
|
||||
|
||||
status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
|
||||
virtio_blk_req_complete(req, status);
|
||||
virtio_blk_free_request(req);
|
||||
status = virtio_blk_handle_scsi_req(req);
|
||||
if (status != -EINPROGRESS) {
|
||||
virtio_blk_req_complete(req, status);
|
||||
virtio_blk_free_request(req);
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb)
|
||||
|
|
|
@ -339,13 +339,13 @@ struct BlockDriverState {
|
|||
* regarding this BDS's context */
|
||||
QLIST_HEAD(, BdrvAioNotifier) aio_notifiers;
|
||||
|
||||
char filename[1024];
|
||||
char backing_file[1024]; /* if non zero, the image is a diff of
|
||||
this file image */
|
||||
char filename[PATH_MAX];
|
||||
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
|
||||
this file image */
|
||||
char backing_format[16]; /* if non-zero and backing_file exists */
|
||||
|
||||
QDict *full_open_options;
|
||||
char exact_filename[1024];
|
||||
char exact_filename[PATH_MAX];
|
||||
|
||||
BlockDriverState *backing_hd;
|
||||
BlockDriverState *file;
|
||||
|
|
|
@ -153,9 +153,6 @@ VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s);
|
|||
|
||||
void virtio_blk_free_request(VirtIOBlockReq *req);
|
||||
|
||||
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
|
||||
VirtQueueElement *elem);
|
||||
|
||||
void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb);
|
||||
|
||||
void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb);
|
||||
|
|
|
@ -2556,7 +2556,7 @@ static int img_rebase(int argc, char **argv)
|
|||
|
||||
/* For safe rebasing we need to compare old and new backing file */
|
||||
if (!unsafe) {
|
||||
char backing_name[1024];
|
||||
char backing_name[PATH_MAX];
|
||||
|
||||
blk_old_backing = blk_new_with_bs("old_backing", &error_abort);
|
||||
bs_old_backing = blk_bs(blk_old_backing);
|
||||
|
@ -2614,7 +2614,7 @@ static int img_rebase(int argc, char **argv)
|
|||
}
|
||||
old_backing_num_sectors = bdrv_nb_sectors(bs_old_backing);
|
||||
if (old_backing_num_sectors < 0) {
|
||||
char backing_name[1024];
|
||||
char backing_name[PATH_MAX];
|
||||
|
||||
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
|
||||
error_report("Could not get size of '%s': %s",
|
||||
|
|
|
@ -186,6 +186,12 @@ $QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
|
|||
poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x2a\x00"
|
||||
$QEMU_IO -c "read 0 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# Test how well zero cluster expansion can cope with this
|
||||
_make_test_img 64M
|
||||
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x2a\x00"
|
||||
$QEMU_IMG amend -o compat=0.10 "$TEST_IMG"
|
||||
|
||||
echo
|
||||
echo "=== Testing unaligned L2 entry ==="
|
||||
echo
|
||||
|
@ -194,6 +200,15 @@ $QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
|
|||
poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x00"
|
||||
$QEMU_IO -c "read 0 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "=== Testing unaligned pre-allocated zero cluster ==="
|
||||
echo
|
||||
_make_test_img 64M
|
||||
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x01"
|
||||
# zero cluster expansion
|
||||
$QEMU_IMG amend -o compat=0.10 "$TEST_IMG"
|
||||
|
||||
echo
|
||||
echo "=== Testing unaligned reftable entry ==="
|
||||
echo
|
||||
|
|
|
@ -123,6 +123,11 @@ wrote 65536/65536 bytes at offset 0
|
|||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed
|
||||
read failed: Input/output error
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed
|
||||
qemu-img: Error while amending options: Input/output error
|
||||
|
||||
=== Testing unaligned L2 entry ===
|
||||
|
||||
|
@ -132,6 +137,14 @@ wrote 65536/65536 bytes at offset 0
|
|||
qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
|
||||
read failed: Input/output error
|
||||
|
||||
=== Testing unaligned pre-allocated zero cluster ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
|
||||
qemu-img: Error while amending options: Input/output error
|
||||
|
||||
=== Testing unaligned reftable entry ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
|
|
@ -54,7 +54,15 @@ $QEMU_IO -r -c "read -pP 0x96 33M 33M" "$TEST_IMG" | _filter_qemu_io
|
|||
|
||||
echo
|
||||
echo "=== Verify pattern 0x00, 66M - 1024M ==="
|
||||
$QEMU_IO -r -c "read -pP 0x00 66M 958M" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -r -c "read -pP 0x00 66M 62M" \
|
||||
-c "read -pP 0x00 128M 128M" \
|
||||
-c "read -pP 0x00 256M 128M" \
|
||||
-c "read -pP 0x00 384M 128M" \
|
||||
-c "read -pP 0x00 512M 128M" \
|
||||
-c "read -pP 0x00 640M 128M" \
|
||||
-c "read -pP 0x00 768M 128M" \
|
||||
-c "read -pP 0x00 896M 128M" \
|
||||
"$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "=== Verify pattern write, 0xc3 99M-157M ==="
|
||||
|
@ -63,7 +71,14 @@ $QEMU_IO -c "write -pP 0xc3 99M 58M" "$TEST_IMG" | _filter_qemu_io
|
|||
$QEMU_IO -c "read -pP 0xa5 0 33M" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -pP 0x96 33M 33M" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -pP 0x00 66M 33M" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -pP 0x00 157MM 867MM" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -pP 0x00 157M 99M" \
|
||||
-c "read -pP 0x00 256M 128M" \
|
||||
-c "read -pP 0x00 384M 128M" \
|
||||
-c "read -pP 0x00 512M 128M" \
|
||||
-c "read -pP 0x00 640M 128M" \
|
||||
-c "read -pP 0x00 768M 128M" \
|
||||
-c "read -pP 0x00 896M 128M" \
|
||||
"$TEST_IMG" | _filter_qemu_io
|
||||
# now verify what we should have actually written
|
||||
$QEMU_IO -c "read -pP 0xc3 99M 58M" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
|
|
|
@ -9,8 +9,22 @@ read 34603008/34603008 bytes at offset 34603008
|
|||
33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Verify pattern 0x00, 66M - 1024M ===
|
||||
read 1004535808/1004535808 bytes at offset 69206016
|
||||
958 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65011712/65011712 bytes at offset 69206016
|
||||
62 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 134217728
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 268435456
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 402653184
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 536870912
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 671088640
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 805306368
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 939524096
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Verify pattern write, 0xc3 99M-157M ===
|
||||
wrote 60817408/60817408 bytes at offset 103809024
|
||||
|
@ -21,8 +35,20 @@ read 34603008/34603008 bytes at offset 34603008
|
|||
33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 34603008/34603008 bytes at offset 69206016
|
||||
33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 909115392/909115392 bytes at offset 164626432
|
||||
867 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 103809024/103809024 bytes at offset 164626432
|
||||
99 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 268435456
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 402653184
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 536870912
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 671088640
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 805306368
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 134217728/134217728 bytes at offset 939524096
|
||||
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 60817408/60817408 bytes at offset 103809024
|
||||
58 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
*** done
|
||||
|
|
Loading…
Reference in New Issue