]> git.proxmox.com Git - qemu.git/blame - block/iscsi.c
consolidate qemu_iovec_copy() and qemu_iovec_concat() and make them consistent
[qemu.git] / block / iscsi.c
CommitLineData
c589b249
RS
1/*
2 * QEMU Block driver for iSCSI images
3 *
4 * Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
24
25#include "config-host.h"
26
27#include <poll.h>
f4dfa67f 28#include <arpa/inet.h>
c589b249
RS
29#include "qemu-common.h"
30#include "qemu-error.h"
31#include "block_int.h"
32#include "trace.h"
dbfff6d7 33#include "hw/scsi-defs.h"
c589b249
RS
34
35#include <iscsi/iscsi.h>
36#include <iscsi/scsi-lowlevel.h>
37
38
39typedef struct IscsiLun {
40 struct iscsi_context *iscsi;
41 int lun;
dbfff6d7 42 enum scsi_inquiry_peripheral_device_type type;
c589b249 43 int block_size;
c7b4a952 44 uint64_t num_blocks;
c9b9f682 45 int events;
c589b249
RS
46} IscsiLun;
47
48typedef 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;
60
61struct IscsiTask {
62 IscsiLun *iscsilun;
63 BlockDriverState *bs;
64 int status;
65 int complete;
66};
67
68static void
69iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
70 void *private_data)
71{
72}
73
74static void
75iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
76{
77 IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
78 IscsiLun *iscsilun = acb->iscsilun;
79
80 acb->common.cb(acb->common.opaque, -ECANCELED);
81 acb->canceled = 1;
82
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);
86
87 /* then also cancel the task locally in libiscsi */
88 iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task);
89}
90
91static AIOPool iscsi_aio_pool = {
92 .aiocb_size = sizeof(IscsiAIOCB),
93 .cancel = iscsi_aio_cancel,
94};
95
96
97static void iscsi_process_read(void *arg);
98static void iscsi_process_write(void *arg);
99
100static int iscsi_process_flush(void *arg)
101{
102 IscsiLun *iscsilun = arg;
103
104 return iscsi_queue_length(iscsilun->iscsi) > 0;
105}
106
107static void
108iscsi_set_events(IscsiLun *iscsilun)
109{
110 struct iscsi_context *iscsi = iscsilun->iscsi;
c9b9f682
RS
111 int ev;
112
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);
122
123 }
124
125 /* If we just added an event, the callback might be delayed
126 * unless we call qemu_notify_event().
127 */
128 if (ev & ~iscsilun->events) {
129 qemu_notify_event();
130 }
131 iscsilun->events = ev;
c589b249
RS
132}
133
134static void
135iscsi_process_read(void *arg)
136{
137 IscsiLun *iscsilun = arg;
138 struct iscsi_context *iscsi = iscsilun->iscsi;
139
140 iscsi_service(iscsi, POLLIN);
141 iscsi_set_events(iscsilun);
142}
143
144static void
145iscsi_process_write(void *arg)
146{
147 IscsiLun *iscsilun = arg;
148 struct iscsi_context *iscsi = iscsilun->iscsi;
149
150 iscsi_service(iscsi, POLLOUT);
151 iscsi_set_events(iscsilun);
152}
153
154
155static int
156iscsi_schedule_bh(QEMUBHFunc *cb, IscsiAIOCB *acb)
157{
158 acb->bh = qemu_bh_new(cb, acb);
159 if (!acb->bh) {
160 error_report("oom: could not create iscsi bh");
161 return -EIO;
162 }
163
164 qemu_bh_schedule(acb->bh);
165 return 0;
166}
167
168static void
169iscsi_readv_writev_bh_cb(void *p)
170{
171 IscsiAIOCB *acb = p;
172
173 qemu_bh_delete(acb->bh);
174
175 if (acb->canceled == 0) {
176 acb->common.cb(acb->common.opaque, acb->status);
177 }
178
179 qemu_aio_release(acb);
180}
181
182
183static void
f4dfa67f 184iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
185 void *command_data, void *opaque)
186{
187 IscsiAIOCB *acb = opaque;
188
f4dfa67f 189 trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
c589b249
RS
190
191 g_free(acb->buf);
192
193 if (acb->canceled != 0) {
194 qemu_aio_release(acb);
195 scsi_free_scsi_task(acb->task);
196 acb->task = NULL;
197 return;
198 }
199
200 acb->status = 0;
201 if (status < 0) {
f4dfa67f 202 error_report("Failed to write16 data to iSCSI lun. %s",
c589b249
RS
203 iscsi_get_error(iscsi));
204 acb->status = -EIO;
205 }
206
207 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
208 scsi_free_scsi_task(acb->task);
209 acb->task = NULL;
210}
211
212static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
213{
214 return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
215}
216
217static BlockDriverAIOCB *
218iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
219 QEMUIOVector *qiov, int nb_sectors,
220 BlockDriverCompletionFunc *cb,
221 void *opaque)
222{
223 IscsiLun *iscsilun = bs->opaque;
224 struct iscsi_context *iscsi = iscsilun->iscsi;
225 IscsiAIOCB *acb;
226 size_t size;
f4dfa67f
RS
227 uint32_t num_sectors;
228 uint64_t lba;
229 struct iscsi_data data;
c589b249
RS
230
231 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
232 trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
233
234 acb->iscsilun = iscsilun;
235 acb->qiov = qiov;
236
237 acb->canceled = 0;
238
f4dfa67f 239 /* XXX we should pass the iovec to write16 to avoid the extra copy */
c589b249
RS
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);
f4dfa67f
RS
244
245
246 acb->task = malloc(sizeof(struct scsi_task));
c589b249 247 if (acb->task == NULL) {
f4dfa67f
RS
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;
252 }
253 memset(acb->task, 0, sizeof(struct scsi_task));
254
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;
261 }
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;
268
269 data.data = acb->buf;
270 data.size = size;
271
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);
c589b249
RS
277 g_free(acb->buf);
278 qemu_aio_release(acb);
279 return NULL;
280 }
281
282 iscsi_set_events(iscsilun);
283
284 return &acb->common;
285}
286
287static void
f4dfa67f 288iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
289 void *command_data, void *opaque)
290{
291 IscsiAIOCB *acb = opaque;
292
f4dfa67f 293 trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
c589b249
RS
294
295 if (acb->canceled != 0) {
296 qemu_aio_release(acb);
297 scsi_free_scsi_task(acb->task);
298 acb->task = NULL;
299 return;
300 }
301
302 acb->status = 0;
303 if (status != 0) {
f4dfa67f 304 error_report("Failed to read16 data from iSCSI lun. %s",
c589b249
RS
305 iscsi_get_error(iscsi));
306 acb->status = -EIO;
307 }
308
309 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
310 scsi_free_scsi_task(acb->task);
311 acb->task = NULL;
312}
313
314static BlockDriverAIOCB *
315iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
316 QEMUIOVector *qiov, int nb_sectors,
317 BlockDriverCompletionFunc *cb,
318 void *opaque)
319{
320 IscsiLun *iscsilun = bs->opaque;
321 struct iscsi_context *iscsi = iscsilun->iscsi;
322 IscsiAIOCB *acb;
f4dfa67f 323 size_t qemu_read_size;
c589b249 324 int i;
f4dfa67f
RS
325 uint64_t lba;
326 uint32_t num_sectors;
c589b249
RS
327
328 qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
329
330 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
331 trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
332
333 acb->iscsilun = iscsilun;
334 acb->qiov = qiov;
335
336 acb->canceled = 0;
337 acb->read_size = qemu_read_size;
338 acb->buf = NULL;
339
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.
343 */
344 acb->read_offset = 0;
345 if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
346 uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;
347
348 acb->read_offset = bdrv_offset % iscsilun->block_size;
349 }
350
f4dfa67f
RS
351 num_sectors = (qemu_read_size + iscsilun->block_size
352 + acb->read_offset - 1)
353 / iscsilun->block_size;
354
355 acb->task = malloc(sizeof(struct scsi_task));
c589b249 356 if (acb->task == NULL) {
f4dfa67f
RS
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;
361 }
362 memset(acb->task, 0, sizeof(struct scsi_task));
363
364 acb->task->xfer_dir = SCSI_XFER_READ;
365 lba = sector_qemu2lun(sector_num, iscsilun);
366 acb->task->expxferlen = qemu_read_size;
367
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;
382 }
383
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);
c589b249
RS
389 qemu_aio_release(acb);
390 return NULL;
391 }
392
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);
397 }
398
399 iscsi_set_events(iscsilun);
400
401 return &acb->common;
402}
403
404
405static void
406iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
407 void *command_data, void *opaque)
408{
409 IscsiAIOCB *acb = opaque;
410
411 if (acb->canceled != 0) {
412 qemu_aio_release(acb);
413 scsi_free_scsi_task(acb->task);
414 acb->task = NULL;
415 return;
416 }
417
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;
423 }
424
425 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
426 scsi_free_scsi_task(acb->task);
427 acb->task = NULL;
428}
429
430static BlockDriverAIOCB *
431iscsi_aio_flush(BlockDriverState *bs,
432 BlockDriverCompletionFunc *cb, void *opaque)
433{
434 IscsiLun *iscsilun = bs->opaque;
435 struct iscsi_context *iscsi = iscsilun->iscsi;
436 IscsiAIOCB *acb;
437
438 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
439
440 acb->iscsilun = iscsilun;
441 acb->canceled = 0;
442
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;
452 }
453
454 iscsi_set_events(iscsilun);
455
456 return &acb->common;
457}
458
fa6acb0c
RS
459static void
460iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
461 void *command_data, void *opaque)
462{
463 IscsiAIOCB *acb = opaque;
464
465 if (acb->canceled != 0) {
466 qemu_aio_release(acb);
467 scsi_free_scsi_task(acb->task);
468 acb->task = NULL;
469 return;
470 }
471
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;
477 }
478
479 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
480 scsi_free_scsi_task(acb->task);
481 acb->task = NULL;
482}
483
484static BlockDriverAIOCB *
485iscsi_aio_discard(BlockDriverState *bs,
486 int64_t sector_num, int nb_sectors,
487 BlockDriverCompletionFunc *cb, void *opaque)
488{
489 IscsiLun *iscsilun = bs->opaque;
490 struct iscsi_context *iscsi = iscsilun->iscsi;
491 IscsiAIOCB *acb;
492 struct unmap_list list[1];
493
494 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
495
496 acb->iscsilun = iscsilun;
497 acb->canceled = 0;
498
499 list[0].lba = sector_qemu2lun(sector_num, iscsilun);
500 list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
501
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;
511 }
512
513 iscsi_set_events(iscsilun);
514
515 return &acb->common;
516}
517
c589b249
RS
518static int64_t
519iscsi_getlength(BlockDriverState *bs)
520{
521 IscsiLun *iscsilun = bs->opaque;
522 int64_t len;
523
524 len = iscsilun->num_blocks;
525 len *= iscsilun->block_size;
526
527 return len;
528}
529
530static void
fa6acb0c 531iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
532 void *command_data, void *opaque)
533{
534 struct IscsiTask *itask = opaque;
fa6acb0c 535 struct scsi_readcapacity16 *rc16;
c589b249
RS
536 struct scsi_task *task = command_data;
537
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;
545 }
546
fa6acb0c
RS
547 rc16 = scsi_datain_unmarshall(task);
548 if (rc16 == NULL) {
549 error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
c589b249
RS
550 itask->status = 1;
551 itask->complete = 1;
552 scsi_free_scsi_task(task);
553 return;
554 }
555
fa6acb0c
RS
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 ;
c589b249
RS
560
561 itask->status = 0;
562 itask->complete = 1;
563 scsi_free_scsi_task(task);
564}
565
6bcd1346
RS
566static void
567iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
568 void *command_data, void *opaque)
569{
570 struct IscsiTask *itask = opaque;
571 struct scsi_readcapacity10 *rc10;
572 struct scsi_task *task = command_data;
573
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;
581 }
582
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;
590 }
591
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 ;
596
597 itask->status = 0;
598 itask->complete = 1;
599 scsi_free_scsi_task(task);
600}
601
c589b249 602static void
dbfff6d7 603iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
c589b249
RS
604 void *opaque)
605{
606 struct IscsiTask *itask = opaque;
dbfff6d7
RS
607 struct scsi_task *task = command_data;
608 struct scsi_inquiry_standard *inq;
c589b249
RS
609
610 if (status != 0) {
611 itask->status = 1;
612 itask->complete = 1;
dbfff6d7 613 scsi_free_scsi_task(task);
c589b249
RS
614 return;
615 }
616
dbfff6d7
RS
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;
624 }
625
626 itask->iscsilun->type = inq->periperal_device_type;
627
628 scsi_free_scsi_task(task);
629
6bcd1346
RS
630 switch (itask->iscsilun->type) {
631 case TYPE_DISK:
632 task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
fa6acb0c 633 iscsi_readcapacity16_cb, opaque);
6bcd1346
RS
634 if (task == NULL) {
635 error_report("iSCSI: failed to send readcapacity16 command.");
636 itask->status = 1;
637 itask->complete = 1;
638 return;
639 }
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;
650 }
651 break;
652 default:
653 itask->status = 0;
c589b249 654 itask->complete = 1;
c589b249
RS
655 }
656}
657
dbfff6d7
RS
658static void
659iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
660 void *opaque)
661{
662 struct IscsiTask *itask = opaque;
663 struct scsi_task *task;
664
665 if (status != 0) {
666 itask->status = 1;
667 itask->complete = 1;
668 return;
669 }
670
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;
679 }
680}
681
f9dadc98
RS
682static int parse_chap(struct iscsi_context *iscsi, const char *target)
683{
684 QemuOptsList *list;
685 QemuOpts *opts;
686 const char *user = NULL;
687 const char *password = NULL;
688
689 list = qemu_find_opts("iscsi");
690 if (!list) {
691 return 0;
692 }
693
694 opts = qemu_opts_find(list, target);
695 if (opts == NULL) {
696 opts = QTAILQ_FIRST(&list->head);
697 if (!opts) {
698 return 0;
699 }
700 }
701
702 user = qemu_opt_get(opts, "user");
703 if (!user) {
704 return 0;
705 }
706
707 password = qemu_opt_get(opts, "password");
708 if (!password) {
709 error_report("CHAP username specified but no password was given");
710 return -1;
711 }
712
713 if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
714 error_report("Failed to set initiator username and password");
715 return -1;
716 }
717
718 return 0;
719}
720
721static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
722{
723 QemuOptsList *list;
724 QemuOpts *opts;
725 const char *digest = NULL;
726
727 list = qemu_find_opts("iscsi");
728 if (!list) {
729 return;
730 }
731
732 opts = qemu_opts_find(list, target);
733 if (opts == NULL) {
734 opts = QTAILQ_FIRST(&list->head);
735 if (!opts) {
736 return;
737 }
738 }
739
740 digest = qemu_opt_get(opts, "header-digest");
741 if (!digest) {
742 return;
743 }
744
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);
755 }
756}
757
758static char *parse_initiator_name(const char *target)
759{
760 QemuOptsList *list;
761 QemuOpts *opts;
762 const char *name = NULL;
763
764 list = qemu_find_opts("iscsi");
765 if (!list) {
766 return g_strdup("iqn.2008-11.org.linux-kvm");
767 }
768
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");
774 }
775 }
776
777 name = qemu_opt_get(opts, "initiator-name");
778 if (!name) {
779 return g_strdup("iqn.2008-11.org.linux-kvm");
780 }
781
782 return g_strdup(name);
783}
784
c589b249
RS
785/*
786 * We support iscsi url's on the form
787 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
788 */
789static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
790{
791 IscsiLun *iscsilun = bs->opaque;
792 struct iscsi_context *iscsi = NULL;
793 struct iscsi_url *iscsi_url = NULL;
794 struct IscsiTask task;
f9dadc98 795 char *initiator_name = NULL;
c589b249
RS
796 int ret;
797
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;
803 }
804
c589b249
RS
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;
811 }
812
f9dadc98
RS
813 memset(iscsilun, 0, sizeof(IscsiLun));
814
815 initiator_name = parse_initiator_name(iscsi_url->target);
816
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;
822 }
823
c589b249
RS
824 if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
825 error_report("iSCSI: Failed to set target name.");
826 ret = -EINVAL;
827 goto failed;
828 }
829
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;
837 }
838 }
f9dadc98
RS
839
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;
845 }
846
c589b249
RS
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;
851 }
852
853 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
854
f9dadc98
RS
855 /* check if we got HEADER_DIGEST via the options */
856 parse_header_digest(iscsi, iscsi_url->target);
857
c589b249
RS
858 task.iscsilun = iscsilun;
859 task.status = 0;
860 task.complete = 0;
861 task.bs = bs;
862
863 iscsilun->iscsi = iscsi;
864 iscsilun->lun = iscsi_url->lun;
865
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;
872 }
873
874 while (!task.complete) {
875 iscsi_set_events(iscsilun);
876 qemu_aio_wait();
877 }
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;
883 }
884
885 if (iscsi_url != NULL) {
886 iscsi_destroy_url(iscsi_url);
887 }
888 return 0;
889
890failed:
f9dadc98
RS
891 if (initiator_name != NULL) {
892 g_free(initiator_name);
893 }
c589b249
RS
894 if (iscsi_url != NULL) {
895 iscsi_destroy_url(iscsi_url);
896 }
897 if (iscsi != NULL) {
898 iscsi_destroy_context(iscsi);
899 }
900 memset(iscsilun, 0, sizeof(IscsiLun));
901 return ret;
902}
903
904static void iscsi_close(BlockDriverState *bs)
905{
906 IscsiLun *iscsilun = bs->opaque;
907 struct iscsi_context *iscsi = iscsilun->iscsi;
908
bafbd6a1 909 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
c589b249
RS
910 iscsi_destroy_context(iscsi);
911 memset(iscsilun, 0, sizeof(IscsiLun));
912}
913
914static BlockDriver bdrv_iscsi = {
915 .format_name = "iscsi",
916 .protocol_name = "iscsi",
917
918 .instance_size = sizeof(IscsiLun),
919 .bdrv_file_open = iscsi_open,
920 .bdrv_close = iscsi_close,
921
922 .bdrv_getlength = iscsi_getlength,
923
924 .bdrv_aio_readv = iscsi_aio_readv,
925 .bdrv_aio_writev = iscsi_aio_writev,
926 .bdrv_aio_flush = iscsi_aio_flush,
fa6acb0c
RS
927
928 .bdrv_aio_discard = iscsi_aio_discard,
c589b249
RS
929};
930
931static void iscsi_block_init(void)
932{
933 bdrv_register(&bdrv_iscsi);
934}
935
936block_init(iscsi_block_init);