Statistics
| Branch: | Revision:

root / block / iscsi.c @ 837c3901

History | View | Annotate | Download (42.3 kB)

1 c589b249 Ronnie Sahlberg
/*
2 c589b249 Ronnie Sahlberg
 * QEMU Block driver for iSCSI images
3 c589b249 Ronnie Sahlberg
 *
4 c589b249 Ronnie Sahlberg
 * Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
5 2af8a1a7 Peter Lieven
 * Copyright (c) 2012-2013 Peter Lieven <pl@kamp.de>
6 c589b249 Ronnie Sahlberg
 *
7 c589b249 Ronnie Sahlberg
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 c589b249 Ronnie Sahlberg
 * of this software and associated documentation files (the "Software"), to deal
9 c589b249 Ronnie Sahlberg
 * in the Software without restriction, including without limitation the rights
10 c589b249 Ronnie Sahlberg
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 c589b249 Ronnie Sahlberg
 * copies of the Software, and to permit persons to whom the Software is
12 c589b249 Ronnie Sahlberg
 * furnished to do so, subject to the following conditions:
13 c589b249 Ronnie Sahlberg
 *
14 c589b249 Ronnie Sahlberg
 * The above copyright notice and this permission notice shall be included in
15 c589b249 Ronnie Sahlberg
 * all copies or substantial portions of the Software.
16 c589b249 Ronnie Sahlberg
 *
17 c589b249 Ronnie Sahlberg
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 c589b249 Ronnie Sahlberg
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 c589b249 Ronnie Sahlberg
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 c589b249 Ronnie Sahlberg
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 c589b249 Ronnie Sahlberg
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 c589b249 Ronnie Sahlberg
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 c589b249 Ronnie Sahlberg
 * THE SOFTWARE.
24 c589b249 Ronnie Sahlberg
 */
25 c589b249 Ronnie Sahlberg
26 c589b249 Ronnie Sahlberg
#include "config-host.h"
27 c589b249 Ronnie Sahlberg
28 c589b249 Ronnie Sahlberg
#include <poll.h>
29 f4dfa67f Ronnie Sahlberg
#include <arpa/inet.h>
30 c589b249 Ronnie Sahlberg
#include "qemu-common.h"
31 1de7afc9 Paolo Bonzini
#include "qemu/config-file.h"
32 1de7afc9 Paolo Bonzini
#include "qemu/error-report.h"
33 737e150e Paolo Bonzini
#include "block/block_int.h"
34 c589b249 Ronnie Sahlberg
#include "trace.h"
35 0d09e41a Paolo Bonzini
#include "block/scsi.h"
36 0a53f010 Ronnie Sahlberg
#include "qemu/iov.h"
37 5accc840 Paolo Bonzini
#include "sysemu/sysemu.h"
38 5accc840 Paolo Bonzini
#include "qmp-commands.h"
39 c589b249 Ronnie Sahlberg
40 c589b249 Ronnie Sahlberg
#include <iscsi/iscsi.h>
41 c589b249 Ronnie Sahlberg
#include <iscsi/scsi-lowlevel.h>
42 c589b249 Ronnie Sahlberg
43 98392453 Ronnie Sahlberg
#ifdef __linux__
44 98392453 Ronnie Sahlberg
#include <scsi/sg.h>
45 0d09e41a Paolo Bonzini
#include <block/scsi.h>
46 98392453 Ronnie Sahlberg
#endif
47 c589b249 Ronnie Sahlberg
48 c589b249 Ronnie Sahlberg
typedef struct IscsiLun {
49 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi;
50 c589b249 Ronnie Sahlberg
    int lun;
51 dbfff6d7 Ronnie Sahlberg
    enum scsi_inquiry_peripheral_device_type type;
52 c589b249 Ronnie Sahlberg
    int block_size;
53 c7b4a952 Paolo Bonzini
    uint64_t num_blocks;
54 c9b9f682 Ronnie Sahlberg
    int events;
55 5b5d34ec Peter Lieven
    QEMUTimer *nop_timer;
56 f18a7cbb Peter Lieven
    uint8_t lbpme;
57 f18a7cbb Peter Lieven
    uint8_t lbprz;
58 fa6252b0 Paolo Bonzini
    uint8_t has_write_same;
59 f18a7cbb Peter Lieven
    struct scsi_inquiry_logical_block_provisioning lbp;
60 f18a7cbb Peter Lieven
    struct scsi_inquiry_block_limits bl;
61 d4cd9615 Peter Lieven
    unsigned char *zeroblock;
62 c589b249 Ronnie Sahlberg
} IscsiLun;
63 c589b249 Ronnie Sahlberg
64 54a5c1d5 Peter Lieven
typedef struct IscsiTask {
65 54a5c1d5 Peter Lieven
    int status;
66 54a5c1d5 Peter Lieven
    int complete;
67 54a5c1d5 Peter Lieven
    int retries;
68 54a5c1d5 Peter Lieven
    int do_retry;
69 54a5c1d5 Peter Lieven
    struct scsi_task *task;
70 54a5c1d5 Peter Lieven
    Coroutine *co;
71 8b9dfe90 Peter Lieven
    QEMUBH *bh;
72 54a5c1d5 Peter Lieven
} IscsiTask;
73 54a5c1d5 Peter Lieven
74 c589b249 Ronnie Sahlberg
typedef struct IscsiAIOCB {
75 c589b249 Ronnie Sahlberg
    BlockDriverAIOCB common;
76 c589b249 Ronnie Sahlberg
    QEMUIOVector *qiov;
77 c589b249 Ronnie Sahlberg
    QEMUBH *bh;
78 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun;
79 c589b249 Ronnie Sahlberg
    struct scsi_task *task;
80 c589b249 Ronnie Sahlberg
    uint8_t *buf;
81 c589b249 Ronnie Sahlberg
    int status;
82 c589b249 Ronnie Sahlberg
    int canceled;
83 1dde716e Peter Lieven
    int retries;
84 1dde716e Peter Lieven
    int64_t sector_num;
85 1dde716e Peter Lieven
    int nb_sectors;
86 98392453 Ronnie Sahlberg
#ifdef __linux__
87 98392453 Ronnie Sahlberg
    sg_io_hdr_t *ioh;
88 98392453 Ronnie Sahlberg
#endif
89 c589b249 Ronnie Sahlberg
} IscsiAIOCB;
90 c589b249 Ronnie Sahlberg
91 5b5d34ec Peter Lieven
#define NOP_INTERVAL 5000
92 5b5d34ec Peter Lieven
#define MAX_NOP_FAILURES 3
93 1dde716e Peter Lieven
#define ISCSI_CMD_RETRIES 5
94 5b5d34ec Peter Lieven
95 c589b249 Ronnie Sahlberg
static void
96 cfb3f506 Paolo Bonzini
iscsi_bh_cb(void *p)
97 27cbd828 Paolo Bonzini
{
98 27cbd828 Paolo Bonzini
    IscsiAIOCB *acb = p;
99 27cbd828 Paolo Bonzini
100 27cbd828 Paolo Bonzini
    qemu_bh_delete(acb->bh);
101 27cbd828 Paolo Bonzini
102 4790b03d Paolo Bonzini
    g_free(acb->buf);
103 4790b03d Paolo Bonzini
    acb->buf = NULL;
104 4790b03d Paolo Bonzini
105 27cbd828 Paolo Bonzini
    if (acb->canceled == 0) {
106 27cbd828 Paolo Bonzini
        acb->common.cb(acb->common.opaque, acb->status);
107 27cbd828 Paolo Bonzini
    }
108 27cbd828 Paolo Bonzini
109 1bd075f2 Paolo Bonzini
    if (acb->task != NULL) {
110 1bd075f2 Paolo Bonzini
        scsi_free_scsi_task(acb->task);
111 1bd075f2 Paolo Bonzini
        acb->task = NULL;
112 1bd075f2 Paolo Bonzini
    }
113 1bd075f2 Paolo Bonzini
114 27cbd828 Paolo Bonzini
    qemu_aio_release(acb);
115 27cbd828 Paolo Bonzini
}
116 27cbd828 Paolo Bonzini
117 cfb3f506 Paolo Bonzini
static void
118 cfb3f506 Paolo Bonzini
iscsi_schedule_bh(IscsiAIOCB *acb)
119 27cbd828 Paolo Bonzini
{
120 1bd075f2 Paolo Bonzini
    if (acb->bh) {
121 1bd075f2 Paolo Bonzini
        return;
122 1bd075f2 Paolo Bonzini
    }
123 cfb3f506 Paolo Bonzini
    acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
124 27cbd828 Paolo Bonzini
    qemu_bh_schedule(acb->bh);
125 27cbd828 Paolo Bonzini
}
126 27cbd828 Paolo Bonzini
127 8b9dfe90 Peter Lieven
static void iscsi_co_generic_bh_cb(void *opaque)
128 8b9dfe90 Peter Lieven
{
129 8b9dfe90 Peter Lieven
    struct IscsiTask *iTask = opaque;
130 8b9dfe90 Peter Lieven
    qemu_bh_delete(iTask->bh);
131 8b9dfe90 Peter Lieven
    qemu_coroutine_enter(iTask->co, NULL);
132 8b9dfe90 Peter Lieven
}
133 8b9dfe90 Peter Lieven
134 54a5c1d5 Peter Lieven
static void
135 54a5c1d5 Peter Lieven
iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
136 54a5c1d5 Peter Lieven
                        void *command_data, void *opaque)
137 54a5c1d5 Peter Lieven
{
138 54a5c1d5 Peter Lieven
    struct IscsiTask *iTask = opaque;
139 54a5c1d5 Peter Lieven
    struct scsi_task *task = command_data;
140 54a5c1d5 Peter Lieven
141 54a5c1d5 Peter Lieven
    iTask->complete = 1;
142 54a5c1d5 Peter Lieven
    iTask->status = status;
143 54a5c1d5 Peter Lieven
    iTask->do_retry = 0;
144 54a5c1d5 Peter Lieven
    iTask->task = task;
145 54a5c1d5 Peter Lieven
146 54a5c1d5 Peter Lieven
    if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
147 54a5c1d5 Peter Lieven
        && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
148 837c3901 Peter Lieven
        error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi));
149 54a5c1d5 Peter Lieven
        iTask->do_retry = 1;
150 54a5c1d5 Peter Lieven
        goto out;
151 54a5c1d5 Peter Lieven
    }
152 54a5c1d5 Peter Lieven
153 54a5c1d5 Peter Lieven
    if (status != SCSI_STATUS_GOOD) {
154 837c3901 Peter Lieven
        error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
155 54a5c1d5 Peter Lieven
    }
156 54a5c1d5 Peter Lieven
157 54a5c1d5 Peter Lieven
out:
158 54a5c1d5 Peter Lieven
    if (iTask->co) {
159 8b9dfe90 Peter Lieven
        iTask->bh = qemu_bh_new(iscsi_co_generic_bh_cb, iTask);
160 8b9dfe90 Peter Lieven
        qemu_bh_schedule(iTask->bh);
161 54a5c1d5 Peter Lieven
    }
162 54a5c1d5 Peter Lieven
}
163 54a5c1d5 Peter Lieven
164 54a5c1d5 Peter Lieven
static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
165 54a5c1d5 Peter Lieven
{
166 54a5c1d5 Peter Lieven
    *iTask = (struct IscsiTask) {
167 54a5c1d5 Peter Lieven
        .co         = qemu_coroutine_self(),
168 54a5c1d5 Peter Lieven
        .retries    = ISCSI_CMD_RETRIES,
169 54a5c1d5 Peter Lieven
    };
170 54a5c1d5 Peter Lieven
}
171 27cbd828 Paolo Bonzini
172 27cbd828 Paolo Bonzini
static void
173 c589b249 Ronnie Sahlberg
iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
174 c589b249 Ronnie Sahlberg
                    void *private_data)
175 c589b249 Ronnie Sahlberg
{
176 1bd075f2 Paolo Bonzini
    IscsiAIOCB *acb = private_data;
177 1bd075f2 Paolo Bonzini
178 1bd075f2 Paolo Bonzini
    acb->status = -ECANCELED;
179 1bd075f2 Paolo Bonzini
    iscsi_schedule_bh(acb);
180 c589b249 Ronnie Sahlberg
}
181 c589b249 Ronnie Sahlberg
182 c589b249 Ronnie Sahlberg
static void
183 c589b249 Ronnie Sahlberg
iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
184 c589b249 Ronnie Sahlberg
{
185 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
186 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = acb->iscsilun;
187 c589b249 Ronnie Sahlberg
188 1bd075f2 Paolo Bonzini
    if (acb->status != -EINPROGRESS) {
189 1bd075f2 Paolo Bonzini
        return;
190 1bd075f2 Paolo Bonzini
    }
191 1bd075f2 Paolo Bonzini
192 b2090919 Paolo Bonzini
    acb->canceled = 1;
193 c589b249 Ronnie Sahlberg
194 b2090919 Paolo Bonzini
    /* send a task mgmt call to the target to cancel the task on the target */
195 64e69e80 Stefan Priebe
    iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
196 1bd075f2 Paolo Bonzini
                                     iscsi_abort_task_cb, acb);
