diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/iscsi.c | 110 | ||||
-rw-r--r-- | block/sheepdog.c | 1 | ||||
-rw-r--r-- | block/vmdk.c | 58 |
3 files changed, 112 insertions, 57 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index 22888a084..c3d8db8b4 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -66,9 +66,43 @@ struct IscsiTask { }; static void +iscsi_bh_cb(void *p) +{ + IscsiAIOCB *acb = p; + + qemu_bh_delete(acb->bh); + + if (acb->canceled == 0) { + acb->common.cb(acb->common.opaque, acb->status); + } + + if (acb->task != NULL) { + scsi_free_scsi_task(acb->task); + acb->task = NULL; + } + + qemu_aio_release(acb); +} + +static void +iscsi_schedule_bh(IscsiAIOCB *acb) +{ + if (acb->bh) { + return; + } + acb->bh = qemu_bh_new(iscsi_bh_cb, acb); + qemu_bh_schedule(acb->bh); +} + + +static void iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) { + IscsiAIOCB *acb = private_data; + + acb->status = -ECANCELED; + iscsi_schedule_bh(acb); } static void @@ -77,15 +111,19 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb) IscsiAIOCB *acb = (IscsiAIOCB *)blockacb; IscsiLun *iscsilun = acb->iscsilun; - acb->common.cb(acb->common.opaque, -ECANCELED); + if (acb->status != -EINPROGRESS) { + return; + } + acb->canceled = 1; /* send a task mgmt call to the target to cancel the task on the target */ iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task, - iscsi_abort_task_cb, NULL); + iscsi_abort_task_cb, acb); - /* then also cancel the task locally in libiscsi */ - iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task); + while (acb->status == -EINPROGRESS) { + qemu_aio_wait(); + } } static AIOPool iscsi_aio_pool = { @@ -152,34 +190,6 @@ iscsi_process_write(void *arg) } -static int -iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb) -{ - acb->bh = qemu_bh_new(cb, acb); - if (!acb->bh) { - error_report("oom: could not create iscsi bh"); - return -EIO; - } - - qemu_bh_schedule(acb->bh); - return 0; -} - -static void -iscsi_readv_writev_bh_cb(void *p) -{ - IscsiAIOCB *acb = p; - - qemu_bh_delete(acb->bh); - - if (acb->canceled == 0) { - acb->common.cb(acb->common.opaque, acb->status); - } - - qemu_aio_release(acb); -} - - static void iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) @@ -191,9 +201,6 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, g_free(acb->buf); if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -204,9 +211,7 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; + iscsi_schedule_bh(acb); } static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun) @@ -235,6 +240,8 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, acb->qiov = qiov; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; /* XXX we should pass the iovec to write16 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ @@ -293,9 +300,6 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled); if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -306,9 +310,7 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; + iscsi_schedule_bh(acb); } static BlockDriverAIOCB * @@ -334,6 +336,8 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, acb->qiov = qiov; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->read_size = qemu_read_size; acb->buf = NULL; @@ -409,9 +413,6 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, IscsiAIOCB *acb = opaque; if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -422,9 +423,7 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; + iscsi_schedule_bh(acb); } static BlockDriverAIOCB * @@ -439,6 +438,8 @@ iscsi_aio_flush(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun, 0, 0, 0, 0, @@ -463,9 +464,6 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, IscsiAIOCB *acb = opaque; if (acb->canceled != 0) { - qemu_aio_release(acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; return; } @@ -476,9 +474,7 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status, acb->status = -EIO; } - iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb); - scsi_free_scsi_task(acb->task); - acb->task = NULL; + iscsi_schedule_bh(acb); } static BlockDriverAIOCB * @@ -495,6 +491,8 @@ iscsi_aio_discard(BlockDriverState *bs, acb->iscsilun = iscsilun; acb->canceled = 0; + acb->bh = NULL; + acb->status = -EINPROGRESS; list[0].lba = sector_qemu2lun(sector_num, iscsilun); list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size; diff --git a/block/sheepdog.c b/block/sheepdog.c index f46ca8fb6..36ff9d748 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -489,6 +489,7 @@ static int connect_to_sdog(const char *addr, const char *port) if (errno == EINTR) { goto reconnect; } + close(fd); break; } diff --git a/block/vmdk.c b/block/vmdk.c index 18e9b4caf..a55f75652 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -35,6 +35,7 @@ #define VMDK4_FLAG_RGD (1 << 1) #define VMDK4_FLAG_COMPRESS (1 << 16) #define VMDK4_FLAG_MARKER (1 << 17) +#define VMDK4_GD_AT_END 0xffffffffffffffffULL typedef struct { uint32_t version; @@ -57,8 +58,8 @@ typedef struct { int64_t desc_offset; int64_t desc_size; int32_t num_gtes_per_gte; - int64_t gd_offset; int64_t rgd_offset; + int64_t gd_offset; int64_t grain_offset; char filler[1]; char check_bytes[4]; @@ -115,6 +116,13 @@ typedef struct VmdkGrainMarker { uint8_t data[0]; } VmdkGrainMarker; +enum { + MARKER_END_OF_STREAM = 0, + MARKER_GRAIN_TABLE = 1, + MARKER_GRAIN_DIRECTORY = 2, + MARKER_FOOTER = 3, +}; + static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename) { uint32_t magic; @@ -451,6 +459,54 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, if (header.capacity == 0 && header.desc_offset) { return vmdk_open_desc_file(bs, flags, header.desc_offset << 9); } + + if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) { + /* + * The footer takes precedence over the header, so read it in. The + * footer starts at offset -1024 from the end: One sector for the + * footer, and another one for the end-of-stream marker. + */ + struct { + struct { + uint64_t val; + uint32_t size; + uint32_t type; + uint8_t pad[512 - 16]; + } QEMU_PACKED footer_marker; + + uint32_t magic; + VMDK4Header header; + uint8_t pad[512 - 4 - sizeof(VMDK4Header)]; + + struct { + uint64_t val; + uint32_t size; + uint32_t type; + uint8_t pad[512 - 16]; + } QEMU_PACKED eos_marker; + } QEMU_PACKED footer; + + ret = bdrv_pread(file, + bs->file->total_sectors * 512 - 1536, + &footer, sizeof(footer)); + if (ret < 0) { + return ret; + } + + /* Some sanity checks for the footer */ + if (be32_to_cpu(footer.magic) != VMDK4_MAGIC || + le32_to_cpu(footer.footer_marker.size) != 0 || + le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER || + le64_to_cpu(footer.eos_marker.val) != 0 || + le32_to_cpu(footer.eos_marker.size) != 0 || + le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM) + { + return -EINVAL; + } + + header = footer.header; + } + l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) * le64_to_cpu(header.granularity); if (l1_entry_sectors == 0) { |