]> Git Repo - qemu.git/blame - block/iscsi.c
target-ppc/kvm.c: Rename 'dprintf' to 'DPRINTF'
[qemu.git] / block / iscsi.c
CommitLineData
c589b249
RS
1/*
2 * QEMU Block driver for iSCSI images
3 *
4 * Copyright (c) 2010-2011 Ronnie Sahlberg <[email protected]>
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 29#include "qemu-common.h"
1de7afc9
PB
30#include "qemu/config-file.h"
31#include "qemu/error-report.h"
737e150e 32#include "block/block_int.h"
c589b249 33#include "trace.h"
0d09e41a 34#include "block/scsi.h"
0a53f010 35#include "qemu/iov.h"
c589b249
RS
36
37#include <iscsi/iscsi.h>
38#include <iscsi/scsi-lowlevel.h>
39
98392453
RS
40#ifdef __linux__
41#include <scsi/sg.h>
0d09e41a 42#include <block/scsi.h>
98392453 43#endif
c589b249
RS
44
45typedef struct IscsiLun {
46 struct iscsi_context *iscsi;
47 int lun;
dbfff6d7 48 enum scsi_inquiry_peripheral_device_type type;
c589b249 49 int block_size;
c7b4a952 50 uint64_t num_blocks;
c9b9f682 51 int events;
5b5d34ec 52 QEMUTimer *nop_timer;
c589b249
RS
53} IscsiLun;
54
55typedef struct IscsiAIOCB {
56 BlockDriverAIOCB common;
57 QEMUIOVector *qiov;
58 QEMUBH *bh;
59 IscsiLun *iscsilun;
60 struct scsi_task *task;
61 uint8_t *buf;
62 int status;
63 int canceled;
1dde716e 64 int retries;
1dde716e
PL
65 int64_t sector_num;
66 int nb_sectors;
98392453
RS
67#ifdef __linux__
68 sg_io_hdr_t *ioh;
69#endif
c589b249
RS
70} IscsiAIOCB;
71
5b5d34ec
PL
72#define NOP_INTERVAL 5000
73#define MAX_NOP_FAILURES 3
1dde716e 74#define ISCSI_CMD_RETRIES 5
5b5d34ec 75
27cbd828 76static void
cfb3f506 77iscsi_bh_cb(void *p)
27cbd828
PB
78{
79 IscsiAIOCB *acb = p;
80
81 qemu_bh_delete(acb->bh);
82
4790b03d
PB
83 g_free(acb->buf);
84 acb->buf = NULL;
85
27cbd828
PB
86 if (acb->canceled == 0) {
87 acb->common.cb(acb->common.opaque, acb->status);
88 }
89
1bd075f2
PB
90 if (acb->task != NULL) {
91 scsi_free_scsi_task(acb->task);
92 acb->task = NULL;
93 }
94
27cbd828
PB
95 qemu_aio_release(acb);
96}
97
cfb3f506
PB
98static void
99iscsi_schedule_bh(IscsiAIOCB *acb)
27cbd828 100{
1bd075f2
PB
101 if (acb->bh) {
102 return;
103 }
cfb3f506 104 acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
27cbd828 105 qemu_bh_schedule(acb->bh);
27cbd828
PB
106}
107
108
c589b249
RS
109static void
110iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
111 void *private_data)
112{
1bd075f2
PB
113 IscsiAIOCB *acb = private_data;
114
115 acb->status = -ECANCELED;
116 iscsi_schedule_bh(acb);
c589b249
RS
117}
118
119static void
120iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
121{
122 IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
123 IscsiLun *iscsilun = acb->iscsilun;
124
1bd075f2
PB
125 if (acb->status != -EINPROGRESS) {
126 return;
127 }
128
b2090919 129 acb->canceled = 1;
c589b249 130
b2090919 131 /* send a task mgmt call to the target to cancel the task on the target */
64e69e80 132 iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
1bd075f2 133 iscsi_abort_task_cb, acb);
b2090919 134
1bd075f2
PB
135 while (acb->status == -EINPROGRESS) {
136 qemu_aio_wait();
137 }
c589b249
RS
138}
139
d7331bed 140static const AIOCBInfo iscsi_aiocb_info = {
c589b249
RS
141 .aiocb_size = sizeof(IscsiAIOCB),
142 .cancel = iscsi_aio_cancel,
143};
144
145
146static void iscsi_process_read(void *arg);
147static void iscsi_process_write(void *arg);
148
149static int iscsi_process_flush(void *arg)
150{
151 IscsiLun *iscsilun = arg;
152
153 return iscsi_queue_length(iscsilun->iscsi) > 0;
154}
155
156static void
157iscsi_set_events(IscsiLun *iscsilun)
158{
159 struct iscsi_context *iscsi = iscsilun->iscsi;
c9b9f682
RS
160 int ev;
161
162 /* We always register a read handler. */
163 ev = POLLIN;
164 ev |= iscsi_which_events(iscsi);
165 if (ev != iscsilun->events) {
166 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
167 iscsi_process_read,
168 (ev & POLLOUT) ? iscsi_process_write : NULL,
169 iscsi_process_flush,
170 iscsilun);
171
172 }
173
c9b9f682 174 iscsilun->events = ev;
c589b249
RS
175}
176
177static void
178iscsi_process_read(void *arg)
179{
180 IscsiLun *iscsilun = arg;
181 struct iscsi_context *iscsi = iscsilun->iscsi;
182
183 iscsi_service(iscsi, POLLIN);
184 iscsi_set_events(iscsilun);
185}
186
187static void
188iscsi_process_write(void *arg)
189{
190 IscsiLun *iscsilun = arg;
191 struct iscsi_context *iscsi = iscsilun->iscsi;
192
193 iscsi_service(iscsi, POLLOUT);
194 iscsi_set_events(iscsilun);
195}
196
1dde716e
PL
197static int
198iscsi_aio_writev_acb(IscsiAIOCB *acb);
c589b249 199
c589b249 200static void
f4dfa67f 201iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
202 void *command_data, void *opaque)
203{
204 IscsiAIOCB *acb = opaque;
205
f4dfa67f 206 trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
c589b249
RS
207
208 g_free(acb->buf);
4790b03d 209 acb->buf = NULL;
c589b249 210
b2090919 211 if (acb->canceled != 0) {
c589b249
RS
212 return;
213 }
214
215 acb->status = 0;
1dde716e
PL
216 if (status != 0) {
217 if (status == SCSI_STATUS_CHECK_CONDITION
218 && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
219 && acb->retries-- > 0) {
f0d2a4d4
PB
220 scsi_free_scsi_task(acb->task);
221 acb->task = NULL;
1dde716e
PL
222 if (iscsi_aio_writev_acb(acb) == 0) {
223 iscsi_set_events(acb->iscsilun);
224 return;
225 }
226 }
f4dfa67f 227 error_report("Failed to write16 data to iSCSI lun. %s",
c589b249
RS
228 iscsi_get_error(iscsi));
229 acb->status = -EIO;
230 }
231
cfb3f506 232 iscsi_schedule_bh(acb);
c589b249
RS
233}
234
0777b5dd
PL
235static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun)
236{
237 return sector * iscsilun->block_size / BDRV_SECTOR_SIZE;
238}
239
c589b249
RS
240static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
241{
242 return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
243}
244
91bea4e2
PL
245static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
246 IscsiLun *iscsilun)
247{
248 if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size ||
249 (nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) {
250 error_report("iSCSI misaligned request: iscsilun->block_size %u, sector_num %ld, nb_sectors %d",
251 iscsilun->block_size, sector_num, nb_sectors);
252 return 0;
253 }
254 return 1;
255}
256
1dde716e
PL
257static int
258iscsi_aio_writev_acb(IscsiAIOCB *acb)
c589b249 259{
1dde716e 260 struct iscsi_context *iscsi = acb->iscsilun->iscsi;
c589b249 261 size_t size;
f4dfa67f
RS
262 uint32_t num_sectors;
263 uint64_t lba;
7371d56f 264#if !defined(LIBISCSI_FEATURE_IOVECTOR)
f4dfa67f 265 struct iscsi_data data;
7371d56f
PL
266#endif
267 int ret;
c589b249 268
c589b249 269 acb->canceled = 0;
1bd075f2
PB
270 acb->bh = NULL;
271 acb->status = -EINPROGRESS;
4790b03d 272 acb->buf = NULL;
c589b249 273
c589b249 274 /* this will allow us to get rid of 'buf' completely */
1dde716e 275 size = acb->nb_sectors * BDRV_SECTOR_SIZE;
7371d56f
PL
276
277#if !defined(LIBISCSI_FEATURE_IOVECTOR)
4cc841b5
PL
278 data.size = MIN(size, acb->qiov->size);
279
280 /* if the iovec only contains one buffer we can pass it directly */
281 if (acb->qiov->niov == 1) {
4cc841b5
PL
282 data.data = acb->qiov->iov[0].iov_base;
283 } else {
284 acb->buf = g_malloc(data.size);
285 qemu_iovec_to_buf(acb->qiov, 0, acb->buf, data.size);
286 data.data = acb->buf;
287 }
7371d56f 288#endif
f4dfa67f
RS
289
290 acb->task = malloc(sizeof(struct scsi_task));
c589b249 291 if (acb->task == NULL) {
f4dfa67f
RS
292 error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
293 "command. %s", iscsi_get_error(iscsi));
1dde716e 294 return -1;
f4dfa67f
RS
295 }
296 memset(acb->task, 0, sizeof(struct scsi_task));
297
298 acb->task->xfer_dir = SCSI_XFER_WRITE;
299 acb->task->cdb_size = 16;
300 acb->task->cdb[0] = 0x8a;
1dde716e 301 lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
f4dfa67f
RS
302 *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
303 *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
0777b5dd 304 num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);
f4dfa67f
RS
305 *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
306 acb->task->expxferlen = size;
307
7371d56f 308#if defined(LIBISCSI_FEATURE_IOVECTOR)
1dde716e 309 ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
7371d56f
PL
310 iscsi_aio_write16_cb,
311 NULL,
312 acb);
313#else
1dde716e 314 ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
7371d56f
PL
315 iscsi_aio_write16_cb,
316 &data,
317 acb);
318#endif
319 if (ret != 0) {
f0d2a4d4 320 scsi_free_scsi_task(acb->task);
c589b249 321 g_free(acb->buf);
1dde716e 322 return -1;
c589b249
RS
323 }
324
7371d56f
PL
325#if defined(LIBISCSI_FEATURE_IOVECTOR)
326 scsi_task_set_iov_out(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);
327#endif
328
1dde716e
PL
329 return 0;
330}
331
332static BlockDriverAIOCB *
333iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
334 QEMUIOVector *qiov, int nb_sectors,
335 BlockDriverCompletionFunc *cb,
336 void *opaque)
337{
338 IscsiLun *iscsilun = bs->opaque;
339 IscsiAIOCB *acb;
c589b249 340
91bea4e2
PL
341 if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
342 return NULL;
343 }
344
1dde716e
PL
345 acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
346 trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
347
348 acb->iscsilun = iscsilun;
349 acb->qiov = qiov;
350 acb->nb_sectors = nb_sectors;
351 acb->sector_num = sector_num;
352 acb->retries = ISCSI_CMD_RETRIES;
353
354 if (iscsi_aio_writev_acb(acb) != 0) {
1dde716e
PL
355 qemu_aio_release(acb);
356 return NULL;
357 }
358
359 iscsi_set_events(iscsilun);
c589b249
RS
360 return &acb->common;
361}
362
1dde716e
PL
363static int
364iscsi_aio_readv_acb(IscsiAIOCB *acb);
365
c589b249 366static void
f4dfa67f 367iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
c589b249
RS
368 void *command_data, void *opaque)
369{
370 IscsiAIOCB *acb = opaque;
371
f4dfa67f 372 trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
c589b249 373
b2090919 374 if (acb->canceled != 0) {
c589b249
RS
375 return;
376 }
377
378 acb->status = 0;
379 if (status != 0) {
1dde716e
PL
380 if (status == SCSI_STATUS_CHECK_CONDITION
381 && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
382 && acb->retries-- > 0) {
f0d2a4d4
PB
383 scsi_free_scsi_task(acb->task);
384 acb->task = NULL;
1dde716e
PL
385 if (iscsi_aio_readv_acb(acb) == 0) {
386 iscsi_set_events(acb->iscsilun);
387 return;
388 }
389 }
f4dfa67f 390 error_report("Failed to read16 data from iSCSI lun. %s",
c589b249
RS
391 iscsi_get_error(iscsi));
392 acb->status = -EIO;
393 }
394
cfb3f506 395 iscsi_schedule_bh(acb);
c589b249
RS
396}
397
1dde716e
PL
398static int
399iscsi_aio_readv_acb(IscsiAIOCB *acb)
c589b249 400{
1dde716e 401 struct iscsi_context *iscsi = acb->iscsilun->iscsi;
7e4d5a9f 402 size_t size;
1dde716e
PL
403 uint64_t lba;
404 uint32_t num_sectors;
405 int ret;
7371d56f 406#if !defined(LIBISCSI_FEATURE_IOVECTOR)
c589b249 407 int i;
7371d56f 408#endif
c589b249
RS
409
410 acb->canceled = 0;
1bd075f2
PB
411 acb->bh = NULL;
412 acb->status = -EINPROGRESS;
c589b249
RS
413 acb->buf = NULL;
414
7e4d5a9f 415 size = acb->nb_sectors * BDRV_SECTOR_SIZE;
f4dfa67f
RS
416
417 acb->task = malloc(sizeof(struct scsi_task));
c589b249 418 if (acb->task == NULL) {
f4dfa67f
RS
419 error_report("iSCSI: Failed to allocate task for scsi READ16 "
420 "command. %s", iscsi_get_error(iscsi));
1dde716e 421 return -1;
f4dfa67f
RS
422 }
423 memset(acb->task, 0, sizeof(struct scsi_task));
424
425 acb->task->xfer_dir = SCSI_XFER_READ;
7e4d5a9f 426 acb->task->expxferlen = size;
1dde716e 427 lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
7e4d5a9f 428 num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);
f4dfa67f 429
1dde716e 430 switch (acb->iscsilun->type) {
f4dfa67f
RS
431 case TYPE_DISK:
432 acb->task->cdb_size = 16;
433 acb->task->cdb[0] = 0x88;
434 *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
435 *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
436 *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
437 break;
438 default:
439 acb->task->cdb_size = 10;
440 acb->task->cdb[0] = 0x28;
441 *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
442 *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
443 break;
444 }
e829b0bb 445
1dde716e 446 ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
7371d56f
PL
447 iscsi_aio_read16_cb,
448 NULL,
449 acb);
450 if (ret != 0) {
f0d2a4d4 451 scsi_free_scsi_task(acb->task);
1dde716e 452 return -1;
c589b249
RS
453 }
454
7371d56f
PL
455#if defined(LIBISCSI_FEATURE_IOVECTOR)
456 scsi_task_set_iov_in(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);
457#else
c589b249
RS
458 for (i = 0; i < acb->qiov->niov; i++) {
459 scsi_task_add_data_in_buffer(acb->task,
460 acb->qiov->iov[i].iov_len,
461 acb->qiov->iov[i].iov_base);
462 }
7371d56f 463#endif
1dde716e
PL
464 return 0;
465}
c589b249 466
1dde716e
PL
467static BlockDriverAIOCB *
468iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
469 QEMUIOVector *qiov, int nb_sectors,
470 BlockDriverCompletionFunc *cb,
471 void *opaque)
472{
473 IscsiLun *iscsilun = bs->opaque;
474 IscsiAIOCB *acb;
475
91bea4e2
PL
476 if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
477 return NULL;
478 }
479
1dde716e
PL
480 acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
481 trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
482
483 acb->nb_sectors = nb_sectors;
484 acb->sector_num = sector_num;
485 acb->iscsilun = iscsilun;
486 acb->qiov = qiov;
1dde716e
PL
487 acb->retries = ISCSI_CMD_RETRIES;
488
489 if (iscsi_aio_readv_acb(acb) != 0) {
1dde716e
PL
490 qemu_aio_release(acb);
491 return NULL;
492 }
c589b249 493
1dde716e 494 iscsi_set_events(iscsilun);
c589b249
RS
495 return &acb->common;
496}
497
1dde716e
PL
498static int
499iscsi_aio_flush_acb(IscsiAIOCB *acb);
c589b249
RS
500
501static void
502iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
503 void *command_data, void *opaque)
504{
505 IscsiAIOCB *acb = opaque;
506
b2090919 507 if (acb->canceled != 0) {
c589b249
RS
508 return;
509 }
510
511 acb->status = 0;
1dde716e
PL
512 if (status != 0) {
513 if (status == SCSI_STATUS_CHECK_CONDITION
514 && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
515 && acb->retries-- > 0) {
f0d2a4d4
PB
516 scsi_free_scsi_task(acb->task);
517 acb->task = NULL;
1dde716e
PL
518 if (iscsi_aio_flush_acb(acb) == 0) {
519 iscsi_set_events(acb->iscsilun);
520 return;
521 }
522 }
c589b249
RS
523 error_report("Failed to sync10 data on iSCSI lun. %s",
524 iscsi_get_error(iscsi));
525 acb->status = -EIO;
526 }
527
cfb3f506 528 iscsi_schedule_bh(acb);
c589b249
RS
529}
530
1dde716e
PL
531static int
532iscsi_aio_flush_acb(IscsiAIOCB *acb)
c589b249 533{
1dde716e 534 struct iscsi_context *iscsi = acb->iscsilun->iscsi;
c589b249 535
c589b249 536 acb->canceled = 0;
1bd075f2
PB
537 acb->bh = NULL;
538 acb->status = -EINPROGRESS;
4790b03d 539 acb->buf = NULL;
c589b249 540
1dde716e 541 acb->task = iscsi_synchronizecache10_task(iscsi, acb->iscsilun->lun,
c589b249
RS
542 0, 0, 0, 0,
543 iscsi_synccache10_cb,
544 acb);
545 if (acb->task == NULL) {
546 error_report("iSCSI: Failed to send synchronizecache10 command. %s",
547 iscsi_get_error(iscsi));
1dde716e
PL
548 return -1;
549 }
550
551 return 0;
552}
553
554static BlockDriverAIOCB *
555iscsi_aio_flush(BlockDriverState *bs,
556 BlockDriverCompletionFunc *cb, void *opaque)
557{
558 IscsiLun *iscsilun = bs->opaque;
559
560 IscsiAIOCB *acb;
561
562 acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
563
564 acb->iscsilun = iscsilun;
565 acb->retries = ISCSI_CMD_RETRIES;
566
567 if (iscsi_aio_flush_acb(acb) != 0) {
c589b249
RS
568 qemu_aio_release(acb);
569 return NULL;
570 }
571
572 iscsi_set_events(iscsilun);
573
574 return &acb->common;
575}
576
1dde716e
PL
577static int iscsi_aio_discard_acb(IscsiAIOCB *acb);
578
fa6acb0c
RS
579static void
580iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
581 void *command_data, void *opaque)
582{
583 IscsiAIOCB *acb = opaque;
584
b2090919 585 if (acb->canceled != 0) {
fa6acb0c
RS
586 return;
587 }
588
589 acb->status = 0;
1dde716e
PL
590 if (status != 0) {
591 if (status == SCSI_STATUS_CHECK_CONDITION
592 && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
593 && acb->retries-- > 0) {
f0d2a4d4
PB
594 scsi_free_scsi_task(acb->task);
595 acb->task = NULL;
1dde716e
PL
596 if (iscsi_aio_discard_acb(acb) == 0) {
597 iscsi_set_events(acb->iscsilun);
598 return;
599 }
600 }
fa6acb0c
RS
601 error_report("Failed to unmap data on iSCSI lun. %s",
602 iscsi_get_error(iscsi));
603 acb->status = -EIO;
604 }
605
cfb3f506 606 iscsi_schedule_bh(acb);
fa6acb0c
RS
607}
608
1dde716e
PL
609static int iscsi_aio_discard_acb(IscsiAIOCB *acb) {
610 struct iscsi_context *iscsi = acb->iscsilun->iscsi;
fa6acb0c
RS
611 struct unmap_list list[1];
612
fa6acb0c 613 acb->canceled = 0;
1bd075f2
PB
614 acb->bh = NULL;
615 acb->status = -EINPROGRESS;
4790b03d 616 acb->buf = NULL;
fa6acb0c 617
1dde716e
PL
618 list[0].lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
619 list[0].num = acb->nb_sectors * BDRV_SECTOR_SIZE / acb->iscsilun->block_size;
fa6acb0c 620
1dde716e 621 acb->task = iscsi_unmap_task(iscsi, acb->iscsilun->lun,
fa6acb0c
RS
622 0, 0, &list[0], 1,
623 iscsi_unmap_cb,
624 acb);
625 if (acb->task == NULL) {
626 error_report("iSCSI: Failed to send unmap command. %s",
627 iscsi_get_error(iscsi));
1dde716e
PL
628 return -1;
629 }
630
631 return 0;
632}
633
634static BlockDriverAIOCB *
635iscsi_aio_discard(BlockDriverState *bs,
636 int64_t sector_num, int nb_sectors,
637 BlockDriverCompletionFunc *cb, void *opaque)
638{
639 IscsiLun *iscsilun = bs->opaque;
640 IscsiAIOCB *acb;
641
642 acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
643
644 acb->iscsilun = iscsilun;
645 acb->nb_sectors = nb_sectors;
646 acb->sector_num = sector_num;
647 acb->retries = ISCSI_CMD_RETRIES;
648
649 if (iscsi_aio_discard_acb(acb) != 0) {
fa6acb0c
RS
650 qemu_aio_release(acb);
651 return NULL;
652 }
653
654 iscsi_set_events(iscsilun);
655
656 return &acb->common;
657}
658
98392453
RS
659#ifdef __linux__
660static void
661iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
662 void *command_data, void *opaque)
663{
664 IscsiAIOCB *acb = opaque;
665
0a53f010
RS
666 g_free(acb->buf);
667 acb->buf = NULL;
668
b2090919 669 if (acb->canceled != 0) {
98392453
RS
670 return;
671 }
672
673 acb->status = 0;
674 if (status < 0) {
675 error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
676 iscsi_get_error(iscsi));
677 acb->status = -EIO;
678 }
679
680 acb->ioh->driver_status = 0;
681 acb->ioh->host_status = 0;
682 acb->ioh->resid = 0;
683
684#define SG_ERR_DRIVER_SENSE 0x08
685
686 if (status == SCSI_STATUS_CHECK_CONDITION && acb->task->datain.size >= 2) {
687 int ss;
688
689 acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
690
691 acb->ioh->sb_len_wr = acb->task->datain.size - 2;
692 ss = (acb->ioh->mx_sb_len >= acb->ioh->sb_len_wr) ?
693 acb->ioh->mx_sb_len : acb->ioh->sb_len_wr;
694 memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
695 }
696
cfb3f506 697 iscsi_schedule_bh(acb);
98392453
RS
698}
699
700static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
701 unsigned long int req, void *buf,
702 BlockDriverCompletionFunc *cb, void *opaque)
703{
704 IscsiLun *iscsilun = bs->opaque;
705 struct iscsi_context *iscsi = iscsilun->iscsi;
706 struct iscsi_data data;
707 IscsiAIOCB *acb;
708
709 assert(req == SG_IO);
710
d7331bed 711 acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
98392453
RS
712
713 acb->iscsilun = iscsilun;
714 acb->canceled = 0;
1bd075f2
PB
715 acb->bh = NULL;
716 acb->status = -EINPROGRESS;
98392453
RS
717 acb->buf = NULL;
718 acb->ioh = buf;
719
720 acb->task = malloc(sizeof(struct scsi_task));
721 if (acb->task == NULL) {
722 error_report("iSCSI: Failed to allocate task for scsi command. %s",
723 iscsi_get_error(iscsi));
724 qemu_aio_release(acb);
725 return NULL;
726 }
727 memset(acb->task, 0, sizeof(struct scsi_task));
728
729 switch (acb->ioh->dxfer_direction) {
730 case SG_DXFER_TO_DEV:
731 acb->task->xfer_dir = SCSI_XFER_WRITE;
732 break;
733 case SG_DXFER_FROM_DEV:
734 acb->task->xfer_dir = SCSI_XFER_READ;
735 break;
736 default:
737 acb->task->xfer_dir = SCSI_XFER_NONE;
738 break;
739 }
740
741 acb->task->cdb_size = acb->ioh->cmd_len;
742 memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
743 acb->task->expxferlen = acb->ioh->dxfer_len;
744
0a53f010 745 data.size = 0;
98392453 746 if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
0a53f010
RS
747 if (acb->ioh->iovec_count == 0) {
748 data.data = acb->ioh->dxferp;
749 data.size = acb->ioh->dxfer_len;
750 } else {
751#if defined(LIBISCSI_FEATURE_IOVECTOR)
752 scsi_task_set_iov_out(acb->task,
753 (struct scsi_iovec *) acb->ioh->dxferp,
754 acb->ioh->iovec_count);
755#else
756 struct iovec *iov = (struct iovec *)acb->ioh->dxferp;
757
758 acb->buf = g_malloc(acb->ioh->dxfer_len);
759 data.data = acb->buf;
760 data.size = iov_to_buf(iov, acb->ioh->iovec_count, 0,
761 acb->buf, acb->ioh->dxfer_len);
762#endif
763 }
98392453 764 }
0a53f010 765
98392453
RS
766 if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
767 iscsi_aio_ioctl_cb,
0a53f010 768 (data.size > 0) ? &data : NULL,
98392453
RS
769 acb) != 0) {
770 scsi_free_scsi_task(acb->task);
771 qemu_aio_release(acb);
772 return NULL;
773 }
774
775 /* tell libiscsi to read straight into the buffer we got from ioctl */
776 if (acb->task->xfer_dir == SCSI_XFER_READ) {
0a53f010
RS
777 if (acb->ioh->iovec_count == 0) {
778 scsi_task_add_data_in_buffer(acb->task,
779 acb->ioh->dxfer_len,
780 acb->ioh->dxferp);
781 } else {
782#if defined(LIBISCSI_FEATURE_IOVECTOR)
783 scsi_task_set_iov_in(acb->task,
784 (struct scsi_iovec *) acb->ioh->dxferp,
785 acb->ioh->iovec_count);
786#else
787 int i;
788 for (i = 0; i < acb->ioh->iovec_count; i++) {
789 struct iovec *iov = (struct iovec *)acb->ioh->dxferp;
790
791 scsi_task_add_data_in_buffer(acb->task,
792 iov[i].iov_len,
793 iov[i].iov_base);
794 }
795#endif
796 }
98392453
RS
797 }
798
799 iscsi_set_events(iscsilun);
800
801 return &acb->common;
802}
803
f1a12821
RS
804
805static void ioctl_cb(void *opaque, int status)
806{
807 int *p_status = opaque;
808 *p_status = status;
809}
810
98392453
RS
811static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
812{
813 IscsiLun *iscsilun = bs->opaque;
f1a12821 814 int status;
98392453
RS
815
816 switch (req) {
817 case SG_GET_VERSION_NUM:
818 *(int *)buf = 30000;
819 break;
820 case SG_GET_SCSI_ID:
821 ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
822 break;
f1a12821
RS
823 case SG_IO:
824 status = -EINPROGRESS;
825 iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
826
827 while (status == -EINPROGRESS) {
828 qemu_aio_wait();
829 }
830
831 return 0;
98392453
RS
832 default:
833 return -1;
834 }
835 return 0;
836}
837#endif
838
c589b249
RS
839static int64_t
840iscsi_getlength(BlockDriverState *bs)
841{
842 IscsiLun *iscsilun = bs->opaque;
843 int64_t len;
844
845 len = iscsilun->num_blocks;
846 len *= iscsilun->block_size;
847
848 return len;
849}
850
f9dadc98
RS
851static int parse_chap(struct iscsi_context *iscsi, const char *target)
852{
853 QemuOptsList *list;
854 QemuOpts *opts;
855 const char *user = NULL;
856 const char *password = NULL;
857
858 list = qemu_find_opts("iscsi");
859 if (!list) {
860 return 0;
861 }
862
863 opts = qemu_opts_find(list, target);
864 if (opts == NULL) {
865 opts = QTAILQ_FIRST(&list->head);
866 if (!opts) {
867 return 0;
868 }
869 }
870
871 user = qemu_opt_get(opts, "user");
872 if (!user) {
873 return 0;
874 }
875
876 password = qemu_opt_get(opts, "password");
877 if (!password) {
878 error_report("CHAP username specified but no password was given");
879 return -1;
880 }
881
882 if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
883 error_report("Failed to set initiator username and password");
884 return -1;
885 }
886
887 return 0;
888}
889
890static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
891{
892 QemuOptsList *list;
893 QemuOpts *opts;
894 const char *digest = NULL;
895
896 list = qemu_find_opts("iscsi");
897 if (!list) {
898 return;
899 }
900
901 opts = qemu_opts_find(list, target);
902 if (opts == NULL) {
903 opts = QTAILQ_FIRST(&list->head);
904 if (!opts) {
905 return;
906 }
907 }
908
909 digest = qemu_opt_get(opts, "header-digest");
910 if (!digest) {
911 return;
912 }
913
914 if (!strcmp(digest, "CRC32C")) {
915 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
916 } else if (!strcmp(digest, "NONE")) {
917 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
918 } else if (!strcmp(digest, "CRC32C-NONE")) {
919 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
920 } else if (!strcmp(digest, "NONE-CRC32C")) {
921 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
922 } else {
923 error_report("Invalid header-digest setting : %s", digest);
924 }
925}
926
927static char *parse_initiator_name(const char *target)
928{
929 QemuOptsList *list;
930 QemuOpts *opts;
931 const char *name = NULL;
31459f46 932 const char *iscsi_name = qemu_get_vm_name();
f9dadc98
RS
933
934 list = qemu_find_opts("iscsi");
f2ef4a6d
PB
935 if (list) {
936 opts = qemu_opts_find(list, target);
f9dadc98 937 if (!opts) {
f2ef4a6d
PB
938 opts = QTAILQ_FIRST(&list->head);
939 }
940 if (opts) {
941 name = qemu_opt_get(opts, "initiator-name");
f9dadc98
RS
942 }
943 }
944
f2ef4a6d
PB
945 if (name) {
946 return g_strdup(name);
947 } else {
31459f46
RS
948 return g_strdup_printf("iqn.2008-11.org.linux-kvm%s%s",
949 iscsi_name ? ":" : "",
950 iscsi_name ? iscsi_name : "");
f9dadc98 951 }
f9dadc98
RS
952}
953
5b5d34ec
PL
954#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
955static void iscsi_nop_timed_event(void *opaque)
956{
957 IscsiLun *iscsilun = opaque;
958
959 if (iscsi_get_nops_in_flight(iscsilun->iscsi) > MAX_NOP_FAILURES) {
960 error_report("iSCSI: NOP timeout. Reconnecting...");
961 iscsi_reconnect(iscsilun->iscsi);
962 }
963
964 if (iscsi_nop_out_async(iscsilun->iscsi, NULL, NULL, 0, NULL) != 0) {
965 error_report("iSCSI: failed to sent NOP-Out. Disabling NOP messages.");
966 return;
967 }
968
969 qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
970 iscsi_set_events(iscsilun);
971}
972#endif
973
cb1b83e7
PL
974static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
975{
976 struct scsi_task *task = NULL;
977 struct scsi_readcapacity10 *rc10 = NULL;
978 struct scsi_readcapacity16 *rc16 = NULL;
979 int ret = 0;
980 int retries = ISCSI_CMD_RETRIES;
981
1288844e
PB
982 do {
983 if (task != NULL) {
984 scsi_free_scsi_task(task);
985 task = NULL;
cb1b83e7 986 }
1288844e
PB
987
988 switch (iscsilun->type) {
989 case TYPE_DISK:
990 task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
991 if (task != NULL && task->status == SCSI_STATUS_GOOD) {
992 rc16 = scsi_datain_unmarshall(task);
993 if (rc16 == NULL) {
994 error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
995 ret = -EINVAL;
996 } else {
997 iscsilun->block_size = rc16->block_length;
998 iscsilun->num_blocks = rc16->returned_lba + 1;
999 }
1000 }
1001 break;
1002 case TYPE_ROM:
1003 task = iscsi_readcapacity10_sync(iscsilun->iscsi, iscsilun->lun, 0, 0);
1004 if (task != NULL && task->status == SCSI_STATUS_GOOD) {
1005 rc10 = scsi_datain_unmarshall(task);
1006 if (rc10 == NULL) {
1007 error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
1008 ret = -EINVAL;
1009 } else {
1010 iscsilun->block_size = rc10->block_size;
1011 if (rc10->lba == 0) {
1012 /* blank disk loaded */
1013 iscsilun->num_blocks = 0;
1014 } else {
1015 iscsilun->num_blocks = rc10->lba + 1;
1016 }
1017 }
1018 }
1019 break;
1020 default:
1021 return 0;
cb1b83e7 1022 }
1288844e
PB
1023 } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
1024 && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
1025 && retries-- > 0);
cb1b83e7 1026
1288844e
PB
1027 if (task == NULL || task->status != SCSI_STATUS_GOOD) {
1028 error_report("iSCSI: failed to send readcapacity10 command.");
1029 ret = -EINVAL;
1030 }
cb1b83e7
PL
1031 if (task) {
1032 scsi_free_scsi_task(task);
1033 }
cb1b83e7
PL
1034 return ret;
1035}
1036
60beb341
KW
1037/* TODO Convert to fine grained options */
1038static QemuOptsList runtime_opts = {
1039 .name = "iscsi",
1040 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
1041 .desc = {
1042 {
1043 .name = "filename",
1044 .type = QEMU_OPT_STRING,
1045 .help = "URL to the iscsi image",
1046 },
1047 { /* end of list */ }
1048 },
1049};
1050
c589b249
RS
1051/*
1052 * We support iscsi url's on the form
1053 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
1054 */
56d1b4d2 1055static int iscsi_open(BlockDriverState *bs, QDict *options, int flags)
c589b249
RS
1056{
1057 IscsiLun *iscsilun = bs->opaque;
1058 struct iscsi_context *iscsi = NULL;
1059 struct iscsi_url *iscsi_url = NULL;
e829b0bb
PL
1060 struct scsi_task *task = NULL;
1061 struct scsi_inquiry_standard *inq = NULL;
f9dadc98 1062 char *initiator_name = NULL;
60beb341
KW
1063 QemuOpts *opts;
1064 Error *local_err = NULL;
1065 const char *filename;
c589b249
RS
1066 int ret;
1067
1068 if ((BDRV_SECTOR_SIZE % 512) != 0) {
1069 error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
1070 "BDRV_SECTOR_SIZE(%lld) is not a multiple "
1071 "of 512", BDRV_SECTOR_SIZE);
1072 return -EINVAL;
1073 }
1074
60beb341
KW
1075 opts = qemu_opts_create_nofail(&runtime_opts);
1076 qemu_opts_absorb_qdict(opts, options, &local_err);
1077 if (error_is_set(&local_err)) {
1078 qerror_report_err(local_err);
1079 error_free(local_err);
1080 ret = -EINVAL;
1081 goto out;
1082 }
1083
1084 filename = qemu_opt_get(opts, "filename");
1085
1086
c589b249
RS
1087 iscsi_url = iscsi_parse_full_url(iscsi, filename);
1088 if (iscsi_url == NULL) {
8da1e18b 1089 error_report("Failed to parse URL : %s", filename);
c589b249 1090 ret = -EINVAL;
b93c94f7 1091 goto out;
c589b249
RS
1092 }
1093
f9dadc98
RS
1094 memset(iscsilun, 0, sizeof(IscsiLun));
1095
1096 initiator_name = parse_initiator_name(iscsi_url->target);
1097
1098 iscsi = iscsi_create_context(initiator_name);
1099 if (iscsi == NULL) {
1100 error_report("iSCSI: Failed to create iSCSI context.");
1101 ret = -ENOMEM;
b93c94f7 1102 goto out;
f9dadc98
RS
1103 }
1104
c589b249
RS
1105 if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
1106 error_report("iSCSI: Failed to set target name.");
1107 ret = -EINVAL;
b93c94f7 1108 goto out;
c589b249
RS
1109 }
1110
1111 if (iscsi_url->user != NULL) {
1112 ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
1113 iscsi_url->passwd);
1114 if (ret != 0) {
1115 error_report("Failed to set initiator username and password");
1116 ret = -EINVAL;
b93c94f7 1117 goto out;
c589b249
RS
1118 }
1119 }
f9dadc98
RS
1120
1121 /* check if we got CHAP username/password via the options */
1122 if (parse_chap(iscsi, iscsi_url->target) != 0) {
1123 error_report("iSCSI: Failed to set CHAP user/password");
1124 ret = -EINVAL;
b93c94f7 1125 goto out;
f9dadc98
RS
1126 }
1127
c589b249
RS
1128 if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
1129 error_report("iSCSI: Failed to set session type to normal.");
1130 ret = -EINVAL;
b93c94f7 1131 goto out;
c589b249
RS
1132 }
1133
1134 iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
1135
f9dadc98
RS
1136 /* check if we got HEADER_DIGEST via the options */
1137 parse_header_digest(iscsi, iscsi_url->target);
1138
e829b0bb
PL
1139 if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
1140 error_report("iSCSI: Failed to connect to LUN : %s",
1141 iscsi_get_error(iscsi));
1142 ret = -EINVAL;
1143 goto out;
1144 }
c589b249
RS
1145
1146 iscsilun->iscsi = iscsi;
1147 iscsilun->lun = iscsi_url->lun;
1148
e829b0bb
PL
1149 task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
1150
1151 if (task == NULL || task->status != SCSI_STATUS_GOOD) {
1152 error_report("iSCSI: failed to send inquiry command.");
c589b249 1153 ret = -EINVAL;
b93c94f7 1154 goto out;
c589b249
RS
1155 }
1156
e829b0bb
PL
1157 inq = scsi_datain_unmarshall(task);
1158 if (inq == NULL) {
1159 error_report("iSCSI: Failed to unmarshall inquiry data.");
c589b249 1160 ret = -EINVAL;
b93c94f7 1161 goto out;
c589b249 1162 }
622695a4 1163
e829b0bb
PL
1164 iscsilun->type = inq->periperal_device_type;
1165
cb1b83e7
PL
1166 if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
1167 goto out;
e829b0bb 1168 }
0777b5dd 1169 bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
e829b0bb 1170
622695a4
RS
1171 /* Medium changer or tape. We dont have any emulation for this so this must
1172 * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
1173 * to read from the device to guess the image format.
1174 */
1175 if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
1176 iscsilun->type == TYPE_TAPE) {
1177 bs->sg = 1;
1178 }
1179
5b5d34ec
PL
1180#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
1181 /* Set up a timer for sending out iSCSI NOPs */
1182 iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
1183 qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
1184#endif
1185
b93c94f7 1186out:
60beb341 1187 qemu_opts_del(opts);
f9dadc98
RS
1188 if (initiator_name != NULL) {
1189 g_free(initiator_name);
1190 }
c589b249
RS
1191 if (iscsi_url != NULL) {
1192 iscsi_destroy_url(iscsi_url);
1193 }
e829b0bb
PL
1194 if (task != NULL) {
1195 scsi_free_scsi_task(task);
1196 }
b93c94f7
PB
1197
1198 if (ret) {
1199 if (iscsi != NULL) {
1200 iscsi_destroy_context(iscsi);
1201 }
1202 memset(iscsilun, 0, sizeof(IscsiLun));
c589b249 1203 }
c589b249
RS
1204 return ret;
1205}
1206
1207static void iscsi_close(BlockDriverState *bs)
1208{
1209 IscsiLun *iscsilun = bs->opaque;
1210 struct iscsi_context *iscsi = iscsilun->iscsi;
1211
5b5d34ec
PL
1212 if (iscsilun->nop_timer) {
1213 qemu_del_timer(iscsilun->nop_timer);
1214 qemu_free_timer(iscsilun->nop_timer);
1215 }
bafbd6a1 1216 qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
c589b249
RS
1217 iscsi_destroy_context(iscsi);
1218 memset(iscsilun, 0, sizeof(IscsiLun));
1219}
1220
cb1b83e7
PL
1221static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
1222{
1223 IscsiLun *iscsilun = bs->opaque;
1224 int ret = 0;
1225
1226 if (iscsilun->type != TYPE_DISK) {
1227 return -ENOTSUP;
1228 }
1229
1230 if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
1231 return ret;
1232 }
1233
1234 if (offset > iscsi_getlength(bs)) {
1235 return -EINVAL;
1236 }
1237
1238 return 0;
1239}
1240
f807ecd5
PL
1241static int iscsi_has_zero_init(BlockDriverState *bs)
1242{
1243 return 0;
1244}
1245
de8864e5
PL
1246static int iscsi_create(const char *filename, QEMUOptionParameter *options)
1247{
1248 int ret = 0;
1249 int64_t total_size = 0;
1250 BlockDriverState bs;
1251 IscsiLun *iscsilun = NULL;
60beb341 1252 QDict *bs_options;
de8864e5
PL
1253
1254 memset(&bs, 0, sizeof(BlockDriverState));
1255
1256 /* Read out options */
1257 while (options && options->name) {
1258 if (!strcmp(options->name, "size")) {
1259 total_size = options->value.n / BDRV_SECTOR_SIZE;
1260 }
1261 options++;
1262 }
1263
1264 bs.opaque = g_malloc0(sizeof(struct IscsiLun));
1265 iscsilun = bs.opaque;
1266
60beb341
KW
1267 bs_options = qdict_new();
1268 qdict_put(bs_options, "filename", qstring_from_str(filename));
56d1b4d2 1269 ret = iscsi_open(&bs, bs_options, 0);
60beb341
KW
1270 QDECREF(bs_options);
1271
de8864e5
PL
1272 if (ret != 0) {
1273 goto out;
1274 }
5b5d34ec
PL
1275 if (iscsilun->nop_timer) {
1276 qemu_del_timer(iscsilun->nop_timer);
1277 qemu_free_timer(iscsilun->nop_timer);
1278 }
de8864e5
PL
1279 if (iscsilun->type != TYPE_DISK) {
1280 ret = -ENODEV;
1281 goto out;
1282 }
1283 if (bs.total_sectors < total_size) {
1284 ret = -ENOSPC;
d3bda7bc 1285 goto out;
de8864e5
PL
1286 }
1287
1288 ret = 0;
1289out:
1290 if (iscsilun->iscsi != NULL) {
1291 iscsi_destroy_context(iscsilun->iscsi);
1292 }
1293 g_free(bs.opaque);
1294 return ret;
1295}
1296
1297static QEMUOptionParameter iscsi_create_options[] = {
1298 {
1299 .name = BLOCK_OPT_SIZE,
1300 .type = OPT_SIZE,
1301 .help = "Virtual disk size"
1302 },
1303 { NULL }
1304};
1305
c589b249
RS
1306static BlockDriver bdrv_iscsi = {
1307 .format_name = "iscsi",
1308 .protocol_name = "iscsi",
1309
1310 .instance_size = sizeof(IscsiLun),
1311 .bdrv_file_open = iscsi_open,
1312 .bdrv_close = iscsi_close,
de8864e5
PL
1313 .bdrv_create = iscsi_create,
1314 .create_options = iscsi_create_options,
c589b249
RS
1315
1316 .bdrv_getlength = iscsi_getlength,
cb1b83e7 1317 .bdrv_truncate = iscsi_truncate,
c589b249
RS
1318
1319 .bdrv_aio_readv = iscsi_aio_readv,
1320 .bdrv_aio_writev = iscsi_aio_writev,
1321 .bdrv_aio_flush = iscsi_aio_flush,
fa6acb0c
RS
1322
1323 .bdrv_aio_discard = iscsi_aio_discard,
f807ecd5 1324 .bdrv_has_zero_init = iscsi_has_zero_init,
98392453
RS
1325
1326#ifdef __linux__
1327 .bdrv_ioctl = iscsi_ioctl,
1328 .bdrv_aio_ioctl = iscsi_aio_ioctl,
1329#endif
c589b249
RS
1330};
1331
4d454574
PB
1332static QemuOptsList qemu_iscsi_opts = {
1333 .name = "iscsi",
1334 .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
1335 .desc = {
1336 {
1337 .name = "user",
1338 .type = QEMU_OPT_STRING,
1339 .help = "username for CHAP authentication to target",
1340 },{
1341 .name = "password",
1342 .type = QEMU_OPT_STRING,
1343 .help = "password for CHAP authentication to target",
1344 },{
1345 .name = "header-digest",
1346 .type = QEMU_OPT_STRING,
1347 .help = "HeaderDigest setting. "
1348 "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
1349 },{
1350 .name = "initiator-name",
1351 .type = QEMU_OPT_STRING,
1352 .help = "Initiator iqn name to use when connecting",
1353 },
1354 { /* end of list */ }
1355 },
1356};
1357
c589b249
RS
1358static void iscsi_block_init(void)
1359{
1360 bdrv_register(&bdrv_iscsi);
4d454574 1361 qemu_add_opts(&qemu_iscsi_opts);
c589b249
RS
1362}
1363
1364block_init(iscsi_block_init);
This page took 0.358923 seconds and 4 git commands to generate.