197 b2090919 Paolo Bonzini
198 1bd075f2 Paolo Bonzini
    while (acb->status == -EINPROGRESS) {
199 1bd075f2 Paolo Bonzini
        qemu_aio_wait();
200 1bd075f2 Paolo Bonzini
    }
201 c589b249 Ronnie Sahlberg
}
202 c589b249 Ronnie Sahlberg
203 d7331bed Stefan Hajnoczi
static const AIOCBInfo iscsi_aiocb_info = {
204 c589b249 Ronnie Sahlberg
    .aiocb_size         = sizeof(IscsiAIOCB),
205 c589b249 Ronnie Sahlberg
    .cancel             = iscsi_aio_cancel,
206 c589b249 Ronnie Sahlberg
};
207 c589b249 Ronnie Sahlberg
208 c589b249 Ronnie Sahlberg
209 c589b249 Ronnie Sahlberg
static void iscsi_process_read(void *arg);
210 c589b249 Ronnie Sahlberg
static void iscsi_process_write(void *arg);
211 c589b249 Ronnie Sahlberg
212 c589b249 Ronnie Sahlberg
static void
213 c589b249 Ronnie Sahlberg
iscsi_set_events(IscsiLun *iscsilun)
214 c589b249 Ronnie Sahlberg
{
215 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
216 c9b9f682 Ronnie Sahlberg
    int ev;
217 c9b9f682 Ronnie Sahlberg
218 c9b9f682 Ronnie Sahlberg
    /* We always register a read handler.  */
219 c9b9f682 Ronnie Sahlberg
    ev = POLLIN;
220 c9b9f682 Ronnie Sahlberg
    ev |= iscsi_which_events(iscsi);
221 c9b9f682 Ronnie Sahlberg
    if (ev != iscsilun->events) {
222 c9b9f682 Ronnie Sahlberg
        qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
223 c9b9f682 Ronnie Sahlberg
                      iscsi_process_read,
224 c9b9f682 Ronnie Sahlberg
                      (ev & POLLOUT) ? iscsi_process_write : NULL,
225 c9b9f682 Ronnie Sahlberg
                      iscsilun);
226 c9b9f682 Ronnie Sahlberg
227 c9b9f682 Ronnie Sahlberg
    }
228 c9b9f682 Ronnie Sahlberg
229 c9b9f682 Ronnie Sahlberg
    iscsilun->events = ev;
230 c589b249 Ronnie Sahlberg
}
231 c589b249 Ronnie Sahlberg
232 c589b249 Ronnie Sahlberg
static void
233 c589b249 Ronnie Sahlberg
iscsi_process_read(void *arg)
234 c589b249 Ronnie Sahlberg
{
235 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = arg;
236 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
237 c589b249 Ronnie Sahlberg
238 c589b249 Ronnie Sahlberg
    iscsi_service(iscsi, POLLIN);
239 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
240 c589b249 Ronnie Sahlberg
}
241 c589b249 Ronnie Sahlberg
242 c589b249 Ronnie Sahlberg
static void
243 c589b249 Ronnie Sahlberg
iscsi_process_write(void *arg)
244 c589b249 Ronnie Sahlberg
{
245 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = arg;
246 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
247 c589b249 Ronnie Sahlberg
248 c589b249 Ronnie Sahlberg
    iscsi_service(iscsi, POLLOUT);
249 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
250 c589b249 Ronnie Sahlberg
}
251 c589b249 Ronnie Sahlberg
252 0777b5dd Peter Lieven
static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun)
253 0777b5dd Peter Lieven
{
254 0777b5dd Peter Lieven
    return sector * iscsilun->block_size / BDRV_SECTOR_SIZE;
255 0777b5dd Peter Lieven
}
256 0777b5dd Peter Lieven
257 c589b249 Ronnie Sahlberg
static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
258 c589b249 Ronnie Sahlberg
{
259 c589b249 Ronnie Sahlberg
    return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
260 c589b249 Ronnie Sahlberg
}
261 c589b249 Ronnie Sahlberg
262 91bea4e2 Peter Lieven
static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
263 91bea4e2 Peter Lieven
                                      IscsiLun *iscsilun)
264 91bea4e2 Peter Lieven
{
265 91bea4e2 Peter Lieven
    if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size ||
266 91bea4e2 Peter Lieven
        (nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) {
267 f5075224 Richard W.M. Jones
            error_report("iSCSI misaligned request: "
268 f5075224 Richard W.M. Jones
                         "iscsilun->block_size %u, sector_num %" PRIi64
269 f5075224 Richard W.M. Jones
                         ", nb_sectors %d",
270 91bea4e2 Peter Lieven
                         iscsilun->block_size, sector_num, nb_sectors);
271 91bea4e2 Peter Lieven
            return 0;
272 91bea4e2 Peter Lieven
    }
273 91bea4e2 Peter Lieven
    return 1;
274 91bea4e2 Peter Lieven
}
275 91bea4e2 Peter Lieven
276 063c3378 Peter Lieven
static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
277 063c3378 Peter Lieven
                                        int64_t sector_num, int nb_sectors,
278 063c3378 Peter Lieven
                                        QEMUIOVector *iov)
279 c589b249 Ronnie Sahlberg
{
280 063c3378 Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
281 063c3378 Peter Lieven
    struct IscsiTask iTask;
282 f4dfa67f Ronnie Sahlberg
    uint64_t lba;
283 063c3378 Peter Lieven
    uint32_t num_sectors;
284 063c3378 Peter Lieven
    uint8_t *data = NULL;
285 063c3378 Peter Lieven
    uint8_t *buf = NULL;
286 c589b249 Ronnie Sahlberg
287 063c3378 Peter Lieven
    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
288 063c3378 Peter Lieven
        return -EINVAL;
289 063c3378 Peter Lieven
    }
290 7371d56f Peter Lieven
291 063c3378 Peter Lieven
    lba = sector_qemu2lun(sector_num, iscsilun);
292 063c3378 Peter Lieven
    num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
293 7371d56f Peter Lieven
#if !defined(LIBISCSI_FEATURE_IOVECTOR)
294 4cc841b5 Peter Lieven
    /* if the iovec only contains one buffer we can pass it directly */
295 063c3378 Peter Lieven
    if (iov->niov == 1) {
296 063c3378 Peter Lieven
        data = iov->iov[0].iov_base;
297 4cc841b5 Peter Lieven
    } else {
298 063c3378 Peter Lieven
        size_t size = MIN(nb_sectors * BDRV_SECTOR_SIZE, iov->size);
299 063c3378 Peter Lieven
        buf = g_malloc(size);
300 063c3378 Peter Lieven
        qemu_iovec_to_buf(iov, 0, buf, size);
301 063c3378 Peter Lieven
        data = buf;
302 4cc841b5 Peter Lieven
    }
303 7371d56f Peter Lieven
#endif
304 063c3378 Peter Lieven
    iscsi_co_init_iscsitask(iscsilun, &iTask);
305 063c3378 Peter Lieven
retry:
306 063c3378 Peter Lieven
    iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
307 063c3378 Peter Lieven
                                    data, num_sectors * iscsilun->block_size,
308 063c3378 Peter Lieven
                                    iscsilun->block_size, 0, 0, 0, 0, 0,
309 063c3378 Peter Lieven
                                    iscsi_co_generic_cb, &iTask);
310 063c3378 Peter Lieven
    if (iTask.task == NULL) {
311 063c3378 Peter Lieven
        g_free(buf);
312 92397116 Peter Lieven
        return -ENOMEM;
313 f4dfa67f Ronnie Sahlberg
    }
314 7371d56f Peter Lieven
#if defined(LIBISCSI_FEATURE_IOVECTOR)
315 063c3378 Peter Lieven
    scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
316 063c3378 Peter Lieven
                          iov->niov);
317 7371d56f Peter Lieven
#endif
318 063c3378 Peter Lieven
    while (!iTask.complete) {
319 063c3378 Peter Lieven
        iscsi_set_events(iscsilun);
320 063c3378 Peter Lieven
        qemu_coroutine_yield();
321 c589b249 Ronnie Sahlberg
    }
322 c589b249 Ronnie Sahlberg
323 063c3378 Peter Lieven
    if (iTask.task != NULL) {
324 063c3378 Peter Lieven
        scsi_free_scsi_task(iTask.task);
325 063c3378 Peter Lieven
        iTask.task = NULL;
326 91bea4e2 Peter Lieven
    }
327 91bea4e2 Peter Lieven
328 063c3378 Peter Lieven
    if (iTask.do_retry) {
329 837c3901 Peter Lieven
        iTask.complete = 0;
330 063c3378 Peter Lieven
        goto retry;
331 1dde716e Peter Lieven
    }
332 1dde716e Peter Lieven
333 063c3378 Peter Lieven
    g_free(buf);
334 c589b249 Ronnie Sahlberg
335 063c3378 Peter Lieven
    if (iTask.status != SCSI_STATUS_GOOD) {
336 063c3378 Peter Lieven
        return -EIO;
337 c589b249 Ronnie Sahlberg
    }
338 c589b249 Ronnie Sahlberg
339 063c3378 Peter Lieven
    return 0;
340 c589b249 Ronnie Sahlberg
}
341 c589b249 Ronnie Sahlberg
342 063c3378 Peter Lieven
static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
343 063c3378 Peter Lieven
                                       int64_t sector_num, int nb_sectors,
344 063c3378 Peter Lieven
                                       QEMUIOVector *iov)
345 c589b249 Ronnie Sahlberg
{
346 063c3378 Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
347 063c3378 Peter Lieven
    struct IscsiTask iTask;
348 1dde716e Peter Lieven
    uint64_t lba;
349 1dde716e Peter Lieven
    uint32_t num_sectors;
350 7371d56f Peter Lieven
#if !defined(LIBISCSI_FEATURE_IOVECTOR)
351 c589b249 Ronnie Sahlberg
    int i;
352 7371d56f Peter Lieven
#endif
353 c589b249 Ronnie Sahlberg
354 063c3378 Peter Lieven
    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
355 063c3378 Peter Lieven
        return -EINVAL;
356 f4dfa67f Ronnie Sahlberg
    }
357 f4dfa67f Ronnie Sahlberg
358 063c3378 Peter Lieven
    lba = sector_qemu2lun(sector_num, iscsilun);
359 063c3378 Peter Lieven
    num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
360 f4dfa67f Ronnie Sahlberg
361 063c3378 Peter Lieven
    iscsi_co_init_iscsitask(iscsilun, &iTask);
362 063c3378 Peter Lieven
retry:
363 063c3378 Peter Lieven
    switch (iscsilun->type) {
364 f4dfa67f Ronnie Sahlberg
    case TYPE_DISK:
365 063c3378 Peter Lieven
        iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
366 063c3378 Peter Lieven
                                       num_sectors * iscsilun->block_size,
367 063c3378 Peter Lieven
                                       iscsilun->block_size, 0, 0, 0, 0, 0,
368 063c3378 Peter Lieven
                                       iscsi_co_generic_cb, &iTask);
369 f4dfa67f Ronnie Sahlberg
        break;
370 f4dfa67f Ronnie Sahlberg
    default:
371 063c3378 Peter Lieven
        iTask.task = iscsi_read10_task(iscsilun->iscsi, iscsilun->lun, lba,
372 063c3378 Peter Lieven
                                       num_sectors * iscsilun->block_size,
373 219c2521 Stefan Weil
                                       iscsilun->block_size,
374 219c2521 Stefan Weil
#if !defined(CONFIG_LIBISCSI_1_4) /* API change from 1.4.0 to 1.5.0 */
375 219c2521 Stefan Weil
                                       0, 0, 0, 0, 0,
376 219c2521 Stefan Weil
#endif
377 063c3378 Peter Lieven
                                       iscsi_co_generic_cb, &iTask);
378 f4dfa67f Ronnie Sahlberg
        break;
379 f4dfa67f Ronnie Sahlberg
    }
380 063c3378 Peter Lieven
    if (iTask.task == NULL) {
381 92397116 Peter Lieven
        return -ENOMEM;
382 c589b249 Ronnie Sahlberg
    }
383 7371d56f Peter Lieven
#if defined(LIBISCSI_FEATURE_IOVECTOR)
384 063c3378 Peter Lieven
    scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);
385 7371d56f Peter Lieven
#else
386 063c3378 Peter Lieven
    for (i = 0; i < iov->niov; i++) {
387 063c3378 Peter Lieven
        scsi_task_add_data_in_buffer(iTask.task,
388 063c3378 Peter Lieven
                                     iov->iov[i].iov_len,
389 063c3378 Peter Lieven
                                     iov->iov[i].iov_base);
390 c589b249 Ronnie Sahlberg
    }
391 7371d56f Peter Lieven
#endif
392 91bea4e2 Peter Lieven
393 063c3378 Peter Lieven
    while (!iTask.complete) {
394 063c3378 Peter Lieven
        iscsi_set_events(iscsilun);
395 063c3378 Peter Lieven
        qemu_coroutine_yield();
396 1dde716e Peter Lieven
    }
