[Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
this patch adds iscsi_truncate which effectively allows for online resizing of iscsi volumes. for this to work you have to resize the volume on your storage and then call block_resize command in qemu which will issue a readcapacity16 to update the capacity. Signed-off-by: Peter Lieven p...@kamp.de --- block/iscsi.c | 74 + 1 file changed, 74 insertions(+) diff --git a/block/iscsi.c b/block/iscsi.c index deb3b68..37f12b3 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -67,6 +67,12 @@ typedef struct IscsiAIOCB { #endif } IscsiAIOCB; +struct IscsiTask { +IscsiLun *iscsilun; +int status; +int complete; +}; + #define NOP_INTERVAL 5000 #define MAX_NOP_FAILURES 3 @@ -700,6 +706,73 @@ iscsi_getlength(BlockDriverState *bs) return len; } +static void +iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, +void *command_data, void *opaque) +{ +struct IscsiTask *itask = opaque; +struct scsi_readcapacity16 *rc16; +struct scsi_task *task = command_data; + +if (status != 0) { +error_report(iSCSI: Failed to read capacity of iSCSI lun. %s, + iscsi_get_error(iscsi)); +itask-status = 1; +itask-complete = 1; +scsi_free_scsi_task(task); +return; +} + +rc16 = scsi_datain_unmarshall(task); +if (rc16 == NULL) { +error_report(iSCSI: Failed to unmarshall readcapacity16 data.); +itask-status = 1; +itask-complete = 1; +scsi_free_scsi_task(task); +return; +} + +itask-iscsilun-block_size = rc16-block_length; +itask-iscsilun-num_blocks = rc16-returned_lba + 1; + +itask-status = 0; +itask-complete = 1; +scsi_free_scsi_task(task); +} + +static int iscsi_truncate(BlockDriverState *bs, int64_t offset) +{ +IscsiLun *iscsilun = bs-opaque; +struct IscsiTask itask; +struct scsi_task *task = NULL; + +if (iscsilun-type != TYPE_DISK) { +return -ENOTSUP; +} + +itask.iscsilun = iscsilun; +itask.status = 0; +itask.complete = 0; + +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); +if (task == NULL) { + error_report(iSCSI: failed to send readcapacity16 command.); + return -EINVAL; +} + +while (!itask.complete) { +iscsi_set_events(iscsilun); +qemu_aio_wait(); +} + +if (offset iscsi_getlength(bs)) { +return -EINVAL; +} + +return 0; +} + static int parse_chap(struct iscsi_context *iscsi, const char *target) { QemuOptsList *list; @@ -1093,6 +1166,7 @@ static BlockDriver bdrv_iscsi = { .create_options = iscsi_create_options, .bdrv_getlength = iscsi_getlength, +.bdrv_truncate = iscsi_truncate, .bdrv_aio_readv = iscsi_aio_readv, .bdrv_aio_writev = iscsi_aio_writev, -- 1.7.9.5
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
Il 15/02/2013 11:58, Peter Lieven ha scritto: this patch adds iscsi_truncate which effectively allows for online resizing of iscsi volumes. for this to work you have to resize the volume on your storage and then call block_resize command in qemu which will issue a readcapacity16 to update the capacity. Signed-off-by: Peter Lieven p...@kamp.de --- block/iscsi.c | 74 + 1 file changed, 74 insertions(+) diff --git a/block/iscsi.c b/block/iscsi.c index deb3b68..37f12b3 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -67,6 +67,12 @@ typedef struct IscsiAIOCB { #endif } IscsiAIOCB; +struct IscsiTask { +IscsiLun *iscsilun; +int status; +int complete; +}; + #define NOP_INTERVAL 5000 #define MAX_NOP_FAILURES 3 @@ -700,6 +706,73 @@ iscsi_getlength(BlockDriverState *bs) return len; } +static void +iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, +void *command_data, void *opaque) +{ +struct IscsiTask *itask = opaque; +struct scsi_readcapacity16 *rc16; +struct scsi_task *task = command_data; + +if (status != 0) { +error_report(iSCSI: Failed to read capacity of iSCSI lun. %s, + iscsi_get_error(iscsi)); +itask-status = 1; +itask-complete = 1; +scsi_free_scsi_task(task); +return; +} + +rc16 = scsi_datain_unmarshall(task); +if (rc16 == NULL) { +error_report(iSCSI: Failed to unmarshall readcapacity16 data.); +itask-status = 1; +itask-complete = 1; +scsi_free_scsi_task(task); +return; +} + +itask-iscsilun-block_size = rc16-block_length; +itask-iscsilun-num_blocks = rc16-returned_lba + 1; + +itask-status = 0; +itask-complete = 1; +scsi_free_scsi_task(task); +} + +static int iscsi_truncate(BlockDriverState *bs, int64_t offset) +{ +IscsiLun *iscsilun = bs-opaque; +struct IscsiTask itask; +struct scsi_task *task = NULL; + +if (iscsilun-type != TYPE_DISK) { +return -ENOTSUP; +} + +itask.iscsilun = iscsilun; +itask.status = 0; +itask.complete = 0; + +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); You can use iscsi_readcapacity16_sync. In fact, you probably should extract code from iscsi_open and reuse it here. Paolo +if (task == NULL) { + error_report(iSCSI: failed to send readcapacity16 command.); + return -EINVAL; +} + +while (!itask.complete) { +iscsi_set_events(iscsilun); +qemu_aio_wait(); +} + +if (offset iscsi_getlength(bs)) { +return -EINVAL; +} + +return 0; +} + static int parse_chap(struct iscsi_context *iscsi, const char *target) { QemuOptsList *list; @@ -1093,6 +1166,7 @@ static BlockDriver bdrv_iscsi = { .create_options = iscsi_create_options, .bdrv_getlength = iscsi_getlength, +.bdrv_truncate = iscsi_truncate, .bdrv_aio_readv = iscsi_aio_readv, .bdrv_aio_writev = iscsi_aio_writev,
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
On 15.02.2013 12:09, Paolo Bonzini wrote: Il 15/02/2013 11:58, Peter Lieven ha scritto: this patch adds iscsi_truncate which effectively allows for online resizing of iscsi volumes. for this to work you have to resize the volume on your storage and then call block_resize command in qemu which will issue a readcapacity16 to update the capacity. Signed-off-by: Peter Lieven p...@kamp.de --- block/iscsi.c | 74 + 1 file changed, 74 insertions(+) diff --git a/block/iscsi.c b/block/iscsi.c index deb3b68..37f12b3 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -67,6 +67,12 @@ typedef struct IscsiAIOCB { #endif } IscsiAIOCB; +struct IscsiTask { +IscsiLun *iscsilun; +int status; +int complete; +}; + #define NOP_INTERVAL 5000 #define MAX_NOP_FAILURES 3 @@ -700,6 +706,73 @@ iscsi_getlength(BlockDriverState *bs) return len; } +static void +iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status, +void *command_data, void *opaque) +{ +struct IscsiTask *itask = opaque; +struct scsi_readcapacity16 *rc16; +struct scsi_task *task = command_data; + +if (status != 0) { +error_report(iSCSI: Failed to read capacity of iSCSI lun. %s, + iscsi_get_error(iscsi)); +itask-status = 1; +itask-complete = 1; +scsi_free_scsi_task(task); +return; +} + +rc16 = scsi_datain_unmarshall(task); +if (rc16 == NULL) { +error_report(iSCSI: Failed to unmarshall readcapacity16 data.); +itask-status = 1; +itask-complete = 1; +scsi_free_scsi_task(task); +return; +} + +itask-iscsilun-block_size = rc16-block_length; +itask-iscsilun-num_blocks = rc16-returned_lba + 1; + +itask-status = 0; +itask-complete = 1; +scsi_free_scsi_task(task); +} + +static int iscsi_truncate(BlockDriverState *bs, int64_t offset) +{ +IscsiLun *iscsilun = bs-opaque; +struct IscsiTask itask; +struct scsi_task *task = NULL; + +if (iscsilun-type != TYPE_DISK) { +return -ENOTSUP; +} + +itask.iscsilun = iscsilun; +itask.status = 0; +itask.complete = 0; + +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); You can use iscsi_readcapacity16_sync. In fact, you probably should extract code from iscsi_open and reuse it here. Thats not possible afaik. Mixing sync and async commands in libiscsi is a very bad thing. It will leed to nested event loops. Peter Paolo +if (task == NULL) { + error_report(iSCSI: failed to send readcapacity16 command.); + return -EINVAL; +} + +while (!itask.complete) { +iscsi_set_events(iscsilun); +qemu_aio_wait(); +} + +if (offset iscsi_getlength(bs)) { +return -EINVAL; +} + +return 0; +} + static int parse_chap(struct iscsi_context *iscsi, const char *target) { QemuOptsList *list; @@ -1093,6 +1166,7 @@ static BlockDriver bdrv_iscsi = { .create_options = iscsi_create_options, .bdrv_getlength = iscsi_getlength, +.bdrv_truncate = iscsi_truncate, .bdrv_aio_readv = iscsi_aio_readv, .bdrv_aio_writev = iscsi_aio_writev,
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
Il 15/02/2013 12:18, Peter Lieven ha scritto: +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); You can use iscsi_readcapacity16_sync. In fact, you probably should extract code from iscsi_open and reuse it here. Thats not possible afaik. Mixing sync and async commands in libiscsi is a very bad thing. It will leed to nested event loops. Ah, I thought qmp_block_resize did a bdrv_drain_all before calling bdrv_truncate. Maybe it should. Kevin, what do you think? Paolo
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
Am 15.02.2013 um 12:54 schrieb Paolo Bonzini pbonz...@redhat.com: Il 15/02/2013 12:18, Peter Lieven ha scritto: +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); You can use iscsi_readcapacity16_sync. In fact, you probably should extract code from iscsi_open and reuse it here. Thats not possible afaik. Mixing sync and async commands in libiscsi is a very bad thing. It will leed to nested event loops. Ah, I thought qmp_block_resize did a bdrv_drain_all before calling bdrv_truncate. Ah ok. In this special case it might be ok. We should ask Ronnie. What must not happen is that the sync task loop calls the async callbacks. Peter Maybe it should. Kevin, what do you think? Paolo
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
On Fri, Feb 15, 2013 at 12:54:51PM +0100, Paolo Bonzini wrote: Il 15/02/2013 12:18, Peter Lieven ha scritto: +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); You can use iscsi_readcapacity16_sync. In fact, you probably should extract code from iscsi_open and reuse it here. Thats not possible afaik. Mixing sync and async commands in libiscsi is a very bad thing. It will leed to nested event loops. Ah, I thought qmp_block_resize did a bdrv_drain_all before calling bdrv_truncate. Maybe it should. Kevin, what do you think? Probably. bdrv_truncate() invalidates the bdrv_check_request() result for in-flight requests, so there better be none. Kevin
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
Am 15.02.2013 um 13:18 schrieb Kevin Wolf kw...@redhat.com: On Fri, Feb 15, 2013 at 12:54:51PM +0100, Paolo Bonzini wrote: Il 15/02/2013 12:18, Peter Lieven ha scritto: +task = iscsi_readcapacity16_task(iscsilun-iscsi, iscsilun-lun, + iscsi_readcapacity16_cb, itask); You can use iscsi_readcapacity16_sync. In fact, you probably should extract code from iscsi_open and reuse it here. Thats not possible afaik. Mixing sync and async commands in libiscsi is a very bad thing. It will leed to nested event loops. Ah, I thought qmp_block_resize did a bdrv_drain_all before calling bdrv_truncate. Maybe it should. Kevin, what do you think? Probably. bdrv_truncate() invalidates the bdrv_check_request() result for in-flight requests, so there better be none. So you would call brdv_drain_all() before calling brdv_truncate and then use a sync iscsi call? Peter Kevin
Re: [Qemu-devel] [PATCH] iscsi: add iscsi_truncate support
Il 15/02/2013 13:36, Peter Lieven ha scritto: Ah, I thought qmp_block_resize did a bdrv_drain_all before calling bdrv_truncate. Maybe it should. Kevin, what do you think? Probably. bdrv_truncate() invalidates the bdrv_check_request() result for in-flight requests, so there better be none. So you would call brdv_drain_all() before calling brdv_truncate and then use a sync iscsi call? Yes, please. Paolo