]> git.ipfire.org Git - thirdparty/qemu.git/blame - block/iscsi.c
iscsi: simplify iscsi_schedule_bh
[thirdparty/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
98392453
RS
38#ifdef __linux__
39#include <scsi/sg.h>
40#include <hw/scsi-defs.h>
41#endif
c589b249
RS
42
43typedef struct IscsiLun {
44 struct iscsi_context *iscsi;
45 int lun;
dbfff6d7 46 enum scsi_inquiry_peripheral_device_type type;
c589b249 47 int block_size;
c7b4a952 48 uint64_t num_blocks;
c9b9f682 49 int events;
c589b249
RS
50} IscsiLun;
51
52typedef struct IscsiAIOCB {
53 BlockDriverAIOCB common;
54 QEMUIOVector *qiov;
55 QEMUBH *bh;
56 IscsiLun *iscsilun;
57 struct scsi_task *task;
58 uint8_t *buf;
59 int status;
60 int canceled;
61 size_t read_size;
62 size_t read_offset;
98392453
RS
63#ifdef __linux__
64 sg_io_hdr_t *ioh;
65#endif
c589b249
RS
66} IscsiAIOCB;
67
68struct IscsiTask {
69 IscsiLun *iscsilun;
70 BlockDriverState *bs;
71 int status;
72 int complete;
73};
74
27cbd828 75static void
cfb3f506 76iscsi_bh_cb(void *p)
27cbd828
PB
77{
78 IscsiAIOCB *acb = p;
79
80 qemu_bh_delete(acb->bh);
81
82 if (acb->canceled == 0) {
83 acb->common.cb(acb->common.opaque, acb->status);
84 }
85
86 qemu_aio_release(acb);
87}
88
cfb3f506
PB
89static void
90iscsi_schedule_bh(IscsiAIOCB *acb)
27cbd828 91{
cfb3f506 92 acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
27cbd828 93 qemu_bh_schedule(acb->bh);
27cbd828
PB
94}
95
96
c589b249
RS
97static void
98iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
99 void *private_data)
100{
101}
102
103static void
104iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
105{
106 IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
107 IscsiLun *iscsilun = acb->iscsilun;
108
64e69e80 109 acb->common.cb(acb->common.opaque, -ECANCELED);
b2090919 110 acb->canceled = 1;
c589b249 111
b2090919 112 /* send a task mgmt call to the target to cancel the task on the target */
64e69e80 113 iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
b2090919
PB
114 iscsi_abort_task_cb, NULL);
115
116 /* then also cancel the task locally in libiscsi */
117 iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task);
c589b249
RS
118}
119
120static AIOPool iscsi_aio_pool = {
121 .aiocb_size = sizeof(IscsiAIOCB),
122 .cancel = iscsi_aio_cancel,
123};
124
125
126static void iscsi_process_read(void *arg);
127static void iscsi_process_write(void *arg);
128
129static int iscsi_process_flush(void *arg)
130{
131 IscsiLun *iscsilun = arg;
132
133 return iscsi_queue_length(iscsilun->iscsi) > 0;
134}
135
136static void
137iscsi_set_events(IscsiLun *iscsilun)
138{
139 struct iscsi_context *iscsi = iscsilun->iscsi;
c9b9f682
RS
140 int ev;
141
142 /* We always register a read handler. */
143 ev = POLLIN;
144 ev |= iscsi_which_events(iscsi);
145 if (ev != iscsilun->events) {
146 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
147 iscsi_process_read,
148 (ev & POLLOUT) ? iscsi_process_write : NULL,
149 iscsi_process_flush,
150 iscsilun);
151
152 }
153
154 /* If we just added an event, the callback might be delayed
155 * unless we call qemu_notify_event().
156 */
157 if (ev & ~iscsilun->events) {
158 qemu_notify_event();
159 }
160 iscsilun->events = ev;
c589b249
RS
161}
162
163static void
164iscsi_process_read(void *arg)
165{
166 IscsiLun *iscsilun = arg;
167 struct iscsi_context *iscsi = iscsilun->iscsi;
168
169 iscsi_service(iscsi, POLLIN);
170 iscsi_set_events(iscsilun);
171}
172
173static void
174iscsi_process_write(void *arg)
175{
176 IscsiLun *iscsilun = arg;
177 struct iscsi_context *iscsi = iscsilun->iscsi;
178
179 iscsi_service(iscsi, POLLOUT);
180 iscsi_set_events(iscsilun);
181}
182
183
c589b249 184static void
f4dfa67f 185iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
186 void *command_data, void *opaque)
187{
188 IscsiAIOCB *acb = opaque;
189
f4dfa67f 190 trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
c589b249
RS
191
192 g_free(acb->buf);
193
b2090919 194 if (acb->canceled != 0) {
c589b249 195 qemu_aio_release(acb);
b2090919
PB
196 scsi_free_scsi_task(acb->task);
197 acb->task = NULL;
c589b249
RS
198 return;
199 }
200
201 acb->status = 0;
202 if (status < 0) {
f4dfa67f 203 error_report("Failed to write16 data to iSCSI lun. %s",
c589b249
RS
204 iscsi_get_error(iscsi));
205 acb->status = -EIO;
206 }
207
cfb3f506 208 iscsi_schedule_bh(acb);
b2090919
PB
209 scsi_free_scsi_task(acb->task);
210 acb->task = NULL;
c589b249
RS
211}
212
213static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
214{
215 return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
216}
217
218static BlockDriverAIOCB *
219iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
220 QEMUIOVector *qiov, int nb_sectors,
221 BlockDriverCompletionFunc *cb,
222 void *opaque)
223{
224 IscsiLun *iscsilun = bs->opaque;
225 struct iscsi_context *iscsi = iscsilun->iscsi;
226 IscsiAIOCB *acb;
227 size_t size;
f4dfa67f
RS
228 uint32_t num_sectors;
229 uint64_t lba;
230 struct iscsi_data data;
c589b249
RS
231
232 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
233 trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
234
235 acb->iscsilun = iscsilun;
236 acb->qiov = qiov;
237
238 acb->canceled = 0;
239
f4dfa67f 240 /* XXX we should pass the iovec to write16 to avoid the extra copy */
c589b249
RS
241 /* this will allow us to get rid of 'buf' completely */
242 size = nb_sectors * BDRV_SECTOR_SIZE;
243 acb->buf = g_malloc(size);
d5e6b161 244 qemu_iovec_to_buf(acb->qiov, 0, acb->buf, size);
f4dfa67f
RS
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 294
b2090919 295 if (acb->canceled != 0) {
c589b249 296 qemu_aio_release(acb);
b2090919
PB
297 scsi_free_scsi_task(acb->task);
298 acb->task = NULL;
c589b249
RS
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
cfb3f506 309 iscsi_schedule_bh(acb);
b2090919
PB
310 scsi_free_scsi_task(acb->task);
311 acb->task = NULL;
c589b249
RS
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
b2090919 411 if (acb->canceled != 0) {
c589b249 412 qemu_aio_release(acb);
b2090919
PB
413 scsi_free_scsi_task(acb->task);
414 acb->task = NULL;
c589b249
RS
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
cfb3f506 425 iscsi_schedule_bh(acb);
b2090919
PB
426 scsi_free_scsi_task(acb->task);
427 acb->task = NULL;
c589b249
RS
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
b2090919 465 if (acb->canceled != 0) {
fa6acb0c 466 qemu_aio_release(acb);
b2090919
PB
467 scsi_free_scsi_task(acb->task);
468 acb->task = NULL;
fa6acb0c
RS
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
cfb3f506 479 iscsi_schedule_bh(acb);
b2090919
PB
480 scsi_free_scsi_task(acb->task);
481 acb->task = NULL;
fa6acb0c
RS
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
98392453
RS
518#ifdef __linux__
519static void
520iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
521 void *command_data, void *opaque)
522{
523 IscsiAIOCB *acb = opaque;
524
b2090919 525 if (acb->canceled != 0) {
98392453 526 qemu_aio_release(acb);
b2090919
PB
527 scsi_free_scsi_task(acb->task);
528 acb->task = NULL;
98392453
RS
529 return;
530 }
531
532 acb->status = 0;
533 if (status < 0) {
534 error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
535 iscsi_get_error(iscsi));
536 acb->status = -EIO;
537 }
538
539 acb->ioh->driver_status = 0;
540 acb->ioh->host_status = 0;
541 acb->ioh->resid = 0;
542
543#define SG_ERR_DRIVER_SENSE 0x08
544
545 if (status == SCSI_STATUS_CHECK_CONDITION && acb->task->datain.size >= 2) {
546 int ss;
547
548 acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
549
550 acb->ioh->sb_len_wr = acb->task->datain.size - 2;
551 ss = (acb->ioh->mx_sb_len >= acb->ioh->sb_len_wr) ?
552 acb->ioh->mx_sb_len : acb->ioh->sb_len_wr;
553 memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
554 }
555
cfb3f506 556 iscsi_schedule_bh(acb);
b2090919
PB
557 scsi_free_scsi_task(acb->task);
558 acb->task = NULL;
98392453
RS
559}
560
561static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
562 unsigned long int req, void *buf,
563 BlockDriverCompletionFunc *cb, void *opaque)
564{
565 IscsiLun *iscsilun = bs->opaque;
566 struct iscsi_context *iscsi = iscsilun->iscsi;
567 struct iscsi_data data;
568 IscsiAIOCB *acb;
569
570 assert(req == SG_IO);
571
572 acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
573
574 acb->iscsilun = iscsilun;
575 acb->canceled = 0;
576 acb->buf = NULL;
577 acb->ioh = buf;
578
579 acb->task = malloc(sizeof(struct scsi_task));
580 if (acb->task == NULL) {
581 error_report("iSCSI: Failed to allocate task for scsi command. %s",
582 iscsi_get_error(iscsi));
583 qemu_aio_release(acb);
584 return NULL;
585 }
586 memset(acb->task, 0, sizeof(struct scsi_task));
587
588 switch (acb->ioh->dxfer_direction) {
589 case SG_DXFER_TO_DEV:
590 acb->task->xfer_dir = SCSI_XFER_WRITE;
591 break;
592 case SG_DXFER_FROM_DEV:
593 acb->task->xfer_dir = SCSI_XFER_READ;
594 break;
595 default:
596 acb->task->xfer_dir = SCSI_XFER_NONE;
597 break;
598 }
599
600 acb->task->cdb_size = acb->ioh->cmd_len;
601 memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
602 acb->task->expxferlen = acb->ioh->dxfer_len;
603
604 if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
605 data.data = acb->ioh->dxferp;
606 data.size = acb->ioh->dxfer_len;
607 }
608 if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
609 iscsi_aio_ioctl_cb,
610 (acb->task->xfer_dir == SCSI_XFER_WRITE) ?
611 &data : NULL,
612 acb) != 0) {
613 scsi_free_scsi_task(acb->task);
614 qemu_aio_release(acb);
615 return NULL;
616 }
617
618 /* tell libiscsi to read straight into the buffer we got from ioctl */
619 if (acb->task->xfer_dir == SCSI_XFER_READ) {
620 scsi_task_add_data_in_buffer(acb->task,
621 acb->ioh->dxfer_len,
622 acb->ioh->dxferp);
623 }
624
625 iscsi_set_events(iscsilun);
626
627 return &acb->common;
628}
629
630static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
631{
632 IscsiLun *iscsilun = bs->opaque;
633
634 switch (req) {
635 case SG_GET_VERSION_NUM:
636 *(int *)buf = 30000;
637 break;
638 case SG_GET_SCSI_ID:
639 ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
640 break;
641 default:
642 return -1;
643 }
644 return 0;
645}
646#endif
647
c589b249
RS
648static int64_t
649iscsi_getlength(BlockDriverState *bs)
650{
651 IscsiLun *iscsilun = bs->opaque;
652 int64_t len;
653
654 len = iscsilun->num_blocks;
655 len *= iscsilun->block_size;
656
657 return len;
658}
659
660static void
fa6acb0c 661iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
662 void *command_data, void *opaque)
663{
664 struct IscsiTask *itask = opaque;
fa6acb0c 665 struct scsi_readcapacity16 *rc16;
c589b249
RS
666 struct scsi_task *task = command_data;
667
668 if (status != 0) {
669 error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
670 iscsi_get_error(iscsi));
671 itask->status = 1;
672 itask->complete = 1;
673 scsi_free_scsi_task(task);
674 return;
675 }
676
fa6acb0c
RS
677 rc16 = scsi_datain_unmarshall(task);
678 if (rc16 == NULL) {
679 error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
c589b249
RS
680 itask->status = 1;
681 itask->complete = 1;
682 scsi_free_scsi_task(task);
683 return;
684 }
685
fa6acb0c
RS
686 itask->iscsilun->block_size = rc16->block_length;
687 itask->iscsilun->num_blocks = rc16->returned_lba + 1;
688 itask->bs->total_sectors = itask->iscsilun->num_blocks *
689 itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
c589b249
RS
690
691 itask->status = 0;
692 itask->complete = 1;
693 scsi_free_scsi_task(task);
694}
695
6bcd1346
RS
696static void
697iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
698 void *command_data, void *opaque)
699{
700 struct IscsiTask *itask = opaque;
701 struct scsi_readcapacity10 *rc10;
702 struct scsi_task *task = command_data;
703
704 if (status != 0) {
705 error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
706 iscsi_get_error(iscsi));
707 itask->status = 1;
708 itask->complete = 1;
709 scsi_free_scsi_task(task);
710 return;
711 }
712
713 rc10 = scsi_datain_unmarshall(task);
714 if (rc10 == NULL) {
715 error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
716 itask->status = 1;
717 itask->complete = 1;
718 scsi_free_scsi_task(task);
719 return;
720 }
721
722 itask->iscsilun->block_size = rc10->block_size;
723 itask->iscsilun->num_blocks = rc10->lba + 1;
724 itask->bs->total_sectors = itask->iscsilun->num_blocks *
725 itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
726
727 itask->status = 0;
728 itask->complete = 1;
729 scsi_free_scsi_task(task);
730}
731
c589b249 732static void
dbfff6d7 733iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
c589b249
RS
734 void *opaque)
735{
736 struct IscsiTask *itask = opaque;
dbfff6d7
RS
737 struct scsi_task *task = command_data;
738 struct scsi_inquiry_standard *inq;
c589b249
RS
739
740 if (status != 0) {
741 itask->status = 1;
742 itask->complete = 1;
dbfff6d7 743 scsi_free_scsi_task(task);
c589b249
RS
744 return;
745 }
746
dbfff6d7
RS
747 inq = scsi_datain_unmarshall(task);
748 if (inq == NULL) {
749 error_report("iSCSI: Failed to unmarshall inquiry data.");
750 itask->status = 1;
751 itask->complete = 1;
752 scsi_free_scsi_task(task);
753 return;
754 }
755
756 itask->iscsilun->type = inq->periperal_device_type;
757
758 scsi_free_scsi_task(task);
759
6bcd1346
RS
760 switch (itask->iscsilun->type) {
761 case TYPE_DISK:
762 task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
fa6acb0c 763 iscsi_readcapacity16_cb, opaque);
6bcd1346
RS
764 if (task == NULL) {
765 error_report("iSCSI: failed to send readcapacity16 command.");
766 itask->status = 1;
767 itask->complete = 1;
768 return;
769 }
770 break;
771 case TYPE_ROM:
772 task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
773 0, 0,
774 iscsi_readcapacity10_cb, opaque);
775 if (task == NULL) {
776 error_report("iSCSI: failed to send readcapacity16 command.");
777 itask->status = 1;
778 itask->complete = 1;
779 return;
780 }
781 break;
782 default:
783 itask->status = 0;
c589b249 784 itask->complete = 1;
c589b249
RS
785 }
786}
787
dbfff6d7
RS
788static void
789iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
790 void *opaque)
791{
792 struct IscsiTask *itask = opaque;
793 struct scsi_task *task;
794
795 if (status != 0) {
796 itask->status = 1;
797 itask->complete = 1;
798 return;
799 }
800
801 task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
802 0, 0, 36,
803 iscsi_inquiry_cb, opaque);
804 if (task == NULL) {
805 error_report("iSCSI: failed to send inquiry command.");
806 itask->status = 1;
807 itask->complete = 1;
808 return;
809 }
810}
811
f9dadc98
RS
812static int parse_chap(struct iscsi_context *iscsi, const char *target)
813{
814 QemuOptsList *list;
815 QemuOpts *opts;
816 const char *user = NULL;
817 const char *password = NULL;
818
819 list = qemu_find_opts("iscsi");
820 if (!list) {
821 return 0;
822 }
823
824 opts = qemu_opts_find(list, target);
825 if (opts == NULL) {
826 opts = QTAILQ_FIRST(&list->head);
827 if (!opts) {
828 return 0;
829 }
830 }
831
832 user = qemu_opt_get(opts, "user");
833 if (!user) {
834 return 0;
835 }
836
837 password = qemu_opt_get(opts, "password");
838 if (!password) {
839 error_report("CHAP username specified but no password was given");
840 return -1;
841 }
842
843 if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
844 error_report("Failed to set initiator username and password");
845 return -1;
846 }
847
848 return 0;
849}
850
851static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
852{
853 QemuOptsList *list;
854 QemuOpts *opts;
855 const char *digest = NULL;
856
857 list = qemu_find_opts("iscsi");
858 if (!list) {
859 return;
860 }
861
862 opts = qemu_opts_find(list, target);
863 if (opts == NULL) {
864 opts = QTAILQ_FIRST(&list->head);
865 if (!opts) {
866 return;
867 }
868 }
869
870 digest = qemu_opt_get(opts, "header-digest");
871 if (!digest) {
872 return;
873 }
874
875 if (!strcmp(digest, "CRC32C")) {
876 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
877 } else if (!strcmp(digest, "NONE")) {
878 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
879 } else if (!strcmp(digest, "CRC32C-NONE")) {
880 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
881 } else if (!strcmp(digest, "NONE-CRC32C")) {
882 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
883 } else {
884 error_report("Invalid header-digest setting : %s", digest);
885 }
886}
887
888static char *parse_initiator_name(const char *target)
889{
890 QemuOptsList *list;
891 QemuOpts *opts;
892 const char *name = NULL;
31459f46 893 const char *iscsi_name = qemu_get_vm_name();
f9dadc98
RS
894
895 list = qemu_find_opts("iscsi");
f2ef4a6d
PB
896 if (list) {
897 opts = qemu_opts_find(list, target);
f9dadc98 898 if (!opts) {
f2ef4a6d
PB
899 opts = QTAILQ_FIRST(&list->head);
900 }
901 if (opts) {
902 name = qemu_opt_get(opts, "initiator-name");
f9dadc98
RS
903 }
904 }
905
f2ef4a6d
PB
906 if (name) {
907 return g_strdup(name);
908 } else {
31459f46
RS
909 return g_strdup_printf("iqn.2008-11.org.linux-kvm%s%s",
910 iscsi_name ? ":" : "",
911 iscsi_name ? iscsi_name : "");
f9dadc98 912 }
f9dadc98
RS
913}
914
c589b249
RS
915/*
916 * We support iscsi url's on the form
917 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
918 */
919static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
920{
921 IscsiLun *iscsilun = bs->opaque;
922 struct iscsi_context *iscsi = NULL;
923 struct iscsi_url *iscsi_url = NULL;
924 struct IscsiTask task;
f9dadc98 925 char *initiator_name = NULL;
c589b249
RS
926 int ret;
927
928 if ((BDRV_SECTOR_SIZE % 512) != 0) {
929 error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
930 "BDRV_SECTOR_SIZE(%lld) is not a multiple "
931 "of 512", BDRV_SECTOR_SIZE);
932 return -EINVAL;
933 }
934
c589b249
RS
935 iscsi_url = iscsi_parse_full_url(iscsi, filename);
936 if (iscsi_url == NULL) {
937 error_report("Failed to parse URL : %s %s", filename,
938 iscsi_get_error(iscsi));
939 ret = -EINVAL;
b93c94f7 940 goto out;
c589b249
RS
941 }
942
f9dadc98
RS
943 memset(iscsilun, 0, sizeof(IscsiLun));
944
945 initiator_name = parse_initiator_name(iscsi_url->target);
946
947 iscsi = iscsi_create_context(initiator_name);
948 if (iscsi == NULL) {
949 error_report("iSCSI: Failed to create iSCSI context.");
950 ret = -ENOMEM;
b93c94f7 951 goto out;
f9dadc98
RS
952 }
953
c589b249
RS
954 if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
955 error_report("iSCSI: Failed to set target name.");
956 ret = -EINVAL;
b93c94f7 957 goto out;
c589b249
RS
958 }
959
960 if (iscsi_url->user != NULL) {
961 ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
962 iscsi_url->passwd);
963 if (ret != 0) {
964 error_report("Failed to set initiator username and password");
965 ret = -EINVAL;
b93c94f7 966 goto out;
c589b249
RS
967 }
968 }
f9dadc98
RS
969
970 /* check if we got CHAP username/password via the options */
971 if (parse_chap(iscsi, iscsi_url->target) != 0) {
972 error_report("iSCSI: Failed to set CHAP user/password");
973 ret = -EINVAL;
b93c94f7 974 goto out;
f9dadc98
RS
975 }
976
c589b249
RS
977 if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
978 error_report("iSCSI: Failed to set session type to normal.");
979 ret = -EINVAL;
b93c94f7 980 goto out;
c589b249
RS
981 }
982
983 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
984
f9dadc98
RS
985 /* check if we got HEADER_DIGEST via the options */
986 parse_header_digest(iscsi, iscsi_url->target);
987
c589b249
RS
988 task.iscsilun = iscsilun;
989 task.status = 0;
990 task.complete = 0;
991 task.bs = bs;
992
993 iscsilun->iscsi = iscsi;
994 iscsilun->lun = iscsi_url->lun;
995
996 if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
997 iscsi_connect_cb, &task)
998 != 0) {
999 error_report("iSCSI: Failed to start async connect.");
1000 ret = -EINVAL;
b93c94f7 1001 goto out;
c589b249
RS
1002 }
1003
1004 while (!task.complete) {
1005 iscsi_set_events(iscsilun);
1006 qemu_aio_wait();
1007 }
1008 if (task.status != 0) {
1009 error_report("iSCSI: Failed to connect to LUN : %s",
1010 iscsi_get_error(iscsi));
1011 ret = -EINVAL;
b93c94f7 1012 goto out;
c589b249 1013 }
622695a4
RS
1014
1015 /* Medium changer or tape. We dont have any emulation for this so this must
1016 * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
1017 * to read from the device to guess the image format.
1018 */
1019 if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
1020 iscsilun->type == TYPE_TAPE) {
1021 bs->sg = 1;
1022 }
1023
b93c94f7 1024 ret = 0;
c589b249 1025
b93c94f7 1026out:
f9dadc98
RS
1027 if (initiator_name != NULL) {
1028 g_free(initiator_name);
1029 }
c589b249
RS
1030 if (iscsi_url != NULL) {
1031 iscsi_destroy_url(iscsi_url);
1032 }
b93c94f7
PB
1033
1034 if (ret) {
1035 if (iscsi != NULL) {
1036 iscsi_destroy_context(iscsi);
1037 }
1038 memset(iscsilun, 0, sizeof(IscsiLun));
c589b249 1039 }
c589b249
RS
1040 return ret;
1041}
1042
1043static void iscsi_close(BlockDriverState *bs)
1044{
1045 IscsiLun *iscsilun = bs->opaque;
1046 struct iscsi_context *iscsi = iscsilun->iscsi;
1047
bafbd6a1 1048 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
c589b249
RS
1049 iscsi_destroy_context(iscsi);
1050 memset(iscsilun, 0, sizeof(IscsiLun));
1051}
1052
1053static BlockDriver bdrv_iscsi = {
1054 .format_name = "iscsi",
1055 .protocol_name = "iscsi",
1056
1057 .instance_size = sizeof(IscsiLun),
1058 .bdrv_file_open = iscsi_open,
1059 .bdrv_close = iscsi_close,
1060
1061 .bdrv_getlength = iscsi_getlength,
1062
1063 .bdrv_aio_readv = iscsi_aio_readv,
1064 .bdrv_aio_writev = iscsi_aio_writev,
1065 .bdrv_aio_flush = iscsi_aio_flush,
fa6acb0c
RS
1066
1067 .bdrv_aio_discard = iscsi_aio_discard,
98392453
RS
1068
1069#ifdef __linux__
1070 .bdrv_ioctl = iscsi_ioctl,
1071 .bdrv_aio_ioctl = iscsi_aio_ioctl,
1072#endif
c589b249
RS
1073};
1074
1075static void iscsi_block_init(void)
1076{
1077 bdrv_register(&bdrv_iscsi);
1078}
1079
1080block_init(iscsi_block_init);