397 c589b249 Ronnie Sahlberg
398 063c3378 Peter Lieven
    if (iTask.task != NULL) {
399 063c3378 Peter Lieven
        scsi_free_scsi_task(iTask.task);
400 063c3378 Peter Lieven
        iTask.task = NULL;
401 c589b249 Ronnie Sahlberg
    }
402 c589b249 Ronnie Sahlberg
403 063c3378 Peter Lieven
    if (iTask.do_retry) {
404 837c3901 Peter Lieven
        iTask.complete = 0;
405 063c3378 Peter Lieven
        goto retry;
406 c589b249 Ronnie Sahlberg
    }
407 c589b249 Ronnie Sahlberg
408 063c3378 Peter Lieven
    if (iTask.status != SCSI_STATUS_GOOD) {
409 063c3378 Peter Lieven
        return -EIO;
410 1dde716e Peter Lieven
    }
411 1dde716e Peter Lieven
412 1dde716e Peter Lieven
    return 0;
413 1dde716e Peter Lieven
}
414 1dde716e Peter Lieven
415 063c3378 Peter Lieven
static int coroutine_fn iscsi_co_flush(BlockDriverState *bs)
416 1dde716e Peter Lieven
{
417 1dde716e Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
418 063c3378 Peter Lieven
    struct IscsiTask iTask;
419 1dde716e Peter Lieven
420 063c3378 Peter Lieven
    iscsi_co_init_iscsitask(iscsilun, &iTask);
421 1dde716e Peter Lieven
422 063c3378 Peter Lieven
retry:
423 063c3378 Peter Lieven
    if (iscsi_synchronizecache10_task(iscsilun->iscsi, iscsilun->lun, 0, 0, 0,
424 063c3378 Peter Lieven
                                      0, iscsi_co_generic_cb, &iTask) == NULL) {
425 92397116 Peter Lieven
        return -ENOMEM;
426 063c3378 Peter Lieven
    }
427 1dde716e Peter Lieven
428 063c3378 Peter Lieven
    while (!iTask.complete) {
429 063c3378 Peter Lieven
        iscsi_set_events(iscsilun);
430 063c3378 Peter Lieven
        qemu_coroutine_yield();
431 063c3378 Peter Lieven
    }
432 1dde716e Peter Lieven
433 063c3378 Peter Lieven
    if (iTask.task != NULL) {
434 063c3378 Peter Lieven
        scsi_free_scsi_task(iTask.task);
435 063c3378 Peter Lieven
        iTask.task = NULL;
436 c589b249 Ronnie Sahlberg
    }
437 c589b249 Ronnie Sahlberg
438 063c3378 Peter Lieven
    if (iTask.do_retry) {
439 837c3901 Peter Lieven
        iTask.complete = 0;
440 063c3378 Peter Lieven
        goto retry;
441 063c3378 Peter Lieven
    }
442 c589b249 Ronnie Sahlberg
443 063c3378 Peter Lieven
    if (iTask.status != SCSI_STATUS_GOOD) {
444 063c3378 Peter Lieven
        return -EIO;
445 063c3378 Peter Lieven
    }
446 063c3378 Peter Lieven
447 063c3378 Peter Lieven
    return 0;
448 c589b249 Ronnie Sahlberg
}
449 c589b249 Ronnie Sahlberg
450 98392453 Ronnie Sahlberg
#ifdef __linux__
451 98392453 Ronnie Sahlberg
static void
452 98392453 Ronnie Sahlberg
iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
453 98392453 Ronnie Sahlberg
                     void *command_data, void *opaque)
454 98392453 Ronnie Sahlberg
{
455 98392453 Ronnie Sahlberg
    IscsiAIOCB *acb = opaque;
456 98392453 Ronnie Sahlberg
457 0a53f010 Ronnie Sahlberg
    g_free(acb->buf);
458 0a53f010 Ronnie Sahlberg
    acb->buf = NULL;
459 0a53f010 Ronnie Sahlberg
460 b2090919 Paolo Bonzini
    if (acb->canceled != 0) {
461 98392453 Ronnie Sahlberg
        return;
462 98392453 Ronnie Sahlberg
    }
463 98392453 Ronnie Sahlberg
464 98392453 Ronnie Sahlberg
    acb->status = 0;
465 98392453 Ronnie Sahlberg
    if (status < 0) {
466 98392453 Ronnie Sahlberg
        error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
467 98392453 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
468 98392453 Ronnie Sahlberg
        acb->status = -EIO;
469 98392453 Ronnie Sahlberg
    }
470 98392453 Ronnie Sahlberg
471 98392453 Ronnie Sahlberg
    acb->ioh->driver_status = 0;
472 98392453 Ronnie Sahlberg
    acb->ioh->host_status   = 0;
473 98392453 Ronnie Sahlberg
    acb->ioh->resid         = 0;
474 98392453 Ronnie Sahlberg
475 98392453 Ronnie Sahlberg
#define SG_ERR_DRIVER_SENSE    0x08
476 98392453 Ronnie Sahlberg
477 98392453 Ronnie Sahlberg
    if (status == SCSI_STATUS_CHECK_CONDITION && acb->task->datain.size >= 2) {
478 98392453 Ronnie Sahlberg
        int ss;
479 98392453 Ronnie Sahlberg
480 98392453 Ronnie Sahlberg
        acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
481 98392453 Ronnie Sahlberg
482 98392453 Ronnie Sahlberg
        acb->ioh->sb_len_wr = acb->task->datain.size - 2;
483 98392453 Ronnie Sahlberg
        ss = (acb->ioh->mx_sb_len >= acb->ioh->sb_len_wr) ?
484 98392453 Ronnie Sahlberg
             acb->ioh->mx_sb_len : acb->ioh->sb_len_wr;
485 98392453 Ronnie Sahlberg
        memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
486 98392453 Ronnie Sahlberg
    }
487 98392453 Ronnie Sahlberg
488 cfb3f506 Paolo Bonzini
    iscsi_schedule_bh(acb);
489 98392453 Ronnie Sahlberg
}
490 98392453 Ronnie Sahlberg
491 98392453 Ronnie Sahlberg
static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
492 98392453 Ronnie Sahlberg
        unsigned long int req, void *buf,
493 98392453 Ronnie Sahlberg
        BlockDriverCompletionFunc *cb, void *opaque)
494 98392453 Ronnie Sahlberg
{
495 98392453 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
496 98392453 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
497 98392453 Ronnie Sahlberg
    struct iscsi_data data;
498 98392453 Ronnie Sahlberg
    IscsiAIOCB *acb;
499 98392453 Ronnie Sahlberg
500 98392453 Ronnie Sahlberg
    assert(req == SG_IO);
501 98392453 Ronnie Sahlberg
502 d7331bed Stefan Hajnoczi
    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
503 98392453 Ronnie Sahlberg
504 98392453 Ronnie Sahlberg
    acb->iscsilun = iscsilun;
505 98392453 Ronnie Sahlberg
    acb->canceled    = 0;
506 1bd075f2 Paolo Bonzini
    acb->bh          = NULL;
507 1bd075f2 Paolo Bonzini
    acb->status      = -EINPROGRESS;
508 98392453 Ronnie Sahlberg
    acb->buf         = NULL;
509 98392453 Ronnie Sahlberg
    acb->ioh         = buf;
510 98392453 Ronnie Sahlberg
511 98392453 Ronnie Sahlberg
    acb->task = malloc(sizeof(struct scsi_task));
512 98392453 Ronnie Sahlberg
    if (acb->task == NULL) {
513 98392453 Ronnie Sahlberg
        error_report("iSCSI: Failed to allocate task for scsi command. %s",
514 98392453 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
515 98392453 Ronnie Sahlberg
        qemu_aio_release(acb);
516 98392453 Ronnie Sahlberg
        return NULL;
517 98392453 Ronnie Sahlberg
    }
518 98392453 Ronnie Sahlberg
    memset(acb->task, 0, sizeof(struct scsi_task));
519 98392453 Ronnie Sahlberg
520 98392453 Ronnie Sahlberg
    switch (acb->ioh->dxfer_direction) {
521 98392453 Ronnie Sahlberg
    case SG_DXFER_TO_DEV:
522 98392453 Ronnie Sahlberg
        acb->task->xfer_dir = SCSI_XFER_WRITE;
523 98392453 Ronnie Sahlberg
        break;
524 98392453 Ronnie Sahlberg
    case SG_DXFER_FROM_DEV:
525 98392453 Ronnie Sahlberg
        acb->task->xfer_dir = SCSI_XFER_READ;
526 98392453 Ronnie Sahlberg
        break;
527 98392453 Ronnie Sahlberg
    default:
528 98392453 Ronnie Sahlberg
        acb->task->xfer_dir = SCSI_XFER_NONE;
529 98392453 Ronnie Sahlberg
        break;
530 98392453 Ronnie Sahlberg
    }
531 98392453 Ronnie Sahlberg
532 98392453 Ronnie Sahlberg
    acb->task->cdb_size = acb->ioh->cmd_len;
533 98392453 Ronnie Sahlberg
    memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
534 98392453 Ronnie Sahlberg
    acb->task->expxferlen = acb->ioh->dxfer_len;
535 98392453 Ronnie Sahlberg
536 0a53f010 Ronnie Sahlberg
    data.size = 0;
537 98392453 Ronnie Sahlberg
    if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
538 0a53f010 Ronnie Sahlberg
        if (acb->ioh->iovec_count == 0) {
539 0a53f010 Ronnie Sahlberg
            data.data = acb->ioh->dxferp;
540 0a53f010 Ronnie Sahlberg
            data.size = acb->ioh->dxfer_len;
541 0a53f010 Ronnie Sahlberg
        } else {
542 0a53f010 Ronnie Sahlberg
#if defined(LIBISCSI_FEATURE_IOVECTOR)
543 0a53f010 Ronnie Sahlberg
            scsi_task_set_iov_out(acb->task,
544 0a53f010 Ronnie Sahlberg
                                 (struct scsi_iovec *) acb->ioh->dxferp,
545 0a53f010 Ronnie Sahlberg
                                 acb->ioh->iovec_count);
546 0a53f010 Ronnie Sahlberg
#else
547 0a53f010 Ronnie Sahlberg
            struct iovec *iov = (struct iovec *)acb->ioh->dxferp;
548 0a53f010 Ronnie Sahlberg
549 0a53f010 Ronnie Sahlberg
            acb->buf = g_malloc(acb->ioh->dxfer_len);
550 0a53f010 Ronnie Sahlberg
            data.data = acb->buf;
551 0a53f010 Ronnie Sahlberg
            data.size = iov_to_buf(iov, acb->ioh->iovec_count, 0,
552 0a53f010 Ronnie Sahlberg
                                   acb->buf, acb->ioh->dxfer_len);
553 0a53f010 Ronnie Sahlberg
#endif
554 0a53f010 Ronnie Sahlberg
        }
555 98392453 Ronnie Sahlberg
    }
556 0a53f010 Ronnie Sahlberg
557 98392453 Ronnie Sahlberg
    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
558 98392453 Ronnie Sahlberg
                                 iscsi_aio_ioctl_cb,
559 0a53f010 Ronnie Sahlberg
                                 (data.size > 0) ? &data : NULL,
560 98392453 Ronnie Sahlberg
                                 acb) != 0) {
561 98392453 Ronnie Sahlberg
        scsi_free_scsi_task(acb->task);
562 98392453 Ronnie Sahlberg
        qemu_aio_release(acb);
563 98392453 Ronnie Sahlberg
        return NULL;
564 98392453 Ronnie Sahlberg
    }
565 98392453 Ronnie Sahlberg
566 98392453 Ronnie Sahlberg
    /* tell libiscsi to read straight into the buffer we got from ioctl */
567 98392453 Ronnie Sahlberg
    if (acb->task->xfer_dir == SCSI_XFER_READ) {
568 0a53f010 Ronnie Sahlberg
        if (acb->ioh->iovec_count == 0) {
569 0a53f010 Ronnie Sahlberg
            scsi_task_add_data_in_buffer(acb->task,
570 0a53f010 Ronnie Sahlberg
                                         acb->ioh->dxfer_len,
571 0a53f010 Ronnie Sahlberg
                                         acb->ioh->dxferp);
572 0a53f010 Ronnie Sahlberg
        } else {
573 0a53f010 Ronnie Sahlberg
#if defined(LIBISCSI_FEATURE_IOVECTOR)
574 0a53f010 Ronnie Sahlberg
            scsi_task_set_iov_in(acb->task,
575 0a53f010 Ronnie Sahlberg
                                 (struct scsi_iovec *) acb->ioh->dxferp,
576 0a53f010 Ronnie Sahlberg
                                 acb->ioh->iovec_count);
577 0a53f010 Ronnie Sahlberg
#else
578 0a53f010 Ronnie Sahlberg
            int i;
579 0a53f010 Ronnie Sahlberg
            for (i = 0; i < acb->ioh->iovec_count; i++) {
580 0a53f010 Ronnie Sahlberg
                struct iovec *iov = (struct iovec *)acb->ioh->dxferp;
581 0a53f010 Ronnie Sahlberg
582 0a53f010 Ronnie Sahlberg
                scsi_task_add_data_in_buffer(acb->task,
583 0a53f010 Ronnie Sahlberg
                    iov[i].iov_len,
584 0a53f010 Ronnie Sahlberg
                    iov[i].iov_base);
585 0a53f010 Ronnie Sahlberg
            }
586 0a53f010 Ronnie Sahlberg
#endif
587 0a53f010 Ronnie Sahlberg
        }
588 98392453 Ronnie Sahlberg
    }
