Statistics
| Branch: | Revision:

root / block / iscsi.c @ 65f3e339

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