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