589 98392453 Ronnie Sahlberg
590 98392453 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
591 98392453 Ronnie Sahlberg
592 98392453 Ronnie Sahlberg
    return &acb->common;
593 98392453 Ronnie Sahlberg
}
594 98392453 Ronnie Sahlberg
595 f1a12821 Ronnie Sahlberg
596 f1a12821 Ronnie Sahlberg
static void ioctl_cb(void *opaque, int status)
597 f1a12821 Ronnie Sahlberg
{
598 f1a12821 Ronnie Sahlberg
    int *p_status = opaque;
599 f1a12821 Ronnie Sahlberg
    *p_status = status;
600 f1a12821 Ronnie Sahlberg
}
601 f1a12821 Ronnie Sahlberg
602 98392453 Ronnie Sahlberg
static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
603 98392453 Ronnie Sahlberg
{
604 98392453 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
605 f1a12821 Ronnie Sahlberg
    int status;
606 98392453 Ronnie Sahlberg
607 98392453 Ronnie Sahlberg
    switch (req) {
608 98392453 Ronnie Sahlberg
    case SG_GET_VERSION_NUM:
609 98392453 Ronnie Sahlberg
        *(int *)buf = 30000;
610 98392453 Ronnie Sahlberg
        break;
611 98392453 Ronnie Sahlberg
    case SG_GET_SCSI_ID:
612 98392453 Ronnie Sahlberg
        ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
613 98392453 Ronnie Sahlberg
        break;
614 f1a12821 Ronnie Sahlberg
    case SG_IO:
615 f1a12821 Ronnie Sahlberg
        status = -EINPROGRESS;
616 f1a12821 Ronnie Sahlberg
        iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
617 f1a12821 Ronnie Sahlberg
618 f1a12821 Ronnie Sahlberg
        while (status == -EINPROGRESS) {
619 f1a12821 Ronnie Sahlberg
            qemu_aio_wait();
620 f1a12821 Ronnie Sahlberg
        }
621 f1a12821 Ronnie Sahlberg
622 f1a12821 Ronnie Sahlberg
        return 0;
623 98392453 Ronnie Sahlberg
    default:
624 98392453 Ronnie Sahlberg
        return -1;
625 98392453 Ronnie Sahlberg
    }
626 98392453 Ronnie Sahlberg
    return 0;
627 98392453 Ronnie Sahlberg
}
628 98392453 Ronnie Sahlberg
#endif
629 98392453 Ronnie Sahlberg
630 c589b249 Ronnie Sahlberg
static int64_t
631 c589b249 Ronnie Sahlberg
iscsi_getlength(BlockDriverState *bs)
632 c589b249 Ronnie Sahlberg
{
633 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
634 c589b249 Ronnie Sahlberg
    int64_t len;
635 c589b249 Ronnie Sahlberg
636 c589b249 Ronnie Sahlberg
    len  = iscsilun->num_blocks;
637 c589b249 Ronnie Sahlberg
    len *= iscsilun->block_size;
638 c589b249 Ronnie Sahlberg
639 c589b249 Ronnie Sahlberg
    return len;
640 c589b249 Ronnie Sahlberg
}
641 c589b249 Ronnie Sahlberg
642 24c7608a Peter Lieven
#if defined(LIBISCSI_FEATURE_IOVECTOR)
643 f35c934a Stefan Weil
644 54a5c1d5 Peter Lieven
static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
645 54a5c1d5 Peter Lieven
                                                  int64_t sector_num,
646 54a5c1d5 Peter Lieven
                                                  int nb_sectors, int *pnum)
647 54a5c1d5 Peter Lieven
{
648 54a5c1d5 Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
649 54a5c1d5 Peter Lieven
    struct scsi_get_lba_status *lbas = NULL;
650 54a5c1d5 Peter Lieven
    struct scsi_lba_status_descriptor *lbasd = NULL;
651 54a5c1d5 Peter Lieven
    struct IscsiTask iTask;
652 54a5c1d5 Peter Lieven
    int64_t ret;
653 54a5c1d5 Peter Lieven
654 54a5c1d5 Peter Lieven
    iscsi_co_init_iscsitask(iscsilun, &iTask);
655 54a5c1d5 Peter Lieven
656 54a5c1d5 Peter Lieven
    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
657 54a5c1d5 Peter Lieven
        ret = -EINVAL;
658 54a5c1d5 Peter Lieven
        goto out;
659 54a5c1d5 Peter Lieven
    }
660 54a5c1d5 Peter Lieven
661 54a5c1d5 Peter Lieven
    /* default to all sectors allocated */
662 54a5c1d5 Peter Lieven
    ret = BDRV_BLOCK_DATA;
663 54a5c1d5 Peter Lieven
    ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
664 54a5c1d5 Peter Lieven
    *pnum = nb_sectors;
665 54a5c1d5 Peter Lieven
666 54a5c1d5 Peter Lieven
    /* LUN does not support logical block provisioning */
667 54a5c1d5 Peter Lieven
    if (iscsilun->lbpme == 0) {
668 54a5c1d5 Peter Lieven
        goto out;
669 54a5c1d5 Peter Lieven
    }
670 54a5c1d5 Peter Lieven
671 54a5c1d5 Peter Lieven
retry:
672 54a5c1d5 Peter Lieven
    if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
673 54a5c1d5 Peter Lieven
                                  sector_qemu2lun(sector_num, iscsilun),
674 54a5c1d5 Peter Lieven
                                  8 + 16, iscsi_co_generic_cb,
675 54a5c1d5 Peter Lieven
                                  &iTask) == NULL) {
676 92397116 Peter Lieven
        ret = -ENOMEM;
677 54a5c1d5 Peter Lieven
        goto out;
678 54a5c1d5 Peter Lieven
    }
679 54a5c1d5 Peter Lieven
680 54a5c1d5 Peter Lieven
    while (!iTask.complete) {
681 54a5c1d5 Peter Lieven
        iscsi_set_events(iscsilun);
682 54a5c1d5 Peter Lieven
        qemu_coroutine_yield();
683 54a5c1d5 Peter Lieven
    }
684 54a5c1d5 Peter Lieven
685 54a5c1d5 Peter Lieven
    if (iTask.do_retry) {
686 54a5c1d5 Peter Lieven
        if (iTask.task != NULL) {
687 54a5c1d5 Peter Lieven
            scsi_free_scsi_task(iTask.task);
688 54a5c1d5 Peter Lieven
            iTask.task = NULL;
689 54a5c1d5 Peter Lieven
        }
690 837c3901 Peter Lieven
        iTask.complete = 0;
691 54a5c1d5 Peter Lieven
        goto retry;
692 54a5c1d5 Peter Lieven
    }
693 54a5c1d5 Peter Lieven
694 54a5c1d5 Peter Lieven
    if (iTask.status != SCSI_STATUS_GOOD) {
695 54a5c1d5 Peter Lieven
        /* in case the get_lba_status_callout fails (i.e.
696 54a5c1d5 Peter Lieven
         * because the device is busy or the cmd is not
697 54a5c1d5 Peter Lieven
         * supported) we pretend all blocks are allocated
698 73f395fa Stefan Weil
         * for backwards compatibility */
699 54a5c1d5 Peter Lieven
        goto out;
700 54a5c1d5 Peter Lieven
    }
701 54a5c1d5 Peter Lieven
702 54a5c1d5 Peter Lieven
    lbas = scsi_datain_unmarshall(iTask.task);
703 54a5c1d5 Peter Lieven
    if (lbas == NULL) {
704 54a5c1d5 Peter Lieven
        ret = -EIO;
705 54a5c1d5 Peter Lieven
        goto out;
706 54a5c1d5 Peter Lieven
    }
707 54a5c1d5 Peter Lieven
708 54a5c1d5 Peter Lieven
    lbasd = &lbas->descriptors[0];
709 54a5c1d5 Peter Lieven
710 54a5c1d5 Peter Lieven
    if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
711 54a5c1d5 Peter Lieven
        ret = -EIO;
712 54a5c1d5 Peter Lieven
        goto out;
713 54a5c1d5 Peter Lieven
    }
714 54a5c1d5 Peter Lieven
715 54a5c1d5 Peter Lieven
    *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
716 54a5c1d5 Peter Lieven
    if (*pnum > nb_sectors) {
717 54a5c1d5 Peter Lieven
        *pnum = nb_sectors;
718 54a5c1d5 Peter Lieven
    }
719 54a5c1d5 Peter Lieven
720 54a5c1d5 Peter Lieven
    if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
721 54a5c1d5 Peter Lieven
        lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
722 54a5c1d5 Peter Lieven
        ret &= ~BDRV_BLOCK_DATA;
723 54a5c1d5 Peter Lieven
        if (iscsilun->lbprz) {
724 54a5c1d5 Peter Lieven
            ret |= BDRV_BLOCK_ZERO;
725 54a5c1d5 Peter Lieven
        }
726 54a5c1d5 Peter Lieven
    }
727 54a5c1d5 Peter Lieven
728 54a5c1d5 Peter Lieven
out:
729 54a5c1d5 Peter Lieven
    if (iTask.task != NULL) {
730 54a5c1d5 Peter Lieven
        scsi_free_scsi_task(iTask.task);
731 54a5c1d5 Peter Lieven
    }
732 54a5c1d5 Peter Lieven
    return ret;
733 54a5c1d5 Peter Lieven
}
734 54a5c1d5 Peter Lieven
735 24c7608a Peter Lieven
#endif /* LIBISCSI_FEATURE_IOVECTOR */
736 f35c934a Stefan Weil
737 65f3e339 Peter Lieven
static int
738 65f3e339 Peter Lieven
coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
739 65f3e339 Peter Lieven
                                   int nb_sectors)
740 65f3e339 Peter Lieven
{
741 65f3e339 Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
742 65f3e339 Peter Lieven
    struct IscsiTask iTask;
743 65f3e339 Peter Lieven
    struct unmap_list list;
744 65f3e339 Peter Lieven
745 65f3e339 Peter Lieven
    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
746 65f3e339 Peter Lieven
        return -EINVAL;
747 65f3e339 Peter Lieven
    }
748 65f3e339 Peter Lieven
749 65f3e339 Peter Lieven
    if (!iscsilun->lbp.lbpu) {
750 65f3e339 Peter Lieven
        /* UNMAP is not supported by the target */
751 65f3e339 Peter Lieven
        return 0;
752 65f3e339 Peter Lieven
    }
753 65f3e339 Peter Lieven
754 65f3e339 Peter Lieven
    list.lba = sector_qemu2lun(sector_num, iscsilun);
755 01a6a238 Peter Lieven
    list.num = sector_qemu2lun(nb_sectors, iscsilun);
756 65f3e339 Peter Lieven
757 01a6a238 Peter Lieven
    iscsi_co_init_iscsitask(iscsilun, &iTask);
758 65f3e339 Peter Lieven
retry:
759 01a6a238 Peter Lieven
    if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1,
760 01a6a238 Peter Lieven
                     iscsi_co_generic_cb, &iTask) == NULL) {
761 92397116 Peter Lieven
        return -ENOMEM;
762 01a6a238 Peter Lieven
    }
763 65f3e339 Peter Lieven
764 01a6a238 Peter Lieven
    while (!iTask.complete) {
765 01a6a238 Peter Lieven
        iscsi_set_events(iscsilun);
766 01a6a238 Peter Lieven
        qemu_coroutine_yield();
767 01a6a238 Peter Lieven
    }
768 65f3e339 Peter Lieven
769 01a6a238 Peter Lieven
    if (iTask.task != NULL) {
770 01a6a238 Peter Lieven
        scsi_free_scsi_task(iTask.task);
771 01a6a238 Peter Lieven
        iTask.task = NULL;
772 01a6a238 Peter Lieven
    }
773 65f3e339 Peter Lieven
774 01a6a238 Peter Lieven
    if (iTask.do_retry) {
775 837c3901 Peter Lieven
        iTask.complete = 0;
776 01a6a238 Peter Lieven
        goto retry;
777 01a6a238 Peter Lieven
    }
778 65f3e339 Peter Lieven
779 01a6a238 Peter Lieven
    if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
780 01a6a238 Peter Lieven
        /* the target might fail with a check condition if it
781 01a6a238 Peter Lieven
           is not happy with the alignment of the UNMAP request
782 01a6a238 Peter Lieven
           we silently fail in this case */
