ide/ahci: Use universal DMA helper functions
[qemu/opensuse.git] / block / iscsi.c
blob22888a0845de653d9bde09a67b3c8eb08b701ad5
1 /*
2 * QEMU Block driver for iSCSI images
4 * Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "config-host.h"
27 #include <poll.h>
28 #include <arpa/inet.h>
29 #include "qemu-common.h"
30 #include "qemu-error.h"
31 #include "block_int.h"
32 #include "trace.h"
33 #include "hw/scsi-defs.h"
35 #include <iscsi/iscsi.h>
36 #include <iscsi/scsi-lowlevel.h>
39 typedef struct IscsiLun {
40 struct iscsi_context *iscsi;
41 int lun;
42 enum scsi_inquiry_peripheral_device_type type;
43 int block_size;
44 uint64_t num_blocks;
45 int events;
46 } IscsiLun;
48 typedef struct IscsiAIOCB {
49 BlockDriverAIOCB common;
50 QEMUIOVector *qiov;
51 QEMUBH *bh;
52 IscsiLun *iscsilun;
53 struct scsi_task *task;
54 uint8_t *buf;
55 int status;
56 int canceled;
57 size_t read_size;
58 size_t read_offset;
59 } IscsiAIOCB;
61 struct IscsiTask {
62 IscsiLun *iscsilun;
63 BlockDriverState *bs;
64 int status;
65 int complete;
68 static void
69 iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
70 void *private_data)
74 static void
75 iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
77 IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
78 IscsiLun *iscsilun = acb->iscsilun;
80 acb->common.cb(acb->common.opaque, -ECANCELED);
81 acb->canceled = 1;
83 /* send a task mgmt call to the target to cancel the task on the target */
84 iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
85 iscsi_abort_task_cb, NULL);
87 /* then also cancel the task locally in libiscsi */
88 iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task);
91 static AIOPool iscsi_aio_pool = {
92 .aiocb_size = sizeof(IscsiAIOCB),
93 .cancel = iscsi_aio_cancel,
97 static void iscsi_process_read(void *arg);
98 static void iscsi_process_write(void *arg);
100 static int iscsi_process_flush(void *arg)
102 IscsiLun *iscsilun = arg;
104 return iscsi_queue_length(iscsilun->iscsi) > 0;
107 static void
108 iscsi_set_events(IscsiLun *iscsilun)
110 struct iscsi_context *iscsi = iscsilun->iscsi;
111 int ev;
113 /* We always register a read handler. */
114 ev = POLLIN;
115 ev |= iscsi_which_events(iscsi);
116 if (ev != iscsilun->events) {
117 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
118 iscsi_process_read,
119 (ev & POLLOUT) ? iscsi_process_write : NULL,
120 iscsi_process_flush,
121 iscsilun);
125 /* If we just added an event, the callback might be delayed
126 * unless we call qemu_notify_event().
128 if (ev & ~iscsilun->events) {
129 qemu_notify_event();
131 iscsilun->events = ev;
134 static void
135 iscsi_process_read(void *arg)
137 IscsiLun *iscsilun = arg;
138 struct iscsi_context *iscsi = iscsilun->iscsi;
140 iscsi_service(iscsi, POLLIN);
141 iscsi_set_events(iscsilun);
144 static void
145 iscsi_process_write(void *arg)
147 IscsiLun *iscsilun = arg;
148 struct iscsi_context *iscsi = iscsilun->iscsi;
150 iscsi_service(iscsi, POLLOUT);
151 iscsi_set_events(iscsilun);
155 static int
156 iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb)
158 acb->bh = qemu_bh_new(cb, acb);
159 if (!acb->bh) {
160 error_report("oom: could not create iscsi bh");
161 return -EIO;
164 qemu_bh_schedule(acb->bh);
165 return 0;
168 static void
169 iscsi_readv_writev_bh_cb(void *p)
171 IscsiAIOCB *acb = p;
173 qemu_bh_delete(acb->bh);
175 if (acb->canceled == 0) {
176 acb->common.cb(acb->common.opaque, acb->status);
179 qemu_aio_release(acb);
183 static void
184 iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
185 void *command_data, void *opaque)
187 IscsiAIOCB *acb = opaque;
189 trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
191 g_free(acb->buf);
193 if (acb->canceled != 0) {
194 qemu_aio_release(acb);
195 scsi_free_scsi_task(acb->task);
196 acb->task = NULL;
197 return;
200 acb->status = 0;
201 if (status < 0) {
202 error_report("Failed to write16 data to iSCSI lun. %s",
203 iscsi_get_error(iscsi));
204 acb->status = -EIO;
207 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
208 scsi_free_scsi_task(acb->task);
209 acb->task = NULL;
212 static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
214 return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
217 static BlockDriverAIOCB *
218 iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
219 QEMUIOVector *qiov, int nb_sectors,
220 BlockDriverCompletionFunc *cb,
221 void *opaque)
223 IscsiLun *iscsilun = bs->opaque;
224 struct iscsi_context *iscsi = iscsilun->iscsi;
225 IscsiAIOCB *acb;
226 size_t size;
227 uint32_t num_sectors;
228 uint64_t lba;
229 struct iscsi_data data;
231 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
232 trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
234 acb->iscsilun = iscsilun;
235 acb->qiov = qiov;
237 acb->canceled = 0;
239 /* XXX we should pass the iovec to write16 to avoid the extra copy */
240 /* this will allow us to get rid of 'buf' completely */
241 size = nb_sectors * BDRV_SECTOR_SIZE;
242 acb->buf = g_malloc(size);
243 qemu_iovec_to_buffer(acb->qiov, acb->buf);
246 acb->task = malloc(sizeof(struct scsi_task));
247 if (acb->task == NULL) {
248 error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
249 "command. %s", iscsi_get_error(iscsi));
250 qemu_aio_release(acb);
251 return NULL;
253 memset(acb->task, 0, sizeof(struct scsi_task));
255 acb->task->xfer_dir = SCSI_XFER_WRITE;
256 acb->task->cdb_size = 16;
257 acb->task->cdb[0] = 0x8a;
258 if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
259 /* set FUA on writes when cache mode is write through */
260 acb->task->cdb[1] |= 0x04;
262 lba = sector_qemu2lun(sector_num, iscsilun);
263 *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
264 *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
265 num_sectors = size / iscsilun->block_size;
266 *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
267 acb->task->expxferlen = size;
269 data.data = acb->buf;
270 data.size = size;
272 if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
273 iscsi_aio_write16_cb,
274 &data,
275 acb) != 0) {
276 scsi_free_scsi_task(acb->task);
277 g_free(acb->buf);
278 qemu_aio_release(acb);
279 return NULL;
282 iscsi_set_events(iscsilun);
284 return &acb->common;
287 static void
288 iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
289 void *command_data, void *opaque)
291 IscsiAIOCB *acb = opaque;
293 trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
295 if (acb->canceled != 0) {
296 qemu_aio_release(acb);
297 scsi_free_scsi_task(acb->task);
298 acb->task = NULL;
299 return;
302 acb->status = 0;
303 if (status != 0) {
304 error_report("Failed to read16 data from iSCSI lun. %s",
305 iscsi_get_error(iscsi));
306 acb->status = -EIO;
309 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
310 scsi_free_scsi_task(acb->task);
311 acb->task = NULL;
314 static BlockDriverAIOCB *
315 iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
316 QEMUIOVector *qiov, int nb_sectors,
317 BlockDriverCompletionFunc *cb,
318 void *opaque)
320 IscsiLun *iscsilun = bs->opaque;
321 struct iscsi_context *iscsi = iscsilun->iscsi;
322 IscsiAIOCB *acb;
323 size_t qemu_read_size;
324 int i;
325 uint64_t lba;
326 uint32_t num_sectors;
328 qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
330 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
331 trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
333 acb->iscsilun = iscsilun;
334 acb->qiov = qiov;
336 acb->canceled = 0;
337 acb->read_size = qemu_read_size;
338 acb->buf = NULL;
340 /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
341 * may be misaligned to the LUN, so we may need to read some extra
342 * data.
344 acb->read_offset = 0;
345 if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
346 uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;
348 acb->read_offset = bdrv_offset % iscsilun->block_size;
351 num_sectors = (qemu_read_size + iscsilun->block_size
352 + acb->read_offset - 1)
353 / iscsilun->block_size;
355 acb->task = malloc(sizeof(struct scsi_task));
356 if (acb->task == NULL) {
357 error_report("iSCSI: Failed to allocate task for scsi READ16 "
358 "command. %s", iscsi_get_error(iscsi));
359 qemu_aio_release(acb);
360 return NULL;
362 memset(acb->task, 0, sizeof(struct scsi_task));
364 acb->task->xfer_dir = SCSI_XFER_READ;
365 lba = sector_qemu2lun(sector_num, iscsilun);
366 acb->task->expxferlen = qemu_read_size;
368 switch (iscsilun->type) {
369 case TYPE_DISK:
370 acb->task->cdb_size = 16;
371 acb->task->cdb[0] = 0x88;
372 *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
373 *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
374 *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
375 break;
376 default:
377 acb->task->cdb_size = 10;
378 acb->task->cdb[0] = 0x28;
379 *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
380 *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
381 break;
384 if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
385 iscsi_aio_read16_cb,
386 NULL,
387 acb) != 0) {
388 scsi_free_scsi_task(acb->task);
389 qemu_aio_release(acb);
390 return NULL;
393 for (i = 0; i < acb->qiov->niov; i++) {
394 scsi_task_add_data_in_buffer(acb->task,
395 acb->qiov->iov[i].iov_len,
396 acb->qiov->iov[i].iov_base);
399 iscsi_set_events(iscsilun);
401 return &acb->common;
405 static void
406 iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
407 void *command_data, void *opaque)
409 IscsiAIOCB *acb = opaque;
411 if (acb->canceled != 0) {
412 qemu_aio_release(acb);
413 scsi_free_scsi_task(acb->task);
414 acb->task = NULL;
415 return;
418 acb->status = 0;
419 if (status < 0) {
420 error_report("Failed to sync10 data on iSCSI lun. %s",
421 iscsi_get_error(iscsi));
422 acb->status = -EIO;
425 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
426 scsi_free_scsi_task(acb->task);
427 acb->task = NULL;
430 static BlockDriverAIOCB *
431 iscsi_aio_flush(BlockDriverState *bs,
432 BlockDriverCompletionFunc *cb, void *opaque)
434 IscsiLun *iscsilun = bs->opaque;
435 struct iscsi_context *iscsi = iscsilun->iscsi;
436 IscsiAIOCB *acb;
438 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
440 acb->iscsilun = iscsilun;
441 acb->canceled = 0;
443 acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
444 0, 0, 0, 0,
445 iscsi_synccache10_cb,
446 acb);
447 if (acb->task == NULL) {
448 error_report("iSCSI: Failed to send synchronizecache10 command. %s",
449 iscsi_get_error(iscsi));
450 qemu_aio_release(acb);
451 return NULL;
454 iscsi_set_events(iscsilun);
456 return &acb->common;
459 static void
460 iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
461 void *command_data, void *opaque)
463 IscsiAIOCB *acb = opaque;
465 if (acb->canceled != 0) {
466 qemu_aio_release(acb);
467 scsi_free_scsi_task(acb->task);
468 acb->task = NULL;
469 return;
472 acb->status = 0;
473 if (status < 0) {
474 error_report("Failed to unmap data on iSCSI lun. %s",
475 iscsi_get_error(iscsi));
476 acb->status = -EIO;
479 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
480 scsi_free_scsi_task(acb->task);
481 acb->task = NULL;
484 static BlockDriverAIOCB *
485 iscsi_aio_discard(BlockDriverState *bs,
486 int64_t sector_num, int nb_sectors,
487 BlockDriverCompletionFunc *cb, void *opaque)
489 IscsiLun *iscsilun = bs->opaque;
490 struct iscsi_context *iscsi = iscsilun->iscsi;
491 IscsiAIOCB *acb;
492 struct unmap_list list[1];
494 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
496 acb->iscsilun = iscsilun;
497 acb->canceled = 0;
499 list[0].lba = sector_qemu2lun(sector_num, iscsilun);
500 list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
502 acb->task = iscsi_unmap_task(iscsi, iscsilun->lun,
503 0, 0, &list[0], 1,
504 iscsi_unmap_cb,
505 acb);
506 if (acb->task == NULL) {
507 error_report("iSCSI: Failed to send unmap command. %s",
508 iscsi_get_error(iscsi));
509 qemu_aio_release(acb);
510 return NULL;
513 iscsi_set_events(iscsilun);
515 return &acb->common;
518 static int64_t
519 iscsi_getlength(BlockDriverState *bs)
521 IscsiLun *iscsilun = bs->opaque;
522 int64_t len;
524 len = iscsilun->num_blocks;
525 len *= iscsilun->block_size;
527 return len;
530 static void
531 iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
532 void *command_data, void *opaque)
534 struct IscsiTask *itask = opaque;
535 struct scsi_readcapacity16 *rc16;
536 struct scsi_task *task = command_data;
538 if (status != 0) {
539 error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
540 iscsi_get_error(iscsi));
541 itask->status = 1;
542 itask->complete = 1;
543 scsi_free_scsi_task(task);
544 return;
547 rc16 = scsi_datain_unmarshall(task);
548 if (rc16 == NULL) {
549 error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
550 itask->status = 1;
551 itask->complete = 1;
552 scsi_free_scsi_task(task);
553 return;
556 itask->iscsilun->block_size = rc16->block_length;
557 itask->iscsilun->num_blocks = rc16->returned_lba + 1;
558 itask->bs->total_sectors = itask->iscsilun->num_blocks *
559 itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
561 itask->status = 0;
562 itask->complete = 1;
563 scsi_free_scsi_task(task);
566 static void
567 iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
568 void *command_data, void *opaque)
570 struct IscsiTask *itask = opaque;
571 struct scsi_readcapacity10 *rc10;
572 struct scsi_task *task = command_data;
574 if (status != 0) {
575 error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
576 iscsi_get_error(iscsi));
577 itask->status = 1;
578 itask->complete = 1;
579 scsi_free_scsi_task(task);
580 return;
583 rc10 = scsi_datain_unmarshall(task);
584 if (rc10 == NULL) {
585 error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
586 itask->status = 1;
587 itask->complete = 1;
588 scsi_free_scsi_task(task);
589 return;
592 itask->iscsilun->block_size = rc10->block_size;
593 itask->iscsilun->num_blocks = rc10->lba + 1;
594 itask->bs->total_sectors = itask->iscsilun->num_blocks *
595 itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
597 itask->status = 0;
598 itask->complete = 1;
599 scsi_free_scsi_task(task);
602 static void
603 iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
604 void *opaque)
606 struct IscsiTask *itask = opaque;
607 struct scsi_task *task = command_data;
608 struct scsi_inquiry_standard *inq;
610 if (status != 0) {
611 itask->status = 1;
612 itask->complete = 1;
613 scsi_free_scsi_task(task);
614 return;
617 inq = scsi_datain_unmarshall(task);
618 if (inq == NULL) {
619 error_report("iSCSI: Failed to unmarshall inquiry data.");
620 itask->status = 1;
621 itask->complete = 1;
622 scsi_free_scsi_task(task);
623 return;
626 itask->iscsilun->type = inq->periperal_device_type;
628 scsi_free_scsi_task(task);
630 switch (itask->iscsilun->type) {
631 case TYPE_DISK:
632 task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
633 iscsi_readcapacity16_cb, opaque);
634 if (task == NULL) {
635 error_report("iSCSI: failed to send readcapacity16 command.");
636 itask->status = 1;
637 itask->complete = 1;
638 return;
640 break;
641 case TYPE_ROM:
642 task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
643 0, 0,
644 iscsi_readcapacity10_cb, opaque);
645 if (task == NULL) {
646 error_report("iSCSI: failed to send readcapacity16 command.");
647 itask->status = 1;
648 itask->complete = 1;
649 return;
651 break;
652 default:
653 itask->status = 0;
654 itask->complete = 1;
658 static void
659 iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
660 void *opaque)
662 struct IscsiTask *itask = opaque;
663 struct scsi_task *task;
665 if (status != 0) {
666 itask->status = 1;
667 itask->complete = 1;
668 return;
671 task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
672 0, 0, 36,
673 iscsi_inquiry_cb, opaque);
674 if (task == NULL) {
675 error_report("iSCSI: failed to send inquiry command.");
676 itask->status = 1;
677 itask->complete = 1;
678 return;
682 static int parse_chap(struct iscsi_context *iscsi, const char *target)
684 QemuOptsList *list;
685 QemuOpts *opts;
686 const char *user = NULL;
687 const char *password = NULL;
689 list = qemu_find_opts("iscsi");
690 if (!list) {
691 return 0;
694 opts = qemu_opts_find(list, target);
695 if (opts == NULL) {
696 opts = QTAILQ_FIRST(&list->head);
697 if (!opts) {
698 return 0;
702 user = qemu_opt_get(opts, "user");
703 if (!user) {
704 return 0;
707 password = qemu_opt_get(opts, "password");
708 if (!password) {
709 error_report("CHAP username specified but no password was given");
710 return -1;
713 if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
714 error_report("Failed to set initiator username and password");
715 return -1;
718 return 0;
721 static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
723 QemuOptsList *list;
724 QemuOpts *opts;
725 const char *digest = NULL;
727 list = qemu_find_opts("iscsi");
728 if (!list) {
729 return;
732 opts = qemu_opts_find(list, target);
733 if (opts == NULL) {
734 opts = QTAILQ_FIRST(&list->head);
735 if (!opts) {
736 return;
740 digest = qemu_opt_get(opts, "header-digest");
741 if (!digest) {
742 return;
745 if (!strcmp(digest, "CRC32C")) {
746 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
747 } else if (!strcmp(digest, "NONE")) {
748 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
749 } else if (!strcmp(digest, "CRC32C-NONE")) {
750 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
751 } else if (!strcmp(digest, "NONE-CRC32C")) {
752 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
753 } else {
754 error_report("Invalid header-digest setting : %s", digest);
758 static char *parse_initiator_name(const char *target)
760 QemuOptsList *list;
761 QemuOpts *opts;
762 const char *name = NULL;
764 list = qemu_find_opts("iscsi");
765 if (!list) {
766 return g_strdup("iqn.2008-11.org.linux-kvm");
769 opts = qemu_opts_find(list, target);
770 if (opts == NULL) {
771 opts = QTAILQ_FIRST(&list->head);
772 if (!opts) {
773 return g_strdup("iqn.2008-11.org.linux-kvm");
777 name = qemu_opt_get(opts, "initiator-name");
778 if (!name) {
779 return g_strdup("iqn.2008-11.org.linux-kvm");
782 return g_strdup(name);
786 * We support iscsi url's on the form
787 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
789 static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
791 IscsiLun *iscsilun = bs->opaque;
792 struct iscsi_context *iscsi = NULL;
793 struct iscsi_url *iscsi_url = NULL;
794 struct IscsiTask task;
795 char *initiator_name = NULL;
796 int ret;
798 if ((BDRV_SECTOR_SIZE % 512) != 0) {
799 error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
800 "BDRV_SECTOR_SIZE(%lld) is not a multiple "
801 "of 512", BDRV_SECTOR_SIZE);
802 return -EINVAL;
805 iscsi_url = iscsi_parse_full_url(iscsi, filename);
806 if (iscsi_url == NULL) {
807 error_report("Failed to parse URL : %s %s", filename,
808 iscsi_get_error(iscsi));
809 ret = -EINVAL;
810 goto failed;
813 memset(iscsilun, 0, sizeof(IscsiLun));
815 initiator_name = parse_initiator_name(iscsi_url->target);
817 iscsi = iscsi_create_context(initiator_name);
818 if (iscsi == NULL) {
819 error_report("iSCSI: Failed to create iSCSI context.");
820 ret = -ENOMEM;
821 goto failed;
824 if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
825 error_report("iSCSI: Failed to set target name.");
826 ret = -EINVAL;
827 goto failed;
830 if (iscsi_url->user != NULL) {
831 ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
832 iscsi_url->passwd);
833 if (ret != 0) {
834 error_report("Failed to set initiator username and password");
835 ret = -EINVAL;
836 goto failed;
840 /* check if we got CHAP username/password via the options */
841 if (parse_chap(iscsi, iscsi_url->target) != 0) {
842 error_report("iSCSI: Failed to set CHAP user/password");
843 ret = -EINVAL;
844 goto failed;
847 if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
848 error_report("iSCSI: Failed to set session type to normal.");
849 ret = -EINVAL;
850 goto failed;
853 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
855 /* check if we got HEADER_DIGEST via the options */
856 parse_header_digest(iscsi, iscsi_url->target);
858 task.iscsilun = iscsilun;
859 task.status = 0;
860 task.complete = 0;
861 task.bs = bs;
863 iscsilun->iscsi = iscsi;
864 iscsilun->lun = iscsi_url->lun;
866 if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
867 iscsi_connect_cb, &task)
868 != 0) {
869 error_report("iSCSI: Failed to start async connect.");
870 ret = -EINVAL;
871 goto failed;
874 while (!task.complete) {
875 iscsi_set_events(iscsilun);
876 qemu_aio_wait();
878 if (task.status != 0) {
879 error_report("iSCSI: Failed to connect to LUN : %s",
880 iscsi_get_error(iscsi));
881 ret = -EINVAL;
882 goto failed;
885 if (iscsi_url != NULL) {
886 iscsi_destroy_url(iscsi_url);
888 return 0;
890 failed:
891 if (initiator_name != NULL) {
892 g_free(initiator_name);
894 if (iscsi_url != NULL) {
895 iscsi_destroy_url(iscsi_url);
897 if (iscsi != NULL) {
898 iscsi_destroy_context(iscsi);
900 memset(iscsilun, 0, sizeof(IscsiLun));
901 return ret;
904 static void iscsi_close(BlockDriverState *bs)
906 IscsiLun *iscsilun = bs->opaque;
907 struct iscsi_context *iscsi = iscsilun->iscsi;
909 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
910 iscsi_destroy_context(iscsi);
911 memset(iscsilun, 0, sizeof(IscsiLun));
914 static BlockDriver bdrv_iscsi = {
915 .format_name = "iscsi",
916 .protocol_name = "iscsi",
918 .instance_size = sizeof(IscsiLun),
919 .bdrv_file_open = iscsi_open,
920 .bdrv_close = iscsi_close,
922 .bdrv_getlength = iscsi_getlength,
924 .bdrv_aio_readv = iscsi_aio_readv,
925 .bdrv_aio_writev = iscsi_aio_writev,
926 .bdrv_aio_flush = iscsi_aio_flush,
928 .bdrv_aio_discard = iscsi_aio_discard,
931 static void iscsi_block_init(void)
933 bdrv_register(&bdrv_iscsi);
936 block_init(iscsi_block_init);