]> git.proxmox.com Git - qemu.git/blame - block/iscsi.c
change qemu_iovec_to_buf() to match other to,from_buf functions
[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);
d5e6b161 243 qemu_iovec_to_buf(acb->qiov, 0, acb->buf, size);
f4dfa67f
RS
244
245 acb->task = malloc(sizeof(struct scsi_task));
c589b249 246 if (acb->task == NULL) {
f4dfa67f
RS
247 error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
248 "command. %s", iscsi_get_error(iscsi));
249 qemu_aio_release(acb);
250 return NULL;
251 }
252 memset(acb->task, 0, sizeof(struct scsi_task));
253
254 acb->task->xfer_dir = SCSI_XFER_WRITE;
255 acb->task->cdb_size = 16;
256 acb->task->cdb[0] = 0x8a;
257 if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
258 /* set FUA on writes when cache mode is write through */
259 acb->task->cdb[1] |= 0x04;
260 }
261 lba = sector_qemu2lun(sector_num, iscsilun);
262 *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
263 *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
264 num_sectors = size / iscsilun->block_size;
265 *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
266 acb->task->expxferlen = size;
267
268 data.data = acb->buf;
269 data.size = size;
270
271 if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
272 iscsi_aio_write16_cb,
273 &data,
274 acb) != 0) {
275 scsi_free_scsi_task(acb->task);
c589b249
RS
276 g_free(acb->buf);
277 qemu_aio_release(acb);
278 return NULL;
279 }
280
281 iscsi_set_events(iscsilun);
282
283 return &acb->common;
284}
285
286static void
f4dfa67f 287iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
288 void *command_data, void *opaque)
289{
290 IscsiAIOCB *acb = opaque;
291
f4dfa67f 292 trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
c589b249
RS
293
294 if (acb->canceled != 0) {
295 qemu_aio_release(acb);
296 scsi_free_scsi_task(acb->task);
297 acb->task = NULL;
298 return;
299 }
300
301 acb->status = 0;
302 if (status != 0) {
f4dfa67f 303 error_report("Failed to read16 data from iSCSI lun. %s",
c589b249
RS
304 iscsi_get_error(iscsi));
305 acb->status = -EIO;
306 }
307
308 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
309 scsi_free_scsi_task(acb->task);
310 acb->task = NULL;
311}
312
313static BlockDriverAIOCB *
314iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
315 QEMUIOVector *qiov, int nb_sectors,
316 BlockDriverCompletionFunc *cb,
317 void *opaque)
318{
319 IscsiLun *iscsilun = bs->opaque;
320 struct iscsi_context *iscsi = iscsilun->iscsi;
321 IscsiAIOCB *acb;
f4dfa67f 322 size_t qemu_read_size;
c589b249 323 int i;
f4dfa67f
RS
324 uint64_t lba;
325 uint32_t num_sectors;
c589b249
RS
326
327 qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
328
329 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
330 trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
331
332 acb->iscsilun = iscsilun;
333 acb->qiov = qiov;
334
335 acb->canceled = 0;
336 acb->read_size = qemu_read_size;
337 acb->buf = NULL;
338
339 /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
340 * may be misaligned to the LUN, so we may need to read some extra
341 * data.
342 */
343 acb->read_offset = 0;
344 if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
345 uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;
346
347 acb->read_offset = bdrv_offset % iscsilun->block_size;
348 }
349
f4dfa67f
RS
350 num_sectors = (qemu_read_size + iscsilun->block_size
351 + acb->read_offset - 1)
352 / iscsilun->block_size;
353
354 acb->task = malloc(sizeof(struct scsi_task));
c589b249 355 if (acb->task == NULL) {
f4dfa67f
RS
356 error_report("iSCSI: Failed to allocate task for scsi READ16 "
357 "command. %s", iscsi_get_error(iscsi));
358 qemu_aio_release(acb);
359 return NULL;
360 }
361 memset(acb->task, 0, sizeof(struct scsi_task));
362
363 acb->task->xfer_dir = SCSI_XFER_READ;
364 lba = sector_qemu2lun(sector_num, iscsilun);
365 acb->task->expxferlen = qemu_read_size;
366
367 switch (iscsilun->type) {
368 case TYPE_DISK:
369 acb->task->cdb_size = 16;
370 acb->task->cdb[0] = 0x88;
371 *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
372 *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
373 *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
374 break;
375 default:
376 acb->task->cdb_size = 10;
377 acb->task->cdb[0] = 0x28;
378 *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
379 *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
380 break;
381 }
382
383 if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
384 iscsi_aio_read16_cb,
385 NULL,
386 acb) != 0) {
387 scsi_free_scsi_task(acb->task);
c589b249
RS
388 qemu_aio_release(acb);
389 return NULL;
390 }
391
392 for (i = 0; i < acb->qiov->niov; i++) {
393 scsi_task_add_data_in_buffer(acb->task,
394 acb->qiov->iov[i].iov_len,
395 acb->qiov->iov[i].iov_base);
396 }
397
398 iscsi_set_events(iscsilun);
399
400 return &acb->common;
401}
402
403
404static void
405iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
406 void *command_data, void *opaque)
407{
408 IscsiAIOCB *acb = opaque;
409
410 if (acb->canceled != 0) {
411 qemu_aio_release(acb);
412 scsi_free_scsi_task(acb->task);
413 acb->task = NULL;
414 return;
415 }
416
417 acb->status = 0;
418 if (status < 0) {
419 error_report("Failed to sync10 data on iSCSI lun. %s",
420 iscsi_get_error(iscsi));
421 acb->status = -EIO;
422 }
423
424 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
425 scsi_free_scsi_task(acb->task);
426 acb->task = NULL;
427}
428
429static BlockDriverAIOCB *
430iscsi_aio_flush(BlockDriverState *bs,
431 BlockDriverCompletionFunc *cb, void *opaque)
432{
433 IscsiLun *iscsilun = bs->opaque;
434 struct iscsi_context *iscsi = iscsilun->iscsi;
435 IscsiAIOCB *acb;
436
437 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
438
439 acb->iscsilun = iscsilun;
440 acb->canceled = 0;
441
442 acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
443 0, 0, 0, 0,
444 iscsi_synccache10_cb,
445 acb);
446 if (acb->task == NULL) {
447 error_report("iSCSI: Failed to send synchronizecache10 command. %s",
448 iscsi_get_error(iscsi));
449 qemu_aio_release(acb);
450 return NULL;
451 }
452
453 iscsi_set_events(iscsilun);
454
455 return &acb->common;
456}
457
fa6acb0c
RS
458static void
459iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
460 void *command_data, void *opaque)
461{
462 IscsiAIOCB *acb = opaque;
463
464 if (acb->canceled != 0) {
465 qemu_aio_release(acb);
466 scsi_free_scsi_task(acb->task);
467 acb->task = NULL;
468 return;
469 }
470
471 acb->status = 0;
472 if (status < 0) {
473 error_report("Failed to unmap data on iSCSI lun. %s",
474 iscsi_get_error(iscsi));
475 acb->status = -EIO;
476 }
477
478 iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
479 scsi_free_scsi_task(acb->task);
480 acb->task = NULL;
481}
482
483static BlockDriverAIOCB *
484iscsi_aio_discard(BlockDriverState *bs,
485 int64_t sector_num, int nb_sectors,
486 BlockDriverCompletionFunc *cb, void *opaque)
487{
488 IscsiLun *iscsilun = bs->opaque;
489 struct iscsi_context *iscsi = iscsilun->iscsi;
490 IscsiAIOCB *acb;
491 struct unmap_list list[1];
492
493 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
494
495 acb->iscsilun = iscsilun;
496 acb->canceled = 0;
497
498 list[0].lba = sector_qemu2lun(sector_num, iscsilun);
499 list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
500
501 acb->task = iscsi_unmap_task(iscsi, iscsilun->lun,
502 0, 0, &list[0], 1,
503 iscsi_unmap_cb,
504 acb);
505 if (acb->task == NULL) {
506 error_report("iSCSI: Failed to send unmap command. %s",
507 iscsi_get_error(iscsi));
508 qemu_aio_release(acb);
509 return NULL;
510 }
511
512 iscsi_set_events(iscsilun);
513
514 return &acb->common;
515}
516
c589b249
RS
517static int64_t
518iscsi_getlength(BlockDriverState *bs)
519{
520 IscsiLun *iscsilun = bs->opaque;
521 int64_t len;
522
523 len = iscsilun->num_blocks;
524 len *= iscsilun->block_size;
525
526 return len;
527}
528
529static void
fa6acb0c 530iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
531 void *command_data, void *opaque)
532{
533 struct IscsiTask *itask = opaque;
fa6acb0c 534 struct scsi_readcapacity16 *rc16;
c589b249
RS
535 struct scsi_task *task = command_data;
536
537 if (status != 0) {
538 error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
539 iscsi_get_error(iscsi));
540 itask->status = 1;
541 itask->complete = 1;
542 scsi_free_scsi_task(task);
543 return;
544 }
545
fa6acb0c
RS
546 rc16 = scsi_datain_unmarshall(task);
547 if (rc16 == NULL) {
548 error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
c589b249
RS
549 itask->status = 1;
550 itask->complete = 1;
551 scsi_free_scsi_task(task);
552 return;
553 }
554
fa6acb0c
RS
555 itask->iscsilun->block_size = rc16->block_length;
556 itask->iscsilun->num_blocks = rc16->returned_lba + 1;
557 itask->bs->total_sectors = itask->iscsilun->num_blocks *
558 itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
c589b249
RS
559
560 itask->status = 0;
561 itask->complete = 1;
562 scsi_free_scsi_task(task);
563}
564
6bcd1346
RS
565static void
566iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
567 void *command_data, void *opaque)
568{
569 struct IscsiTask *itask = opaque;
570 struct scsi_readcapacity10 *rc10;
571 struct scsi_task *task = command_data;
572
573 if (status != 0) {
574 error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
575 iscsi_get_error(iscsi));
576 itask->status = 1;
577 itask->complete = 1;
578 scsi_free_scsi_task(task);
579 return;
580 }
581
582 rc10 = scsi_datain_unmarshall(task);
583 if (rc10 == NULL) {
584 error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
585 itask->status = 1;
586 itask->complete = 1;
587 scsi_free_scsi_task(task);
588 return;
589 }
590
591 itask->iscsilun->block_size = rc10->block_size;
592 itask->iscsilun->num_blocks = rc10->lba + 1;
593 itask->bs->total_sectors = itask->iscsilun->num_blocks *
594 itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
595
596 itask->status = 0;
597 itask->complete = 1;
598 scsi_free_scsi_task(task);
599}
600
c589b249 601static void
dbfff6d7 602iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
c589b249
RS
603 void *opaque)
604{
605 struct IscsiTask *itask = opaque;
dbfff6d7
RS
606 struct scsi_task *task = command_data;
607 struct scsi_inquiry_standard *inq;
c589b249
RS
608
609 if (status != 0) {
610 itask->status = 1;
611 itask->complete = 1;
dbfff6d7 612 scsi_free_scsi_task(task);
c589b249
RS
613 return;
614 }
615
dbfff6d7
RS
616 inq = scsi_datain_unmarshall(task);
617 if (inq == NULL) {
618 error_report("iSCSI: Failed to unmarshall inquiry data.");
619 itask->status = 1;
620 itask->complete = 1;
621 scsi_free_scsi_task(task);
622 return;
623 }
624
625 itask->iscsilun->type = inq->periperal_device_type;
626
627 scsi_free_scsi_task(task);
628
6bcd1346
RS
629 switch (itask->iscsilun->type) {
630 case TYPE_DISK:
631 task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
fa6acb0c 632 iscsi_readcapacity16_cb, opaque);
6bcd1346
RS
633 if (task == NULL) {
634 error_report("iSCSI: failed to send readcapacity16 command.");
635 itask->status = 1;
636 itask->complete = 1;
637 return;
638 }
639 break;
640 case TYPE_ROM:
641 task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
642 0, 0,
643 iscsi_readcapacity10_cb, opaque);
644 if (task == NULL) {
645 error_report("iSCSI: failed to send readcapacity16 command.");
646 itask->status = 1;
647 itask->complete = 1;
648 return;
649 }
650 break;
651 default:
652 itask->status = 0;
c589b249 653 itask->complete = 1;
c589b249
RS
654 }
655}
656
dbfff6d7
RS
657static void
658iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
659 void *opaque)
660{
661 struct IscsiTask *itask = opaque;
662 struct scsi_task *task;
663
664 if (status != 0) {
665 itask->status = 1;
666 itask->complete = 1;
667 return;
668 }
669
670 task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
671 0, 0, 36,
672 iscsi_inquiry_cb, opaque);
673 if (task == NULL) {
674 error_report("iSCSI: failed to send inquiry command.");
675 itask->status = 1;
676 itask->complete = 1;
677 return;
678 }
679}
680
f9dadc98
RS
681static int parse_chap(struct iscsi_context *iscsi, const char *target)
682{
683 QemuOptsList *list;
684 QemuOpts *opts;
685 const char *user = NULL;
686 const char *password = NULL;
687
688 list = qemu_find_opts("iscsi");
689 if (!list) {
690 return 0;
691 }
692
693 opts = qemu_opts_find(list, target);
694 if (opts == NULL) {
695 opts = QTAILQ_FIRST(&list->head);
696 if (!opts) {
697 return 0;
698 }
699 }
700
701 user = qemu_opt_get(opts, "user");
702 if (!user) {
703 return 0;
704 }
705
706 password = qemu_opt_get(opts, "password");
707 if (!password) {
708 error_report("CHAP username specified but no password was given");
709 return -1;
710 }
711
712 if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
713 error_report("Failed to set initiator username and password");
714 return -1;
715 }
716
717 return 0;
718}
719
720static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
721{
722 QemuOptsList *list;
723 QemuOpts *opts;
724 const char *digest = NULL;
725
726 list = qemu_find_opts("iscsi");
727 if (!list) {
728 return;
729 }
730
731 opts = qemu_opts_find(list, target);
732 if (opts == NULL) {
733 opts = QTAILQ_FIRST(&list->head);
734 if (!opts) {
735 return;
736 }
737 }
738
739 digest = qemu_opt_get(opts, "header-digest");
740 if (!digest) {
741 return;
742 }
743
744 if (!strcmp(digest, "CRC32C")) {
745 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
746 } else if (!strcmp(digest, "NONE")) {
747 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
748 } else if (!strcmp(digest, "CRC32C-NONE")) {
749 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
750 } else if (!strcmp(digest, "NONE-CRC32C")) {
751 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
752 } else {
753 error_report("Invalid header-digest setting : %s", digest);
754 }
755}
756
757static char *parse_initiator_name(const char *target)
758{
759 QemuOptsList *list;
760 QemuOpts *opts;
761 const char *name = NULL;
762
763 list = qemu_find_opts("iscsi");
764 if (!list) {
765 return g_strdup("iqn.2008-11.org.linux-kvm");
766 }
767
768 opts = qemu_opts_find(list, target);
769 if (opts == NULL) {
770 opts = QTAILQ_FIRST(&list->head);
771 if (!opts) {
772 return g_strdup("iqn.2008-11.org.linux-kvm");
773 }
774 }
775
776 name = qemu_opt_get(opts, "initiator-name");
777 if (!name) {
778 return g_strdup("iqn.2008-11.org.linux-kvm");
779 }
780
781 return g_strdup(name);
782}
783
c589b249
RS
784/*
785 * We support iscsi url's on the form
786 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
787 */
788static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
789{
790 IscsiLun *iscsilun = bs->opaque;
791 struct iscsi_context *iscsi = NULL;
792 struct iscsi_url *iscsi_url = NULL;
793 struct IscsiTask task;
f9dadc98 794 char *initiator_name = NULL;
c589b249
RS
795 int ret;
796
797 if ((BDRV_SECTOR_SIZE % 512) != 0) {
798 error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
799 "BDRV_SECTOR_SIZE(%lld) is not a multiple "
800 "of 512", BDRV_SECTOR_SIZE);
801 return -EINVAL;
802 }
803
c589b249
RS
804 iscsi_url = iscsi_parse_full_url(iscsi, filename);
805 if (iscsi_url == NULL) {
806 error_report("Failed to parse URL : %s %s", filename,
807 iscsi_get_error(iscsi));
808 ret = -EINVAL;
809 goto failed;
810 }
811
f9dadc98
RS
812 memset(iscsilun, 0, sizeof(IscsiLun));
813
814 initiator_name = parse_initiator_name(iscsi_url->target);
815
816 iscsi = iscsi_create_context(initiator_name);
817 if (iscsi == NULL) {
818 error_report("iSCSI: Failed to create iSCSI context.");
819 ret = -ENOMEM;
820 goto failed;
821 }
822
c589b249
RS
823 if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
824 error_report("iSCSI: Failed to set target name.");
825 ret = -EINVAL;
826 goto failed;
827 }
828
829 if (iscsi_url->user != NULL) {
830 ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
831 iscsi_url->passwd);
832 if (ret != 0) {
833 error_report("Failed to set initiator username and password");
834 ret = -EINVAL;
835 goto failed;
836 }
837 }
f9dadc98
RS
838
839 /* check if we got CHAP username/password via the options */
840 if (parse_chap(iscsi, iscsi_url->target) != 0) {
841 error_report("iSCSI: Failed to set CHAP user/password");
842 ret = -EINVAL;
843 goto failed;
844 }
845
c589b249
RS
846 if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
847 error_report("iSCSI: Failed to set session type to normal.");
848 ret = -EINVAL;
849 goto failed;
850 }
851
852 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
853
f9dadc98
RS
854 /* check if we got HEADER_DIGEST via the options */
855 parse_header_digest(iscsi, iscsi_url->target);
856
c589b249
RS
857 task.iscsilun = iscsilun;
858 task.status = 0;
859 task.complete = 0;
860 task.bs = bs;
861
862 iscsilun->iscsi = iscsi;
863 iscsilun->lun = iscsi_url->lun;
864
865 if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
866 iscsi_connect_cb, &task)
867 != 0) {
868 error_report("iSCSI: Failed to start async connect.");
869 ret = -EINVAL;
870 goto failed;
871 }
872
873 while (!task.complete) {
874 iscsi_set_events(iscsilun);
875 qemu_aio_wait();
876 }
877 if (task.status != 0) {
878 error_report("iSCSI: Failed to connect to LUN : %s",
879 iscsi_get_error(iscsi));
880 ret = -EINVAL;
881 goto failed;
882 }
883
884 if (iscsi_url != NULL) {
885 iscsi_destroy_url(iscsi_url);
886 }
887 return 0;
888
889failed:
f9dadc98
RS
890 if (initiator_name != NULL) {
891 g_free(initiator_name);
892 }
c589b249
RS
893 if (iscsi_url != NULL) {
894 iscsi_destroy_url(iscsi_url);
895 }
896 if (iscsi != NULL) {
897 iscsi_destroy_context(iscsi);
898 }
899 memset(iscsilun, 0, sizeof(IscsiLun));
900 return ret;
901}
902
903static void iscsi_close(BlockDriverState *bs)
904{
905 IscsiLun *iscsilun = bs->opaque;
906 struct iscsi_context *iscsi = iscsilun->iscsi;
907
bafbd6a1 908 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
c589b249
RS
909 iscsi_destroy_context(iscsi);
910 memset(iscsilun, 0, sizeof(IscsiLun));
911}
912
913static BlockDriver bdrv_iscsi = {
914 .format_name = "iscsi",
915 .protocol_name = "iscsi",
916
917 .instance_size = sizeof(IscsiLun),
918 .bdrv_file_open = iscsi_open,
919 .bdrv_close = iscsi_close,
920
921 .bdrv_getlength = iscsi_getlength,
922
923 .bdrv_aio_readv = iscsi_aio_readv,
924 .bdrv_aio_writev = iscsi_aio_writev,
925 .bdrv_aio_flush = iscsi_aio_flush,
fa6acb0c
RS
926
927 .bdrv_aio_discard = iscsi_aio_discard,
c589b249
RS
928};
929
930static void iscsi_block_init(void)
931{
932 bdrv_register(&bdrv_iscsi);
933}
934
935block_init(iscsi_block_init);