783 01a6a238 Peter Lieven
        return 0;
784 01a6a238 Peter Lieven
    }
785 65f3e339 Peter Lieven
786 01a6a238 Peter Lieven
    if (iTask.status != SCSI_STATUS_GOOD) {
787 01a6a238 Peter Lieven
        return -EIO;
788 65f3e339 Peter Lieven
    }
789 65f3e339 Peter Lieven
790 65f3e339 Peter Lieven
    return 0;
791 65f3e339 Peter Lieven
}
792 65f3e339 Peter Lieven
793 d4cd9615 Peter Lieven
#if defined(SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED)
794 d4cd9615 Peter Lieven
795 d4cd9615 Peter Lieven
static int
796 d4cd9615 Peter Lieven
coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
797 d4cd9615 Peter Lieven
                                   int nb_sectors, BdrvRequestFlags flags)
798 d4cd9615 Peter Lieven
{
799 d4cd9615 Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
800 d4cd9615 Peter Lieven
    struct IscsiTask iTask;
801 d4cd9615 Peter Lieven
    uint64_t lba;
802 d4cd9615 Peter Lieven
    uint32_t nb_blocks;
803 d4cd9615 Peter Lieven
804 d4cd9615 Peter Lieven
    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
805 d4cd9615 Peter Lieven
        return -EINVAL;
806 d4cd9615 Peter Lieven
    }
807 d4cd9615 Peter Lieven
808 fa6252b0 Paolo Bonzini
    if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
809 fa6252b0 Paolo Bonzini
        /* WRITE SAME without UNMAP is not supported by the target */
810 fa6252b0 Paolo Bonzini
        return -ENOTSUP;
811 fa6252b0 Paolo Bonzini
    }
812 fa6252b0 Paolo Bonzini
813 fa6252b0 Paolo Bonzini
    if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
814 fa6252b0 Paolo Bonzini
        /* WRITE SAME with UNMAP is not supported by the target */
815 d4cd9615 Peter Lieven
        return -ENOTSUP;
816 d4cd9615 Peter Lieven
    }
817 d4cd9615 Peter Lieven
818 d4cd9615 Peter Lieven
    lba = sector_qemu2lun(sector_num, iscsilun);
819 d4cd9615 Peter Lieven
    nb_blocks = sector_qemu2lun(nb_sectors, iscsilun);
820 d4cd9615 Peter Lieven
821 d4cd9615 Peter Lieven
    if (iscsilun->zeroblock == NULL) {
822 d4cd9615 Peter Lieven
        iscsilun->zeroblock = g_malloc0(iscsilun->block_size);
823 d4cd9615 Peter Lieven
    }
824 d4cd9615 Peter Lieven
825 d4cd9615 Peter Lieven
    iscsi_co_init_iscsitask(iscsilun, &iTask);
826 d4cd9615 Peter Lieven
retry:
827 d4cd9615 Peter Lieven
    if (iscsi_writesame16_task(iscsilun->iscsi, iscsilun->lun, lba,
828 d4cd9615 Peter Lieven
                               iscsilun->zeroblock, iscsilun->block_size,
829 d4cd9615 Peter Lieven
                               nb_blocks, 0, !!(flags & BDRV_REQ_MAY_UNMAP),
830 d4cd9615 Peter Lieven
                               0, 0, iscsi_co_generic_cb, &iTask) == NULL) {
831 92397116 Peter Lieven
        return -ENOMEM;
832 d4cd9615 Peter Lieven
    }
833 d4cd9615 Peter Lieven
834 d4cd9615 Peter Lieven
    while (!iTask.complete) {
835 d4cd9615 Peter Lieven
        iscsi_set_events(iscsilun);
836 d4cd9615 Peter Lieven
        qemu_coroutine_yield();
837 d4cd9615 Peter Lieven
    }
838 d4cd9615 Peter Lieven
839 d4cd9615 Peter Lieven
    if (iTask.task != NULL) {
840 d4cd9615 Peter Lieven
        scsi_free_scsi_task(iTask.task);
841 d4cd9615 Peter Lieven
        iTask.task = NULL;
842 d4cd9615 Peter Lieven
    }
843 d4cd9615 Peter Lieven
844 d4cd9615 Peter Lieven
    if (iTask.do_retry) {
845 837c3901 Peter Lieven
        iTask.complete = 0;
846 d4cd9615 Peter Lieven
        goto retry;
847 d4cd9615 Peter Lieven
    }
848 d4cd9615 Peter Lieven
849 d4cd9615 Peter Lieven
    if (iTask.status != SCSI_STATUS_GOOD) {
850 fa6252b0 Paolo Bonzini
        if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
851 fa6252b0 Paolo Bonzini
            iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
852 fa6252b0 Paolo Bonzini
            iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
853 fa6252b0 Paolo Bonzini
            /* WRITE SAME is not supported by the target */
854 fa6252b0 Paolo Bonzini
            iscsilun->has_write_same = false;
855 fa6252b0 Paolo Bonzini
            return -ENOTSUP;
856 fa6252b0 Paolo Bonzini
        }
857 fa6252b0 Paolo Bonzini
858 d4cd9615 Peter Lieven
        return -EIO;
859 d4cd9615 Peter Lieven
    }
860 d4cd9615 Peter Lieven
861 d4cd9615 Peter Lieven
    return 0;
862 d4cd9615 Peter Lieven
}
863 d4cd9615 Peter Lieven
864 d4cd9615 Peter Lieven
#endif /* SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED */
865 d4cd9615 Peter Lieven
866 f2917853 Paolo Bonzini
static void parse_chap(struct iscsi_context *iscsi, const char *target,
867 f2917853 Paolo Bonzini
                       Error **errp)
868 f9dadc98 Ronnie Sahlberg
{
869 f9dadc98 Ronnie Sahlberg
    QemuOptsList *list;
870 f9dadc98 Ronnie Sahlberg
    QemuOpts *opts;
871 f9dadc98 Ronnie Sahlberg
    const char *user = NULL;
872 f9dadc98 Ronnie Sahlberg
    const char *password = NULL;
873 f9dadc98 Ronnie Sahlberg
874 f9dadc98 Ronnie Sahlberg
    list = qemu_find_opts("iscsi");
875 f9dadc98 Ronnie Sahlberg
    if (!list) {
876 f2917853 Paolo Bonzini
        return;
877 f9dadc98 Ronnie Sahlberg
    }
878 f9dadc98 Ronnie Sahlberg
879 f9dadc98 Ronnie Sahlberg
    opts = qemu_opts_find(list, target);
880 f9dadc98 Ronnie Sahlberg
    if (opts == NULL) {
881 f9dadc98 Ronnie Sahlberg
        opts = QTAILQ_FIRST(&list->head);
882 f9dadc98 Ronnie Sahlberg
        if (!opts) {
883 f2917853 Paolo Bonzini
            return;
884 f9dadc98 Ronnie Sahlberg
        }
885 f9dadc98 Ronnie Sahlberg
    }
886 f9dadc98 Ronnie Sahlberg
887 f9dadc98 Ronnie Sahlberg
    user = qemu_opt_get(opts, "user");
888 f9dadc98 Ronnie Sahlberg
    if (!user) {
889 f2917853 Paolo Bonzini
        return;
890 f9dadc98 Ronnie Sahlberg
    }
891 f9dadc98 Ronnie Sahlberg
892 f9dadc98 Ronnie Sahlberg
    password = qemu_opt_get(opts, "password");
893 f9dadc98 Ronnie Sahlberg
    if (!password) {
894 f2917853 Paolo Bonzini
        error_setg(errp, "CHAP username specified but no password was given");
895 f2917853 Paolo Bonzini
        return;
896 f9dadc98 Ronnie Sahlberg
    }
897 f9dadc98 Ronnie Sahlberg
898 f9dadc98 Ronnie Sahlberg
    if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
899 f2917853 Paolo Bonzini
        error_setg(errp, "Failed to set initiator username and password");
900 f9dadc98 Ronnie Sahlberg
    }
901 f9dadc98 Ronnie Sahlberg
}
902 f9dadc98 Ronnie Sahlberg
903 f2917853 Paolo Bonzini
static void parse_header_digest(struct iscsi_context *iscsi, const char *target,
904 f2917853 Paolo Bonzini
                                Error **errp)
905 f9dadc98 Ronnie Sahlberg
{
906 f9dadc98 Ronnie Sahlberg
    QemuOptsList *list;
907 f9dadc98 Ronnie Sahlberg
    QemuOpts *opts;
908 f9dadc98 Ronnie Sahlberg
    const char *digest = NULL;
909 f9dadc98 Ronnie Sahlberg
910 f9dadc98 Ronnie Sahlberg
    list = qemu_find_opts("iscsi");
911 f9dadc98 Ronnie Sahlberg
    if (!list) {
912 f9dadc98 Ronnie Sahlberg
        return;
913 f9dadc98 Ronnie Sahlberg
    }
914 f9dadc98 Ronnie Sahlberg
915 f9dadc98 Ronnie Sahlberg
    opts = qemu_opts_find(list, target);
916 f9dadc98 Ronnie Sahlberg
    if (opts == NULL) {
917 f9dadc98 Ronnie Sahlberg
        opts = QTAILQ_FIRST(&list->head);
918 f9dadc98 Ronnie Sahlberg
        if (!opts) {
919 f9dadc98 Ronnie Sahlberg
            return;
920 f9dadc98 Ronnie Sahlberg
        }
921 f9dadc98 Ronnie Sahlberg
    }
922 f9dadc98 Ronnie Sahlberg
923 f9dadc98 Ronnie Sahlberg
    digest = qemu_opt_get(opts, "header-digest");
924 f9dadc98 Ronnie Sahlberg
    if (!digest) {
925 f9dadc98 Ronnie Sahlberg
        return;
926 f9dadc98 Ronnie Sahlberg
    }
927 f9dadc98 Ronnie Sahlberg
928 f9dadc98 Ronnie Sahlberg
    if (!strcmp(digest, "CRC32C")) {
929 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
930 f9dadc98 Ronnie Sahlberg
    } else if (!strcmp(digest, "NONE")) {
931 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
932 f9dadc98 Ronnie Sahlberg
    } else if (!strcmp(digest, "CRC32C-NONE")) {
933 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
934 f9dadc98 Ronnie Sahlberg
    } else if (!strcmp(digest, "NONE-CRC32C")) {
935 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
936 f9dadc98 Ronnie Sahlberg
    } else {
937 f2917853 Paolo Bonzini
        error_setg(errp, "Invalid header-digest setting : %s", digest);
938 f9dadc98 Ronnie Sahlberg
    }
939 f9dadc98 Ronnie Sahlberg
}
940 f9dadc98 Ronnie Sahlberg
941 f9dadc98 Ronnie Sahlberg
static char *parse_initiator_name(const char *target)
942 f9dadc98 Ronnie Sahlberg
{
943 f9dadc98 Ronnie Sahlberg
    QemuOptsList *list;
944 f9dadc98 Ronnie Sahlberg
    QemuOpts *opts;
945 5accc840 Paolo Bonzini
    const char *name;
946 5accc840 Paolo Bonzini
    char *iscsi_name;
947 5accc840 Paolo Bonzini
    UuidInfo *uuid_info;
948 f9dadc98 Ronnie Sahlberg
949 f9dadc98 Ronnie Sahlberg
    list = qemu_find_opts("iscsi");
950 f2ef4a6d Paolo Bonzini
    if (list) {
951 f2ef4a6d Paolo Bonzini
        opts = qemu_opts_find(list, target);
952 f9dadc98 Ronnie Sahlberg
        if (!opts) {
953 f2ef4a6d Paolo Bonzini
            opts = QTAILQ_FIRST(&list->head);
954 f2ef4a6d Paolo Bonzini
        }
955 f2ef4a6d Paolo Bonzini
        if (opts) {
956 f2ef4a6d Paolo Bonzini
            name = qemu_opt_get(opts, "initiator-name");
957 5accc840 Paolo Bonzini
            if (name) {
958 5accc840 Paolo Bonzini
                return g_strdup(name);
959 5accc840 Paolo Bonzini
            }
960 f9dadc98 Ronnie Sahlberg
        }
961 f9dadc98 Ronnie Sahlberg
    }
962 f9dadc98 Ronnie Sahlberg
963 5accc840 Paolo Bonzini
    uuid_info = qmp_query_uuid(NULL);
964 5accc840 Paolo Bonzini
    if (strcmp(uuid_info->UUID, UUID_NONE) == 0) {
965 5accc840 Paolo Bonzini
        name = qemu_get_vm_name();
966 f2ef4a6d Paolo Bonzini
    } else {
967 5accc840 Paolo Bonzini
        name = uuid_info->UUID;
968 f9dadc98 Ronnie Sahlberg
    }
969 5accc840 Paolo Bonzini
    iscsi_name = g_strdup_printf("iqn.2008-11.org.linux-kvm%s%s",
970 5accc840 Paolo Bonzini
                                 name ? ":" : "", name ? name : "");
971 5accc840 Paolo Bonzini
    qapi_free_UuidInfo(uuid_info);
972 5accc840 Paolo Bonzini
    return iscsi_name;
973 f9dadc98 Ronnie Sahlberg
}
974 f9dadc98 Ronnie Sahlberg
975 5b5d34ec Peter Lieven
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
976 5b5d34ec Peter Lieven
static void iscsi_nop_timed_event(void *opaque)
977 5b5d34ec Peter Lieven
{
978 5b5d34ec Peter Lieven
    IscsiLun *iscsilun = opaque;
979 5b5d34ec Peter Lieven
980 5b5d34ec Peter Lieven
    if (iscsi_get_nops_in_flight(iscsilun->iscsi) > MAX_NOP_FAILURES) {
981 5b5d34ec Peter Lieven
        error_report("iSCSI: NOP timeout. Reconnecting...");
982 5b5d34ec Peter Lieven
        iscsi_reconnect(iscsilun->iscsi);
983 5b5d34ec Peter Lieven
    }
984 5b5d34ec Peter Lieven
985 5b5d34ec Peter Lieven
    if (iscsi_nop_out_async(iscsilun->iscsi, NULL, NULL, 0, NULL) != 0) {
986 5b5d34ec Peter Lieven
        error_report("iSCSI: failed to sent NOP-Out. Disabling NOP messages.");
987 5b5d34ec Peter Lieven
        return;
988 5b5d34ec Peter Lieven
    }
989 5b5d34ec Peter Lieven
990 bc72ad67 Alex Bligh
    timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
991 5b5d34ec Peter Lieven
    iscsi_set_events(iscsilun);
992 5b5d34ec Peter Lieven
}
993 5b5d34ec Peter Lieven
#endif
994 5b5d34ec Peter Lieven
995 f2917853 Paolo Bonzini
static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
996 cb1b83e7 Peter Lieven
{
997 cb1b83e7 Peter Lieven
    struct scsi_task *task = NULL;
998 cb1b83e7 Peter Lieven
    struct scsi_readcapacity10 *rc10 = NULL;
999 cb1b83e7 Peter Lieven
    struct scsi_readcapacity16 *rc16 = NULL;
1000 cb1b83e7 Peter Lieven
    int retries = ISCSI_CMD_RETRIES; 
1001 cb1b83e7 Peter Lieven
1002 1288844e Paolo Bonzini
    do {
1003 1288844e Paolo Bonzini
        if (task != NULL) {
1004 1288844e Paolo Bonzini
            scsi_free_scsi_task(task);
1005 1288844e Paolo Bonzini
            task = NULL;
1006 cb1b83e7 Peter Lieven
        }
1007 1288844e Paolo Bonzini
1008 1288844e Paolo Bonzini
        switch (iscsilun->type) {
1009 1288844e Paolo Bonzini
        case TYPE_DISK:
1010 1288844e Paolo Bonzini
            task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
1011 1288844e Paolo Bonzini
            if (task != NULL && task->status == SCSI_STATUS_GOOD) {
1012 1288844e Paolo Bonzini
                rc16 = scsi_datain_unmarshall(task);
1013 1288844e Paolo Bonzini
                if (rc16 == NULL) {
1014 f2917853 Paolo Bonzini
                    error_setg(errp, "iSCSI: Failed to unmarshall readcapacity16 data.");
1015 1288844e Paolo Bonzini
                } else {
1016 1288844e Paolo Bonzini
                    iscsilun->block_size = rc16->block_length;
1017 1288844e Paolo Bonzini
                    iscsilun->num_blocks = rc16->returned_lba + 1;
1018 f18a7cbb Peter Lieven
                    iscsilun->lbpme = rc16->lbpme;
1019 f18a7cbb Peter Lieven
                    iscsilun->lbprz = rc16->lbprz;
1020 1288844e Paolo Bonzini
                }
1021 1288844e Paolo Bonzini
            }
1022 1288844e Paolo Bonzini
            break;
1023 1288844e Paolo Bonzini
        case TYPE_ROM:
1024 1288844e Paolo Bonzini
            task = iscsi_readcapacity10_sync(iscsilun->iscsi, iscsilun->lun, 0, 0);
1025 1288844e Paolo Bonzini
            if (task != NULL && task->status == SCSI_STATUS_GOOD) {
1026 1288844e Paolo Bonzini
                rc10 = scsi_datain_unmarshall(task);
1027 1288844e Paolo Bonzini
                if (rc10 == NULL) {
1028 f2917853 Paolo Bonzini
                    error_setg(errp, "iSCSI: Failed to unmarshall readcapacity10 data.");
1029 1288844e Paolo Bonzini
                } else {
1030 1288844e Paolo Bonzini
                    iscsilun->block_size = rc10->block_size;
1031 1288844e Paolo Bonzini
                    if (rc10->lba == 0) {
1032 1288844e Paolo Bonzini
                        /* blank disk loaded */
1033 1288844e Paolo Bonzini
                        iscsilun->num_blocks = 0;
1034 1288844e Paolo Bonzini
                    } else {
1035 1288844e Paolo Bonzini
                        iscsilun->num_blocks = rc10->lba + 1;
1036 1288844e Paolo Bonzini
                    }
1037 1288844e Paolo Bonzini
                }
1038 1288844e Paolo Bonzini
            }
1039 1288844e Paolo Bonzini
            break;
1040 1288844e Paolo Bonzini
        default:
1041 f2917853 Paolo Bonzini
            return;
1042 cb1b83e7 Peter Lieven
        }
1043 1288844e Paolo Bonzini
    } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
1044 1288844e Paolo Bonzini
             && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
1045 1288844e Paolo Bonzini
             && retries-- > 0);
1046 cb1b83e7 Peter Lieven
1047 1288844e Paolo Bonzini
    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
1048 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
1049 1288844e Paolo Bonzini
    }
1050 cb1b83e7 Peter Lieven
    if (task) {
1051 cb1b83e7 Peter Lieven
        scsi_free_scsi_task(task);
1052 cb1b83e7 Peter Lieven
    }
1053 cb1b83e7 Peter Lieven
}
1054 cb1b83e7 Peter Lieven
1055 60beb341 Kevin Wolf
/* TODO Convert to fine grained options */
1056 60beb341 Kevin Wolf
static QemuOptsList runtime_opts = {
1057 60beb341 Kevin Wolf
    .name = "iscsi",
1058 60beb341 Kevin Wolf
    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
1059 60beb341 Kevin Wolf
    .desc = {
1060 60beb341 Kevin Wolf
        {
1061 60beb341 Kevin Wolf
            .name = "filename",
1062 60beb341 Kevin Wolf
            .type = QEMU_OPT_STRING,
1063 60beb341 Kevin Wolf
            .help = "URL to the iscsi image",
1064 60beb341 Kevin Wolf
        },
1065 60beb341 Kevin Wolf
        { /* end of list */ }
1066 60beb341 Kevin Wolf
    },
1067 60beb341 Kevin Wolf
};
1068 60beb341 Kevin Wolf
1069 35cb1748 Paolo Bonzini
static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
1070 f2917853 Paolo Bonzini
                                          int evpd, int pc, Error **errp)
1071 35cb1748 Paolo Bonzini
{
1072 35cb1748 Paolo Bonzini
    int full_size;
1073 35cb1748 Paolo Bonzini
    struct scsi_task *task = NULL;
1074 35cb1748 Paolo Bonzini
    task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, 64);
1075 35cb1748 Paolo Bonzini
    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
1076 35cb1748 Paolo Bonzini
        goto fail;
1077 35cb1748 Paolo Bonzini
    }
1078 35cb1748 Paolo Bonzini
    full_size = scsi_datain_getfullsize(task);
1079 35cb1748 Paolo Bonzini
    if (full_size > task->datain.size) {
1080 35cb1748 Paolo Bonzini
        scsi_free_scsi_task(task);
1081 35cb1748 Paolo Bonzini
1082 35cb1748 Paolo Bonzini
        /* we need more data for the full list */
1083 35cb1748 Paolo Bonzini
        task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, full_size);
1084 f18a7cbb Peter Lieven
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
1085 f18a7cbb Peter Lieven
            goto fail;
1086 f18a7cbb Peter Lieven
        }
1087 35cb1748 Paolo Bonzini
    }
1088 f18a7cbb Peter Lieven
1089 35cb1748 Paolo Bonzini
    return task;
1090 f18a7cbb Peter Lieven
1091 f18a7cbb Peter Lieven
fail:
1092 f2917853 Paolo Bonzini
    error_setg(errp, "iSCSI: Inquiry command failed : %s",
1093 f2917853 Paolo Bonzini
               iscsi_get_error(iscsi));
1094 35cb1748 Paolo Bonzini
    if (task) {
1095 35cb1748 Paolo Bonzini
        scsi_free_scsi_task(task);
1096 f18a7cbb Peter Lieven
        return NULL;
1097 35cb1748 Paolo Bonzini
    }
1098 35cb1748 Paolo Bonzini
    return NULL;
1099 f18a7cbb Peter Lieven
}
1100 f18a7cbb Peter Lieven
1101 c589b249 Ronnie Sahlberg
/*
1102 c589b249 Ronnie Sahlberg
 * We support iscsi url's on the form
1103 c589b249 Ronnie Sahlberg
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
1104 28f106af Jeff Cody
 *
1105 28f106af Jeff Cody
 * Note: flags are currently not used by iscsi_open.  If this function
1106 28f106af Jeff Cody
 * is changed such that flags are used, please examine iscsi_reopen_prepare()
1107 28f106af Jeff Cody
 * to see if needs to be changed as well.
1108 c589b249 Ronnie Sahlberg
 */
1109 015a1036 Max Reitz
static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
1110 015a1036 Max Reitz
                      Error **errp)
1111 c589b249 Ronnie Sahlberg
{
1112 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
1113 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = NULL;
1114 c589b249 Ronnie Sahlberg
    struct iscsi_url *iscsi_url = NULL;
1115 e829b0bb Peter Lieven
    struct scsi_task *task = NULL;
1116 e829b0bb Peter Lieven
    struct scsi_inquiry_standard *inq = NULL;
1117 f9dadc98 Ronnie Sahlberg
    char *initiator_name = NULL;
1118 60beb341 Kevin Wolf
    QemuOpts *opts;
1119 60beb341 Kevin Wolf
    Error *local_err = NULL;
1120 60beb341 Kevin Wolf
    const char *filename;
1121 c589b249 Ronnie Sahlberg
    int ret;
1122 c589b249 Ronnie Sahlberg
1123 c589b249 Ronnie Sahlberg
    if ((BDRV_SECTOR_SIZE % 512) != 0) {
1124 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
1125 f2917853 Paolo Bonzini
                   "BDRV_SECTOR_SIZE(%lld) is not a multiple "
1126 f2917853 Paolo Bonzini
                   "of 512", BDRV_SECTOR_SIZE);
1127 c589b249 Ronnie Sahlberg
        return -EINVAL;
1128 c589b249 Ronnie Sahlberg
    }
1129 c589b249 Ronnie Sahlberg
1130 87ea75d5 Peter Crosthwaite
    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
1131 60beb341 Kevin Wolf
    qemu_opts_absorb_qdict(opts, options, &local_err);
1132 84d18f06 Markus Armbruster
    if (local_err) {
1133 f2917853 Paolo Bonzini
        error_propagate(errp, local_err);
1134 60beb341 Kevin Wolf
        ret = -EINVAL;
1135 60beb341 Kevin Wolf
        goto out;
1136 60beb341 Kevin Wolf
    }
1137 60beb341 Kevin Wolf
1138 60beb341 Kevin Wolf
    filename = qemu_opt_get(opts, "filename");
1139 60beb341 Kevin Wolf
1140 c589b249 Ronnie Sahlberg
    iscsi_url = iscsi_parse_full_url(iscsi, filename);
1141 c589b249 Ronnie Sahlberg
    if (iscsi_url == NULL) {
1142 f2917853 Paolo Bonzini
        error_setg(errp, "Failed to parse URL : %s", filename);
1143 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
1144 b93c94f7 Paolo Bonzini
        goto out;
1145 c589b249 Ronnie Sahlberg
    }
1146 c589b249 Ronnie Sahlberg
1147 f9dadc98 Ronnie Sahlberg
    memset(iscsilun, 0, sizeof(IscsiLun));
1148 f9dadc98 Ronnie Sahlberg
1149 f9dadc98 Ronnie Sahlberg
    initiator_name = parse_initiator_name(iscsi_url->target);
1150 f9dadc98 Ronnie Sahlberg
1151 f9dadc98 Ronnie Sahlberg
    iscsi = iscsi_create_context(initiator_name);
1152 f9dadc98 Ronnie Sahlberg
    if (iscsi == NULL) {
1153 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: Failed to create iSCSI context.");
1154 f9dadc98 Ronnie Sahlberg
        ret = -ENOMEM;
1155 b93c94f7 Paolo Bonzini
        goto out;
1156 f9dadc98 Ronnie Sahlberg
    }
1157 f9dadc98 Ronnie Sahlberg
1158 c589b249 Ronnie Sahlberg
    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
1159 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: Failed to set target name.");
1160 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
1161 b93c94f7 Paolo Bonzini
        goto out;
1162 c589b249 Ronnie Sahlberg
    }
1163 c589b249 Ronnie Sahlberg
1164 c589b249 Ronnie Sahlberg
    if (iscsi_url->user != NULL) {
1165 c589b249 Ronnie Sahlberg
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
1166 c589b249 Ronnie Sahlberg
                                              iscsi_url->passwd);
1167 c589b249 Ronnie Sahlberg
        if (ret != 0) {
1168 f2917853 Paolo Bonzini
            error_setg(errp, "Failed to set initiator username and password");
1169 c589b249 Ronnie Sahlberg
            ret = -EINVAL;
1170 b93c94f7 Paolo Bonzini
            goto out;
1171 c589b249 Ronnie Sahlberg
        }
1172 c589b249 Ronnie Sahlberg
    }
1173 f9dadc98 Ronnie Sahlberg
1174 f9dadc98 Ronnie Sahlberg
    /* check if we got CHAP username/password via the options */
1175 f2917853 Paolo Bonzini
    parse_chap(iscsi, iscsi_url->target, &local_err);
1176 f2917853 Paolo Bonzini
    if (local_err != NULL) {
1177 f2917853 Paolo Bonzini
        error_propagate(errp, local_err);
1178 f9dadc98 Ronnie Sahlberg
        ret = -EINVAL;
1179 b93c94f7 Paolo Bonzini
        goto out;
1180 f9dadc98 Ronnie Sahlberg
    }
1181 f9dadc98 Ronnie Sahlberg
1182 c589b249 Ronnie Sahlberg
    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
1183 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: Failed to set session type to normal.");
1184 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
1185 b93c94f7 Paolo Bonzini
        goto out;
1186 c589b249 Ronnie Sahlberg
    }
1187 c589b249 Ronnie Sahlberg
1188 c589b249 Ronnie Sahlberg
    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
1189 c589b249 Ronnie Sahlberg
1190 f9dadc98 Ronnie Sahlberg
    /* check if we got HEADER_DIGEST via the options */
1191 f2917853 Paolo Bonzini
    parse_header_digest(iscsi, iscsi_url->target, &local_err);
1192 f2917853 Paolo Bonzini
    if (local_err != NULL) {
1193 f2917853 Paolo Bonzini
        error_propagate(errp, local_err);
1194 f2917853 Paolo Bonzini
        ret = -EINVAL;
1195 f2917853 Paolo Bonzini
        goto out;
1196 f2917853 Paolo Bonzini
    }
1197 f9dadc98 Ronnie Sahlberg
1198 e829b0bb Peter Lieven
    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
1199 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: Failed to connect to LUN : %s",
1200 e829b0bb Peter Lieven
            iscsi_get_error(iscsi));
1201 e829b0bb Peter Lieven
        ret = -EINVAL;
1202 e829b0bb Peter Lieven
        goto out;
1203 e829b0bb Peter Lieven
    }
1204 c589b249 Ronnie Sahlberg
1205 c589b249 Ronnie Sahlberg
    iscsilun->iscsi = iscsi;
1206 c589b249 Ronnie Sahlberg
    iscsilun->lun   = iscsi_url->lun;
1207 c589b249 Ronnie Sahlberg
1208 e829b0bb Peter Lieven
    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
1209 e829b0bb Peter Lieven
1210 e829b0bb Peter Lieven
    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
1211 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: failed to send inquiry command.");
1212 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
1213 b93c94f7 Paolo Bonzini
        goto out;
1214 c589b249 Ronnie Sahlberg
    }
1215 c589b249 Ronnie Sahlberg
1216 e829b0bb Peter Lieven
    inq = scsi_datain_unmarshall(task);
1217 e829b0bb Peter Lieven
    if (inq == NULL) {
1218 f2917853 Paolo Bonzini
        error_setg(errp, "iSCSI: Failed to unmarshall inquiry data.");
1219 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
1220 b93c94f7 Paolo Bonzini
        goto out;
1221 c589b249 Ronnie Sahlberg
    }
1222 622695a4 Ronnie Sahlberg
1223 e829b0bb Peter Lieven
    iscsilun->type = inq->periperal_device_type;
1224 fa6252b0 Paolo Bonzini
    iscsilun->has_write_same = true;
1225 e829b0bb Peter Lieven
1226 f2917853 Paolo Bonzini
    iscsi_readcapacity_sync(iscsilun, &local_err);
1227 f2917853 Paolo Bonzini
    if (local_err != NULL) {
1228 f2917853 Paolo Bonzini
        error_propagate(errp, local_err);
1229 cb1b83e7 Peter Lieven
        goto out;
1230 e829b0bb Peter Lieven
    }
1231 0777b5dd Peter Lieven
    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
1232 2c9880c4 Paolo Bonzini
    bs->request_alignment = iscsilun->block_size;
1233 e829b0bb Peter Lieven
1234 622695a4 Ronnie Sahlberg
    /* Medium changer or tape. We dont have any emulation for this so this must
1235 622695a4 Ronnie Sahlberg
     * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
1236 622695a4 Ronnie Sahlberg
     * to read from the device to guess the image format.
1237 622695a4 Ronnie Sahlberg
     */
1238 622695a4 Ronnie Sahlberg
    if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
1239 622695a4 Ronnie Sahlberg
        iscsilun->type == TYPE_TAPE) {
1240 622695a4 Ronnie Sahlberg
        bs->sg = 1;
1241 622695a4 Ronnie Sahlberg
    }
1242 622695a4 Ronnie Sahlberg
1243 f18a7cbb Peter Lieven
    if (iscsilun->lbpme) {
1244 f18a7cbb Peter Lieven
        struct scsi_inquiry_logical_block_provisioning *inq_lbp;
1245 f18a7cbb Peter Lieven
        task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
1246 f2917853 Paolo Bonzini
                                SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
1247 f2917853 Paolo Bonzini
                                errp);
1248 f18a7cbb Peter Lieven
        if (task == NULL) {
1249 f18a7cbb Peter Lieven
            ret = -EINVAL;
1250 f18a7cbb Peter Lieven
            goto out;
1251 f18a7cbb Peter Lieven
        }
1252 f18a7cbb Peter Lieven
        inq_lbp = scsi_datain_unmarshall(task);
1253 f18a7cbb Peter Lieven
        if (inq_lbp == NULL) {
1254 f2917853 Paolo Bonzini
            error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
1255 f18a7cbb Peter Lieven
            ret = -EINVAL;
1256 f18a7cbb Peter Lieven
            goto out;
1257 f18a7cbb Peter Lieven
        }
1258 f18a7cbb Peter Lieven
        memcpy(&iscsilun->lbp, inq_lbp,
1259 f18a7cbb Peter Lieven
               sizeof(struct scsi_inquiry_logical_block_provisioning));
1260 f18a7cbb Peter Lieven
        scsi_free_scsi_task(task);
1261 f18a7cbb Peter Lieven
        task = NULL;
1262 f18a7cbb Peter Lieven
    }
1263 f18a7cbb Peter Lieven
1264 f18a7cbb Peter Lieven
    if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
1265 f18a7cbb Peter Lieven
        struct scsi_inquiry_block_limits *inq_bl;
1266 f18a7cbb Peter Lieven
        task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
1267 f2917853 Paolo Bonzini
                                SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, errp);
1268 f18a7cbb Peter Lieven
        if (task == NULL) {
1269 f18a7cbb Peter Lieven
            ret = -EINVAL;
1270 f18a7cbb Peter Lieven
            goto out;
1271 f18a7cbb Peter Lieven
        }
1272 f18a7cbb Peter Lieven
        inq_bl = scsi_datain_unmarshall(task);
1273 f18a7cbb Peter Lieven
        if (inq_bl == NULL) {
1274 f2917853 Paolo Bonzini
            error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
1275 f18a7cbb Peter Lieven
            ret = -EINVAL;
1276 f18a7cbb Peter Lieven
            goto out;
1277 f18a7cbb Peter Lieven
        }
1278 f18a7cbb Peter Lieven
        memcpy(&iscsilun->bl, inq_bl,
1279 f18a7cbb Peter Lieven
               sizeof(struct scsi_inquiry_block_limits));
1280 f18a7cbb Peter Lieven
        scsi_free_scsi_task(task);
1281 f18a7cbb Peter Lieven
        task = NULL;
1282 f18a7cbb Peter Lieven
    }
1283 f18a7cbb Peter Lieven
1284 5b5d34ec Peter Lieven
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
1285 5b5d34ec Peter Lieven
    /* Set up a timer for sending out iSCSI NOPs */
1286 bc72ad67 Alex Bligh
    iscsilun->nop_timer = timer_new_ms(QEMU_CLOCK_REALTIME, iscsi_nop_timed_event, iscsilun);
1287 bc72ad67 Alex Bligh
    timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
1288 5b5d34ec Peter Lieven
#endif
1289 5b5d34ec Peter Lieven
1290 b93c94f7 Paolo Bonzini
out:
1291 60beb341 Kevin Wolf
    qemu_opts_del(opts);
1292 f9dadc98 Ronnie Sahlberg
    if (initiator_name != NULL) {
1293 f9dadc98 Ronnie Sahlberg
        g_free(initiator_name);
1294 f9dadc98 Ronnie Sahlberg
    }
1295 c589b249 Ronnie Sahlberg
    if (iscsi_url != NULL) {
1296 c589b249 Ronnie Sahlberg
        iscsi_destroy_url(iscsi_url);
1297 c589b249 Ronnie Sahlberg
    }
1298 e829b0bb Peter Lieven
    if (task != NULL) {
1299 e829b0bb Peter Lieven
        scsi_free_scsi_task(task);
1300 e829b0bb Peter Lieven
    }
1301 b93c94f7 Paolo Bonzini
1302 b93c94f7 Paolo Bonzini
    if (ret) {
1303 b93c94f7 Paolo Bonzini
        if (iscsi != NULL) {
1304 b93c94f7 Paolo Bonzini
            iscsi_destroy_context(iscsi);
1305 b93c94f7 Paolo Bonzini
        }
1306 b93c94f7 Paolo Bonzini
        memset(iscsilun, 0, sizeof(IscsiLun));
1307 c589b249 Ronnie Sahlberg
    }
1308 c589b249 Ronnie Sahlberg
    return ret;
1309 c589b249 Ronnie Sahlberg
}
1310 c589b249 Ronnie Sahlberg
1311 c589b249 Ronnie Sahlberg
static void iscsi_close(BlockDriverState *bs)
1312 c589b249 Ronnie Sahlberg
{
1313 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
1314 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
1315 c589b249 Ronnie Sahlberg
1316 5b5d34ec Peter Lieven
    if (iscsilun->nop_timer) {
1317 bc72ad67 Alex Bligh
        timer_del(iscsilun->nop_timer);
1318 bc72ad67 Alex Bligh
        timer_free(iscsilun->nop_timer);
1319 5b5d34ec Peter Lieven
    }
1320 f2e5dca4 Stefan Hajnoczi
    qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
1321 c589b249 Ronnie Sahlberg
    iscsi_destroy_context(iscsi);
1322 d4cd9615 Peter Lieven
    g_free(iscsilun->zeroblock);
1323 c589b249 Ronnie Sahlberg
    memset(iscsilun, 0, sizeof(IscsiLun));
1324 c589b249 Ronnie Sahlberg
}
1325 c589b249 Ronnie Sahlberg
1326 d34682cd Kevin Wolf
static int iscsi_refresh_limits(BlockDriverState *bs)
1327 d34682cd Kevin Wolf
{
1328 d34682cd Kevin Wolf
    IscsiLun *iscsilun = bs->opaque;
1329 d34682cd Kevin Wolf
1330 d34682cd Kevin Wolf
    /* We don't actually refresh here, but just return data queried in
1331 d34682cd Kevin Wolf
     * iscsi_open(): iscsi targets don't change their limits. */
1332 d34682cd Kevin Wolf
    if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
1333 d34682cd Kevin Wolf
        if (iscsilun->bl.max_unmap < 0xffffffff) {
1334 d34682cd Kevin Wolf
            bs->bl.max_discard = sector_lun2qemu(iscsilun->bl.max_unmap,
1335 d34682cd Kevin Wolf
                                                 iscsilun);
1336 d34682cd Kevin Wolf
        }
1337 d34682cd Kevin Wolf
        bs->bl.discard_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
1338 d34682cd Kevin Wolf
                                                   iscsilun);
1339 d34682cd Kevin Wolf
1340 d34682cd Kevin Wolf
        if (iscsilun->bl.max_ws_len < 0xffffffff) {
1341 d34682cd Kevin Wolf
            bs->bl.max_write_zeroes = sector_lun2qemu(iscsilun->bl.max_ws_len,
1342 d34682cd Kevin Wolf
                                                      iscsilun);
1343 d34682cd Kevin Wolf
        }
1344 d34682cd Kevin Wolf
        bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
1345 d34682cd Kevin Wolf
                                                        iscsilun);
1346 d34682cd Kevin Wolf
    }
1347 5d259fc7 Peter Lieven
    bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
1348 5d259fc7 Peter Lieven
                                                 iscsilun);
1349 e9f526ab Anthony Liguori
    return 0;
1350 e9f526ab Anthony Liguori
}
1351 d34682cd Kevin Wolf
1352 28f106af Jeff Cody
/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
1353 28f106af Jeff Cody
 * prepare.  Note that this will not re-establish a connection with an iSCSI
1354 28f106af Jeff Cody
 * target - it is effectively a NOP.  */
1355 dc6afb99 Jeff Cody
static int iscsi_reopen_prepare(BDRVReopenState *state,
1356 dc6afb99 Jeff Cody
                                BlockReopenQueue *queue, Error **errp)
1357 dc6afb99 Jeff Cody
{
1358 28f106af Jeff Cody
    /* NOP */
1359 d34682cd Kevin Wolf
    return 0;
1360 d34682cd Kevin Wolf
}
1361 d34682cd Kevin Wolf
1362 cb1b83e7 Peter Lieven
static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
1363 cb1b83e7 Peter Lieven
{
1364 cb1b83e7 Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
1365 f2917853 Paolo Bonzini
    Error *local_err = NULL;
1366 cb1b83e7 Peter Lieven
1367 cb1b83e7 Peter Lieven
    if (iscsilun->type != TYPE_DISK) {
1368 cb1b83e7 Peter Lieven
        return -ENOTSUP;
1369 cb1b83e7 Peter Lieven
    }
1370 cb1b83e7 Peter Lieven
1371 f2917853 Paolo Bonzini
    iscsi_readcapacity_sync(iscsilun, &local_err);
1372 f2917853 Paolo Bonzini
    if (local_err != NULL) {
1373 f2917853 Paolo Bonzini
        error_free(local_err);
1374 f2917853 Paolo Bonzini
        return -EIO;
1375 cb1b83e7 Peter Lieven
    }
1376 cb1b83e7 Peter Lieven
1377 cb1b83e7 Peter Lieven
    if (offset > iscsi_getlength(bs)) {
1378 cb1b83e7 Peter Lieven
        return -EINVAL;
1379 cb1b83e7 Peter Lieven
    }
1380 cb1b83e7 Peter Lieven
1381 cb1b83e7 Peter Lieven
    return 0;
1382 cb1b83e7 Peter Lieven
}
1383 cb1b83e7 Peter Lieven
1384 d5124c00 Max Reitz
static int iscsi_create(const char *filename, QEMUOptionParameter *options,
1385 d5124c00 Max Reitz
                        Error **errp)
1386 de8864e5 Peter Lieven
{
1387 de8864e5 Peter Lieven
    int ret = 0;
1388 de8864e5 Peter Lieven
    int64_t total_size = 0;
1389 13c91cb7 Fam Zheng
    BlockDriverState *bs;
1390 de8864e5 Peter Lieven
    IscsiLun *iscsilun = NULL;
1391 60beb341 Kevin Wolf
    QDict *bs_options;
1392 de8864e5 Peter Lieven
1393 13c91cb7 Fam Zheng
    bs = bdrv_new("");
1394 de8864e5 Peter Lieven
1395 de8864e5 Peter Lieven
    /* Read out options */
1396 de8864e5 Peter Lieven
    while (options && options->name) {
1397 de8864e5 Peter Lieven
        if (!strcmp(options->name, "size")) {
1398 de8864e5 Peter Lieven
            total_size = options->value.n / BDRV_SECTOR_SIZE;
1399 de8864e5 Peter Lieven
        }
1400 de8864e5 Peter Lieven
        options++;
1401 de8864e5 Peter Lieven
    }
1402 de8864e5 Peter Lieven
1403 13c91cb7 Fam Zheng
    bs->opaque = g_malloc0(sizeof(struct IscsiLun));
1404 13c91cb7 Fam Zheng
    iscsilun = bs->opaque;
1405 de8864e5 Peter Lieven
1406 60beb341 Kevin Wolf
    bs_options = qdict_new();
1407 60beb341 Kevin Wolf
    qdict_put(bs_options, "filename", qstring_from_str(filename));
1408 015a1036 Max Reitz
    ret = iscsi_open(bs, bs_options, 0, NULL);
1409 60beb341 Kevin Wolf
    QDECREF(bs_options);
1410 60beb341 Kevin Wolf
1411 de8864e5 Peter Lieven
    if (ret != 0) {
1412 de8864e5 Peter Lieven
        goto out;
1413 de8864e5 Peter Lieven
    }
1414 5b5d34ec Peter Lieven
    if (iscsilun->nop_timer) {
1415 bc72ad67 Alex Bligh
        timer_del(iscsilun->nop_timer);
1416 bc72ad67 Alex Bligh
        timer_free(iscsilun->nop_timer);
1417 5b5d34ec Peter Lieven
    }
1418 de8864e5 Peter Lieven
    if (iscsilun->type != TYPE_DISK) {
1419 de8864e5 Peter Lieven
        ret = -ENODEV;
1420 de8864e5 Peter Lieven
        goto out;
1421 de8864e5 Peter Lieven
    }
1422 13c91cb7 Fam Zheng
    if (bs->total_sectors < total_size) {
1423 de8864e5 Peter Lieven
        ret = -ENOSPC;
1424 d3bda7bc Peter Lieven
        goto out;
1425 de8864e5 Peter Lieven
    }
1426 de8864e5 Peter Lieven
1427 de8864e5 Peter Lieven
    ret = 0;
1428 de8864e5 Peter Lieven
out:
1429 de8864e5 Peter Lieven
    if (iscsilun->iscsi != NULL) {
1430 de8864e5 Peter Lieven
        iscsi_destroy_context(iscsilun->iscsi);
1431 de8864e5 Peter Lieven
    }
1432 13c91cb7 Fam Zheng
    g_free(bs->opaque);
1433 13c91cb7 Fam Zheng
    bs->opaque = NULL;
1434 4f6fd349 Fam Zheng
    bdrv_unref(bs);
1435 de8864e5 Peter Lieven
    return ret;
1436 de8864e5 Peter Lieven
}
1437 de8864e5 Peter Lieven
1438 186d4f2b Peter Lieven
static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
1439 186d4f2b Peter Lieven
{
1440 186d4f2b Peter Lieven
    IscsiLun *iscsilun = bs->opaque;
1441 186d4f2b Peter Lieven
    bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
1442 186d4f2b Peter Lieven
    bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
1443 1c0704a5 Peter Lieven
    /* Guess the internal cluster (page) size of the iscsi target by the means
1444 1c0704a5 Peter Lieven
     * of opt_unmap_gran. Transfer the unmap granularity only if it has a
1445 1c0704a5 Peter Lieven
     * reasonable size for bdi->cluster_size */
1446 1c0704a5 Peter Lieven
    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 64 * 1024 &&
1447 1c0704a5 Peter Lieven
        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
1448 1c0704a5 Peter Lieven
        bdi->cluster_size = iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
1449 1c0704a5 Peter Lieven
    }
1450 186d4f2b Peter Lieven
    return 0;
1451 186d4f2b Peter Lieven
}
1452 186d4f2b Peter Lieven
1453 de8864e5 Peter Lieven
static QEMUOptionParameter iscsi_create_options[] = {
1454 de8864e5 Peter Lieven
    {
1455 de8864e5 Peter Lieven
        .name = BLOCK_OPT_SIZE,
1456 de8864e5 Peter Lieven
        .type = OPT_SIZE,
1457 de8864e5 Peter Lieven
        .help = "Virtual disk size"
1458 de8864e5 Peter Lieven
    },
1459 de8864e5 Peter Lieven
    { NULL }
1460 de8864e5 Peter Lieven
};
1461 de8864e5 Peter Lieven
1462 c589b249 Ronnie Sahlberg
static BlockDriver bdrv_iscsi = {
1463 c589b249 Ronnie Sahlberg
    .format_name     = "iscsi",
1464 c589b249 Ronnie Sahlberg
    .protocol_name   = "iscsi",
1465 c589b249 Ronnie Sahlberg
1466 c589b249 Ronnie Sahlberg
    .instance_size   = sizeof(IscsiLun),
1467 030be321 Benoît Canet
    .bdrv_needs_filename = true,
1468 c589b249 Ronnie Sahlberg
    .bdrv_file_open  = iscsi_open,
1469 c589b249 Ronnie Sahlberg
    .bdrv_close      = iscsi_close,
1470 de8864e5 Peter Lieven
    .bdrv_create     = iscsi_create,
1471 de8864e5 Peter Lieven
    .create_options  = iscsi_create_options,
1472 dc6afb99 Jeff Cody
    .bdrv_reopen_prepare  = iscsi_reopen_prepare,
1473 c589b249 Ronnie Sahlberg
1474 c589b249 Ronnie Sahlberg
    .bdrv_getlength  = iscsi_getlength,
1475 186d4f2b Peter Lieven
    .bdrv_get_info   = iscsi_get_info,
1476 cb1b83e7 Peter Lieven
    .bdrv_truncate   = iscsi_truncate,
1477 d34682cd Kevin Wolf
    .bdrv_refresh_limits = iscsi_refresh_limits,
1478 c589b249 Ronnie Sahlberg
1479 24c7608a Peter Lieven
#if defined(LIBISCSI_FEATURE_IOVECTOR)
1480 54a5c1d5 Peter Lieven
    .bdrv_co_get_block_status = iscsi_co_get_block_status,
1481 f35c934a Stefan Weil
#endif
1482 65f3e339 Peter Lieven
    .bdrv_co_discard      = iscsi_co_discard,
1483 d4cd9615 Peter Lieven
#if defined(SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED)
1484 d4cd9615 Peter Lieven
    .bdrv_co_write_zeroes = iscsi_co_write_zeroes,
1485 d4cd9615 Peter Lieven
#endif
1486 063c3378 Peter Lieven
    .bdrv_co_readv         = iscsi_co_readv,
1487 063c3378 Peter Lieven
    .bdrv_co_writev        = iscsi_co_writev,
1488 063c3378 Peter Lieven
    .bdrv_co_flush_to_disk = iscsi_co_flush,
1489 fa6acb0c Ronnie Sahlberg
1490 98392453 Ronnie Sahlberg
#ifdef __linux__
1491 98392453 Ronnie Sahlberg
    .bdrv_ioctl       = iscsi_ioctl,
1492 98392453 Ronnie Sahlberg
    .bdrv_aio_ioctl   = iscsi_aio_ioctl,
1493 98392453 Ronnie Sahlberg
#endif
1494 c589b249 Ronnie Sahlberg
};
1495 c589b249 Ronnie Sahlberg
1496 4d454574 Paolo Bonzini
static QemuOptsList qemu_iscsi_opts = {
1497 4d454574 Paolo Bonzini
    .name = "iscsi",
1498 4d454574 Paolo Bonzini
    .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
1499 4d454574 Paolo Bonzini
    .desc = {
1500 4d454574 Paolo Bonzini
        {
1501 4d454574 Paolo Bonzini
            .name = "user",
1502 4d454574 Paolo Bonzini
            .type = QEMU_OPT_STRING,
1503 4d454574 Paolo Bonzini
            .help = "username for CHAP authentication to target",
1504 4d454574 Paolo Bonzini
        },{
1505 4d454574 Paolo Bonzini
            .name = "password",
1506 4d454574 Paolo Bonzini
            .type = QEMU_OPT_STRING,
1507 4d454574 Paolo Bonzini
            .help = "password for CHAP authentication to target",
1508 4d454574 Paolo Bonzini
        },{
1509 4d454574 Paolo Bonzini
            .name = "header-digest",
1510 4d454574 Paolo Bonzini
            .type = QEMU_OPT_STRING,
1511 4d454574 Paolo Bonzini
            .help = "HeaderDigest setting. "
1512 4d454574 Paolo Bonzini
                    "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
1513 4d454574 Paolo Bonzini
        },{
1514 4d454574 Paolo Bonzini
            .name = "initiator-name",
1515 4d454574 Paolo Bonzini
            .type = QEMU_OPT_STRING,
1516 4d454574 Paolo Bonzini
            .help = "Initiator iqn name to use when connecting",
1517 4d454574 Paolo Bonzini
        },
1518 4d454574 Paolo Bonzini
        { /* end of list */ }
1519 4d454574 Paolo Bonzini
    },
1520 4d454574 Paolo Bonzini
};
1521 4d454574 Paolo Bonzini
1522 c589b249 Ronnie Sahlberg
static void iscsi_block_init(void)
1523 c589b249 Ronnie Sahlberg
{
1524 c589b249 Ronnie Sahlberg
    bdrv_register(&bdrv_iscsi);
1525 4d454574 Paolo Bonzini
    qemu_add_opts(&qemu_iscsi_opts);
1526 c589b249 Ronnie Sahlberg
}
1527 c589b249 Ronnie Sahlberg
1528 c589b249 Ronnie Sahlberg
block_init(iscsi_block_init);