Statistics
| Branch: | Revision:

root / block / iscsi.c @ 396d2cfc

History | View | Annotate | Download (26.2 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 dbfff6d7 Ronnie Sahlberg
#include "hw/scsi-defs.h"
35 c589b249 Ronnie Sahlberg
36 c589b249 Ronnie Sahlberg
#include <iscsi/iscsi.h>
37 c589b249 Ronnie Sahlberg
#include <iscsi/scsi-lowlevel.h>
38 c589b249 Ronnie Sahlberg
39 98392453 Ronnie Sahlberg
#ifdef __linux__
40 98392453 Ronnie Sahlberg
#include <scsi/sg.h>
41 98392453 Ronnie Sahlberg
#include <hw/scsi-defs.h>
42 98392453 Ronnie Sahlberg
#endif
43 c589b249 Ronnie Sahlberg
44 c589b249 Ronnie Sahlberg
typedef struct IscsiLun {
45 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi;
46 c589b249 Ronnie Sahlberg
    int lun;
47 dbfff6d7 Ronnie Sahlberg
    enum scsi_inquiry_peripheral_device_type type;
48 c589b249 Ronnie Sahlberg
    int block_size;
49 c7b4a952 Paolo Bonzini
    uint64_t num_blocks;
50 c9b9f682 Ronnie Sahlberg
    int events;
51 c589b249 Ronnie Sahlberg
} IscsiLun;
52 c589b249 Ronnie Sahlberg
53 c589b249 Ronnie Sahlberg
typedef struct IscsiAIOCB {
54 c589b249 Ronnie Sahlberg
    BlockDriverAIOCB common;
55 c589b249 Ronnie Sahlberg
    QEMUIOVector *qiov;
56 c589b249 Ronnie Sahlberg
    QEMUBH *bh;
57 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun;
58 c589b249 Ronnie Sahlberg
    struct scsi_task *task;
59 c589b249 Ronnie Sahlberg
    uint8_t *buf;
60 c589b249 Ronnie Sahlberg
    int status;
61 c589b249 Ronnie Sahlberg
    int canceled;
62 c589b249 Ronnie Sahlberg
    size_t read_size;
63 c589b249 Ronnie Sahlberg
    size_t read_offset;
64 98392453 Ronnie Sahlberg
#ifdef __linux__
65 98392453 Ronnie Sahlberg
    sg_io_hdr_t *ioh;
66 98392453 Ronnie Sahlberg
#endif
67 c589b249 Ronnie Sahlberg
} IscsiAIOCB;
68 c589b249 Ronnie Sahlberg
69 c589b249 Ronnie Sahlberg
static void
70 cfb3f506 Paolo Bonzini
iscsi_bh_cb(void *p)
71 27cbd828 Paolo Bonzini
{
72 27cbd828 Paolo Bonzini
    IscsiAIOCB *acb = p;
73 27cbd828 Paolo Bonzini
74 27cbd828 Paolo Bonzini
    qemu_bh_delete(acb->bh);
75 27cbd828 Paolo Bonzini
76 27cbd828 Paolo Bonzini
    if (acb->canceled == 0) {
77 27cbd828 Paolo Bonzini
        acb->common.cb(acb->common.opaque, acb->status);
78 27cbd828 Paolo Bonzini
    }
79 27cbd828 Paolo Bonzini
80 1bd075f2 Paolo Bonzini
    if (acb->task != NULL) {
81 1bd075f2 Paolo Bonzini
        scsi_free_scsi_task(acb->task);
82 1bd075f2 Paolo Bonzini
        acb->task = NULL;
83 1bd075f2 Paolo Bonzini
    }
84 1bd075f2 Paolo Bonzini
85 27cbd828 Paolo Bonzini
    qemu_aio_release(acb);
86 27cbd828 Paolo Bonzini
}
87 27cbd828 Paolo Bonzini
88 cfb3f506 Paolo Bonzini
static void
89 cfb3f506 Paolo Bonzini
iscsi_schedule_bh(IscsiAIOCB *acb)
90 27cbd828 Paolo Bonzini
{
91 1bd075f2 Paolo Bonzini
    if (acb->bh) {
92 1bd075f2 Paolo Bonzini
        return;
93 1bd075f2 Paolo Bonzini
    }
94 cfb3f506 Paolo Bonzini
    acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
95 27cbd828 Paolo Bonzini
    qemu_bh_schedule(acb->bh);
96 27cbd828 Paolo Bonzini
}
97 27cbd828 Paolo Bonzini
98 27cbd828 Paolo Bonzini
99 27cbd828 Paolo Bonzini
static void
100 c589b249 Ronnie Sahlberg
iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
101 c589b249 Ronnie Sahlberg
                    void *private_data)
102 c589b249 Ronnie Sahlberg
{
103 1bd075f2 Paolo Bonzini
    IscsiAIOCB *acb = private_data;
104 1bd075f2 Paolo Bonzini
105 1bd075f2 Paolo Bonzini
    acb->status = -ECANCELED;
106 1bd075f2 Paolo Bonzini
    iscsi_schedule_bh(acb);
107 c589b249 Ronnie Sahlberg
}
108 c589b249 Ronnie Sahlberg
109 c589b249 Ronnie Sahlberg
static void
110 c589b249 Ronnie Sahlberg
iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
111 c589b249 Ronnie Sahlberg
{
112 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
113 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = acb->iscsilun;
114 c589b249 Ronnie Sahlberg
115 1bd075f2 Paolo Bonzini
    if (acb->status != -EINPROGRESS) {
116 1bd075f2 Paolo Bonzini
        return;
117 1bd075f2 Paolo Bonzini
    }
118 1bd075f2 Paolo Bonzini
119 b2090919 Paolo Bonzini
    acb->canceled = 1;
120 c589b249 Ronnie Sahlberg
121 b2090919 Paolo Bonzini
    /* send a task mgmt call to the target to cancel the task on the target */
122 64e69e80 Stefan Priebe
    iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
123 1bd075f2 Paolo Bonzini
                                     iscsi_abort_task_cb, acb);
124 b2090919 Paolo Bonzini
125 1bd075f2 Paolo Bonzini
    while (acb->status == -EINPROGRESS) {
126 1bd075f2 Paolo Bonzini
        qemu_aio_wait();
127 1bd075f2 Paolo Bonzini
    }
128 c589b249 Ronnie Sahlberg
}
129 c589b249 Ronnie Sahlberg
130 d7331bed Stefan Hajnoczi
static const AIOCBInfo iscsi_aiocb_info = {
131 c589b249 Ronnie Sahlberg
    .aiocb_size         = sizeof(IscsiAIOCB),
132 c589b249 Ronnie Sahlberg
    .cancel             = iscsi_aio_cancel,
133 c589b249 Ronnie Sahlberg
};
134 c589b249 Ronnie Sahlberg
135 c589b249 Ronnie Sahlberg
136 c589b249 Ronnie Sahlberg
static void iscsi_process_read(void *arg);
137 c589b249 Ronnie Sahlberg
static void iscsi_process_write(void *arg);
138 c589b249 Ronnie Sahlberg
139 c589b249 Ronnie Sahlberg
static int iscsi_process_flush(void *arg)
140 c589b249 Ronnie Sahlberg
{
141 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = arg;
142 c589b249 Ronnie Sahlberg
143 c589b249 Ronnie Sahlberg
    return iscsi_queue_length(iscsilun->iscsi) > 0;
144 c589b249 Ronnie Sahlberg
}
145 c589b249 Ronnie Sahlberg
146 c589b249 Ronnie Sahlberg
static void
147 c589b249 Ronnie Sahlberg
iscsi_set_events(IscsiLun *iscsilun)
148 c589b249 Ronnie Sahlberg
{
149 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
150 c9b9f682 Ronnie Sahlberg
    int ev;
151 c9b9f682 Ronnie Sahlberg
152 c9b9f682 Ronnie Sahlberg
    /* We always register a read handler.  */
153 c9b9f682 Ronnie Sahlberg
    ev = POLLIN;
154 c9b9f682 Ronnie Sahlberg
    ev |= iscsi_which_events(iscsi);
155 c9b9f682 Ronnie Sahlberg
    if (ev != iscsilun->events) {
156 c9b9f682 Ronnie Sahlberg
        qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
157 c9b9f682 Ronnie Sahlberg
                      iscsi_process_read,
158 c9b9f682 Ronnie Sahlberg
                      (ev & POLLOUT) ? iscsi_process_write : NULL,
159 c9b9f682 Ronnie Sahlberg
                      iscsi_process_flush,
160 c9b9f682 Ronnie Sahlberg
                      iscsilun);
161 c9b9f682 Ronnie Sahlberg
162 c9b9f682 Ronnie Sahlberg
    }
163 c9b9f682 Ronnie Sahlberg
164 c9b9f682 Ronnie Sahlberg
    iscsilun->events = ev;
165 c589b249 Ronnie Sahlberg
}
166 c589b249 Ronnie Sahlberg
167 c589b249 Ronnie Sahlberg
static void
168 c589b249 Ronnie Sahlberg
iscsi_process_read(void *arg)
169 c589b249 Ronnie Sahlberg
{
170 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = arg;
171 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
172 c589b249 Ronnie Sahlberg
173 c589b249 Ronnie Sahlberg
    iscsi_service(iscsi, POLLIN);
174 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
175 c589b249 Ronnie Sahlberg
}
176 c589b249 Ronnie Sahlberg
177 c589b249 Ronnie Sahlberg
static void
178 c589b249 Ronnie Sahlberg
iscsi_process_write(void *arg)
179 c589b249 Ronnie Sahlberg
{
180 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = arg;
181 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
182 c589b249 Ronnie Sahlberg
183 c589b249 Ronnie Sahlberg
    iscsi_service(iscsi, POLLOUT);
184 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
185 c589b249 Ronnie Sahlberg
}
186 c589b249 Ronnie Sahlberg
187 c589b249 Ronnie Sahlberg
188 c589b249 Ronnie Sahlberg
static void
189 f4dfa67f Ronnie Sahlberg
iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
190 c589b249 Ronnie Sahlberg
                     void *command_data, void *opaque)
191 c589b249 Ronnie Sahlberg
{
192 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb = opaque;
193 c589b249 Ronnie Sahlberg
194 f4dfa67f Ronnie Sahlberg
    trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
195 c589b249 Ronnie Sahlberg
196 c589b249 Ronnie Sahlberg
    g_free(acb->buf);
197 c589b249 Ronnie Sahlberg
198 b2090919 Paolo Bonzini
    if (acb->canceled != 0) {
199 c589b249 Ronnie Sahlberg
        return;
200 c589b249 Ronnie Sahlberg
    }
201 c589b249 Ronnie Sahlberg
202 c589b249 Ronnie Sahlberg
    acb->status = 0;
203 c589b249 Ronnie Sahlberg
    if (status < 0) {
204 f4dfa67f Ronnie Sahlberg
        error_report("Failed to write16 data to iSCSI lun. %s",
205 c589b249 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
206 c589b249 Ronnie Sahlberg
        acb->status = -EIO;
207 c589b249 Ronnie Sahlberg
    }
208 c589b249 Ronnie Sahlberg
209 cfb3f506 Paolo Bonzini
    iscsi_schedule_bh(acb);
210 c589b249 Ronnie Sahlberg
}
211 c589b249 Ronnie Sahlberg
212 c589b249 Ronnie Sahlberg
static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
213 c589b249 Ronnie Sahlberg
{
214 c589b249 Ronnie Sahlberg
    return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
215 c589b249 Ronnie Sahlberg
}
216 c589b249 Ronnie Sahlberg
217 c589b249 Ronnie Sahlberg
static BlockDriverAIOCB *
218 c589b249 Ronnie Sahlberg
iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
219 c589b249 Ronnie Sahlberg
                 QEMUIOVector *qiov, int nb_sectors,
220 c589b249 Ronnie Sahlberg
                 BlockDriverCompletionFunc *cb,
221 c589b249 Ronnie Sahlberg
                 void *opaque)
222 c589b249 Ronnie Sahlberg
{
223 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
224 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
225 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb;
226 c589b249 Ronnie Sahlberg
    size_t size;
227 f4dfa67f Ronnie Sahlberg
    uint32_t num_sectors;
228 f4dfa67f Ronnie Sahlberg
    uint64_t lba;
229 f4dfa67f Ronnie Sahlberg
    struct iscsi_data data;
230 c589b249 Ronnie Sahlberg
231 d7331bed Stefan Hajnoczi
    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
232 c589b249 Ronnie Sahlberg
    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
233 c589b249 Ronnie Sahlberg
234 c589b249 Ronnie Sahlberg
    acb->iscsilun = iscsilun;
235 c589b249 Ronnie Sahlberg
    acb->qiov     = qiov;
236 c589b249 Ronnie Sahlberg
237 c589b249 Ronnie Sahlberg
    acb->canceled   = 0;
238 1bd075f2 Paolo Bonzini
    acb->bh         = NULL;
239 1bd075f2 Paolo Bonzini
    acb->status     = -EINPROGRESS;
240 c589b249 Ronnie Sahlberg
241 f4dfa67f Ronnie Sahlberg
    /* XXX we should pass the iovec to write16 to avoid the extra copy */
242 c589b249 Ronnie Sahlberg
    /* this will allow us to get rid of 'buf' completely */
243 c589b249 Ronnie Sahlberg
    size = nb_sectors * BDRV_SECTOR_SIZE;
244 c589b249 Ronnie Sahlberg
    acb->buf = g_malloc(size);
245 d5e6b161 Michael Tokarev
    qemu_iovec_to_buf(acb->qiov, 0, acb->buf, size);
246 f4dfa67f Ronnie Sahlberg
247 f4dfa67f Ronnie Sahlberg
    acb->task = malloc(sizeof(struct scsi_task));
248 c589b249 Ronnie Sahlberg
    if (acb->task == NULL) {
249 f4dfa67f Ronnie Sahlberg
        error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
250 f4dfa67f Ronnie Sahlberg
                     "command. %s", iscsi_get_error(iscsi));
251 f4dfa67f Ronnie Sahlberg
        qemu_aio_release(acb);
252 f4dfa67f Ronnie Sahlberg
        return NULL;
253 f4dfa67f Ronnie Sahlberg
    }
254 f4dfa67f Ronnie Sahlberg
    memset(acb->task, 0, sizeof(struct scsi_task));
255 f4dfa67f Ronnie Sahlberg
256 f4dfa67f Ronnie Sahlberg
    acb->task->xfer_dir = SCSI_XFER_WRITE;
257 f4dfa67f Ronnie Sahlberg
    acb->task->cdb_size = 16;
258 f4dfa67f Ronnie Sahlberg
    acb->task->cdb[0] = 0x8a;
259 f4dfa67f Ronnie Sahlberg
    lba = sector_qemu2lun(sector_num, iscsilun);
260 f4dfa67f Ronnie Sahlberg
    *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
261 f4dfa67f Ronnie Sahlberg
    *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
262 f4dfa67f Ronnie Sahlberg
    num_sectors = size / iscsilun->block_size;
263 f4dfa67f Ronnie Sahlberg
    *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
264 f4dfa67f Ronnie Sahlberg
    acb->task->expxferlen = size;
265 f4dfa67f Ronnie Sahlberg
266 f4dfa67f Ronnie Sahlberg
    data.data = acb->buf;
267 f4dfa67f Ronnie Sahlberg
    data.size = size;
268 f4dfa67f Ronnie Sahlberg
269 f4dfa67f Ronnie Sahlberg
    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
270 f4dfa67f Ronnie Sahlberg
                                 iscsi_aio_write16_cb,
271 f4dfa67f Ronnie Sahlberg
                                 &data,
272 f4dfa67f Ronnie Sahlberg
                                 acb) != 0) {
273 f4dfa67f Ronnie Sahlberg
        scsi_free_scsi_task(acb->task);
274 c589b249 Ronnie Sahlberg
        g_free(acb->buf);
275 c589b249 Ronnie Sahlberg
        qemu_aio_release(acb);
276 c589b249 Ronnie Sahlberg
        return NULL;
277 c589b249 Ronnie Sahlberg
    }
278 c589b249 Ronnie Sahlberg
279 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
280 c589b249 Ronnie Sahlberg
281 c589b249 Ronnie Sahlberg
    return &acb->common;
282 c589b249 Ronnie Sahlberg
}
283 c589b249 Ronnie Sahlberg
284 c589b249 Ronnie Sahlberg
static void
285 f4dfa67f Ronnie Sahlberg
iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
286 c589b249 Ronnie Sahlberg
                    void *command_data, void *opaque)
287 c589b249 Ronnie Sahlberg
{
288 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb = opaque;
289 c589b249 Ronnie Sahlberg
290 f4dfa67f Ronnie Sahlberg
    trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
291 c589b249 Ronnie Sahlberg
292 b2090919 Paolo Bonzini
    if (acb->canceled != 0) {
293 c589b249 Ronnie Sahlberg
        return;
294 c589b249 Ronnie Sahlberg
    }
295 c589b249 Ronnie Sahlberg
296 c589b249 Ronnie Sahlberg
    acb->status = 0;
297 c589b249 Ronnie Sahlberg
    if (status != 0) {
298 f4dfa67f Ronnie Sahlberg
        error_report("Failed to read16 data from iSCSI lun. %s",
299 c589b249 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
300 c589b249 Ronnie Sahlberg
        acb->status = -EIO;
301 c589b249 Ronnie Sahlberg
    }
302 c589b249 Ronnie Sahlberg
303 cfb3f506 Paolo Bonzini
    iscsi_schedule_bh(acb);
304 c589b249 Ronnie Sahlberg
}
305 c589b249 Ronnie Sahlberg
306 c589b249 Ronnie Sahlberg
static BlockDriverAIOCB *
307 c589b249 Ronnie Sahlberg
iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
308 c589b249 Ronnie Sahlberg
                QEMUIOVector *qiov, int nb_sectors,
309 c589b249 Ronnie Sahlberg
                BlockDriverCompletionFunc *cb,
310 c589b249 Ronnie Sahlberg
                void *opaque)
311 c589b249 Ronnie Sahlberg
{
312 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
313 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
314 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb;
315 f4dfa67f Ronnie Sahlberg
    size_t qemu_read_size;
316 c589b249 Ronnie Sahlberg
    int i;
317 f4dfa67f Ronnie Sahlberg
    uint64_t lba;
318 f4dfa67f Ronnie Sahlberg
    uint32_t num_sectors;
319 c589b249 Ronnie Sahlberg
320 c589b249 Ronnie Sahlberg
    qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
321 c589b249 Ronnie Sahlberg
322 d7331bed Stefan Hajnoczi
    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
323 c589b249 Ronnie Sahlberg
    trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
324 c589b249 Ronnie Sahlberg
325 c589b249 Ronnie Sahlberg
    acb->iscsilun = iscsilun;
326 c589b249 Ronnie Sahlberg
    acb->qiov     = qiov;
327 c589b249 Ronnie Sahlberg
328 c589b249 Ronnie Sahlberg
    acb->canceled    = 0;
329 1bd075f2 Paolo Bonzini
    acb->bh          = NULL;
330 1bd075f2 Paolo Bonzini
    acb->status      = -EINPROGRESS;
331 c589b249 Ronnie Sahlberg
    acb->read_size   = qemu_read_size;
332 c589b249 Ronnie Sahlberg
    acb->buf         = NULL;
333 c589b249 Ronnie Sahlberg
334 c589b249 Ronnie Sahlberg
    /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
335 c589b249 Ronnie Sahlberg
     * may be misaligned to the LUN, so we may need to read some extra
336 c589b249 Ronnie Sahlberg
     * data.
337 c589b249 Ronnie Sahlberg
     */
338 c589b249 Ronnie Sahlberg
    acb->read_offset = 0;
339 c589b249 Ronnie Sahlberg
    if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
340 c589b249 Ronnie Sahlberg
        uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;
341 c589b249 Ronnie Sahlberg
342 c589b249 Ronnie Sahlberg
        acb->read_offset  = bdrv_offset % iscsilun->block_size;
343 c589b249 Ronnie Sahlberg
    }
344 c589b249 Ronnie Sahlberg
345 f4dfa67f Ronnie Sahlberg
    num_sectors  = (qemu_read_size + iscsilun->block_size
346 f4dfa67f Ronnie Sahlberg
                    + acb->read_offset - 1)
347 f4dfa67f Ronnie Sahlberg
                    / iscsilun->block_size;
348 f4dfa67f Ronnie Sahlberg
349 f4dfa67f Ronnie Sahlberg
    acb->task = malloc(sizeof(struct scsi_task));
350 c589b249 Ronnie Sahlberg
    if (acb->task == NULL) {
351 f4dfa67f Ronnie Sahlberg
        error_report("iSCSI: Failed to allocate task for scsi READ16 "
352 f4dfa67f Ronnie Sahlberg
                     "command. %s", iscsi_get_error(iscsi));
353 f4dfa67f Ronnie Sahlberg
        qemu_aio_release(acb);
354 f4dfa67f Ronnie Sahlberg
        return NULL;
355 f4dfa67f Ronnie Sahlberg
    }
356 f4dfa67f Ronnie Sahlberg
    memset(acb->task, 0, sizeof(struct scsi_task));
357 f4dfa67f Ronnie Sahlberg
358 f4dfa67f Ronnie Sahlberg
    acb->task->xfer_dir = SCSI_XFER_READ;
359 f4dfa67f Ronnie Sahlberg
    lba = sector_qemu2lun(sector_num, iscsilun);
360 f4dfa67f Ronnie Sahlberg
    acb->task->expxferlen = qemu_read_size;
361 f4dfa67f Ronnie Sahlberg
362 f4dfa67f Ronnie Sahlberg
    switch (iscsilun->type) {
363 f4dfa67f Ronnie Sahlberg
    case TYPE_DISK:
364 f4dfa67f Ronnie Sahlberg
        acb->task->cdb_size = 16;
365 f4dfa67f Ronnie Sahlberg
        acb->task->cdb[0]  = 0x88;
366 f4dfa67f Ronnie Sahlberg
        *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
367 f4dfa67f Ronnie Sahlberg
        *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
368 f4dfa67f Ronnie Sahlberg
        *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
369 f4dfa67f Ronnie Sahlberg
        break;
370 f4dfa67f Ronnie Sahlberg
    default:
371 f4dfa67f Ronnie Sahlberg
        acb->task->cdb_size = 10;
372 f4dfa67f Ronnie Sahlberg
        acb->task->cdb[0]  = 0x28;
373 f4dfa67f Ronnie Sahlberg
        *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
374 f4dfa67f Ronnie Sahlberg
        *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
375 f4dfa67f Ronnie Sahlberg
        break;
376 f4dfa67f Ronnie Sahlberg
    }
377 e829b0bb Peter Lieven
378 f4dfa67f Ronnie Sahlberg
    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
379 f4dfa67f Ronnie Sahlberg
                                 iscsi_aio_read16_cb,
380 f4dfa67f Ronnie Sahlberg
                                 NULL,
381 f4dfa67f Ronnie Sahlberg
                                 acb) != 0) {
382 f4dfa67f Ronnie Sahlberg
        scsi_free_scsi_task(acb->task);
383 c589b249 Ronnie Sahlberg
        qemu_aio_release(acb);
384 c589b249 Ronnie Sahlberg
        return NULL;
385 c589b249 Ronnie Sahlberg
    }
386 c589b249 Ronnie Sahlberg
387 c589b249 Ronnie Sahlberg
    for (i = 0; i < acb->qiov->niov; i++) {
388 c589b249 Ronnie Sahlberg
        scsi_task_add_data_in_buffer(acb->task,
389 c589b249 Ronnie Sahlberg
                acb->qiov->iov[i].iov_len,
390 c589b249 Ronnie Sahlberg
                acb->qiov->iov[i].iov_base);
391 c589b249 Ronnie Sahlberg
    }
392 c589b249 Ronnie Sahlberg
393 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
394 c589b249 Ronnie Sahlberg
395 c589b249 Ronnie Sahlberg
    return &acb->common;
396 c589b249 Ronnie Sahlberg
}
397 c589b249 Ronnie Sahlberg
398 c589b249 Ronnie Sahlberg
399 c589b249 Ronnie Sahlberg
static void
400 c589b249 Ronnie Sahlberg
iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
401 c589b249 Ronnie Sahlberg
                     void *command_data, void *opaque)
402 c589b249 Ronnie Sahlberg
{
403 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb = opaque;
404 c589b249 Ronnie Sahlberg
405 b2090919 Paolo Bonzini
    if (acb->canceled != 0) {
406 c589b249 Ronnie Sahlberg
        return;
407 c589b249 Ronnie Sahlberg
    }
408 c589b249 Ronnie Sahlberg
409 c589b249 Ronnie Sahlberg
    acb->status = 0;
410 c589b249 Ronnie Sahlberg
    if (status < 0) {
411 c589b249 Ronnie Sahlberg
        error_report("Failed to sync10 data on iSCSI lun. %s",
412 c589b249 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
413 c589b249 Ronnie Sahlberg
        acb->status = -EIO;
414 c589b249 Ronnie Sahlberg
    }
415 c589b249 Ronnie Sahlberg
416 cfb3f506 Paolo Bonzini
    iscsi_schedule_bh(acb);
417 c589b249 Ronnie Sahlberg
}
418 c589b249 Ronnie Sahlberg
419 c589b249 Ronnie Sahlberg
static BlockDriverAIOCB *
420 c589b249 Ronnie Sahlberg
iscsi_aio_flush(BlockDriverState *bs,
421 c589b249 Ronnie Sahlberg
                BlockDriverCompletionFunc *cb, void *opaque)
422 c589b249 Ronnie Sahlberg
{
423 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
424 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
425 c589b249 Ronnie Sahlberg
    IscsiAIOCB *acb;
426 c589b249 Ronnie Sahlberg
427 d7331bed Stefan Hajnoczi
    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
428 c589b249 Ronnie Sahlberg
429 c589b249 Ronnie Sahlberg
    acb->iscsilun = iscsilun;
430 c589b249 Ronnie Sahlberg
    acb->canceled   = 0;
431 1bd075f2 Paolo Bonzini
    acb->bh         = NULL;
432 1bd075f2 Paolo Bonzini
    acb->status     = -EINPROGRESS;
433 c589b249 Ronnie Sahlberg
434 c589b249 Ronnie Sahlberg
    acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
435 c589b249 Ronnie Sahlberg
                                         0, 0, 0, 0,
436 c589b249 Ronnie Sahlberg
                                         iscsi_synccache10_cb,
437 c589b249 Ronnie Sahlberg
                                         acb);
438 c589b249 Ronnie Sahlberg
    if (acb->task == NULL) {
439 c589b249 Ronnie Sahlberg
        error_report("iSCSI: Failed to send synchronizecache10 command. %s",
440 c589b249 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
441 c589b249 Ronnie Sahlberg
        qemu_aio_release(acb);
442 c589b249 Ronnie Sahlberg
        return NULL;
443 c589b249 Ronnie Sahlberg
    }
444 c589b249 Ronnie Sahlberg
445 c589b249 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
446 c589b249 Ronnie Sahlberg
447 c589b249 Ronnie Sahlberg
    return &acb->common;
448 c589b249 Ronnie Sahlberg
}
449 c589b249 Ronnie Sahlberg
450 fa6acb0c Ronnie Sahlberg
static void
451 fa6acb0c Ronnie Sahlberg
iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
452 fa6acb0c Ronnie Sahlberg
                     void *command_data, void *opaque)
453 fa6acb0c Ronnie Sahlberg
{
454 fa6acb0c Ronnie Sahlberg
    IscsiAIOCB *acb = opaque;
455 fa6acb0c Ronnie Sahlberg
456 b2090919 Paolo Bonzini
    if (acb->canceled != 0) {
457 fa6acb0c Ronnie Sahlberg
        return;
458 fa6acb0c Ronnie Sahlberg
    }
459 fa6acb0c Ronnie Sahlberg
460 fa6acb0c Ronnie Sahlberg
    acb->status = 0;
461 fa6acb0c Ronnie Sahlberg
    if (status < 0) {
462 fa6acb0c Ronnie Sahlberg
        error_report("Failed to unmap data on iSCSI lun. %s",
463 fa6acb0c Ronnie Sahlberg
                     iscsi_get_error(iscsi));
464 fa6acb0c Ronnie Sahlberg
        acb->status = -EIO;
465 fa6acb0c Ronnie Sahlberg
    }
466 fa6acb0c Ronnie Sahlberg
467 cfb3f506 Paolo Bonzini
    iscsi_schedule_bh(acb);
468 fa6acb0c Ronnie Sahlberg
}
469 fa6acb0c Ronnie Sahlberg
470 fa6acb0c Ronnie Sahlberg
static BlockDriverAIOCB *
471 fa6acb0c Ronnie Sahlberg
iscsi_aio_discard(BlockDriverState *bs,
472 fa6acb0c Ronnie Sahlberg
                  int64_t sector_num, int nb_sectors,
473 fa6acb0c Ronnie Sahlberg
                  BlockDriverCompletionFunc *cb, void *opaque)
474 fa6acb0c Ronnie Sahlberg
{
475 fa6acb0c Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
476 fa6acb0c Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
477 fa6acb0c Ronnie Sahlberg
    IscsiAIOCB *acb;
478 fa6acb0c Ronnie Sahlberg
    struct unmap_list list[1];
479 fa6acb0c Ronnie Sahlberg
480 d7331bed Stefan Hajnoczi
    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
481 fa6acb0c Ronnie Sahlberg
482 fa6acb0c Ronnie Sahlberg
    acb->iscsilun = iscsilun;
483 fa6acb0c Ronnie Sahlberg
    acb->canceled   = 0;
484 1bd075f2 Paolo Bonzini
    acb->bh         = NULL;
485 1bd075f2 Paolo Bonzini
    acb->status     = -EINPROGRESS;
486 fa6acb0c Ronnie Sahlberg
487 fa6acb0c Ronnie Sahlberg
    list[0].lba = sector_qemu2lun(sector_num, iscsilun);
488 fa6acb0c Ronnie Sahlberg
    list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
489 fa6acb0c Ronnie Sahlberg
490 fa6acb0c Ronnie Sahlberg
    acb->task = iscsi_unmap_task(iscsi, iscsilun->lun,
491 fa6acb0c Ronnie Sahlberg
                                 0, 0, &list[0], 1,
492 fa6acb0c Ronnie Sahlberg
                                 iscsi_unmap_cb,
493 fa6acb0c Ronnie Sahlberg
                                 acb);
494 fa6acb0c Ronnie Sahlberg
    if (acb->task == NULL) {
495 fa6acb0c Ronnie Sahlberg
        error_report("iSCSI: Failed to send unmap command. %s",
496 fa6acb0c Ronnie Sahlberg
                     iscsi_get_error(iscsi));
497 fa6acb0c Ronnie Sahlberg
        qemu_aio_release(acb);
498 fa6acb0c Ronnie Sahlberg
        return NULL;
499 fa6acb0c Ronnie Sahlberg
    }
500 fa6acb0c Ronnie Sahlberg
501 fa6acb0c Ronnie Sahlberg
    iscsi_set_events(iscsilun);
502 fa6acb0c Ronnie Sahlberg
503 fa6acb0c Ronnie Sahlberg
    return &acb->common;
504 fa6acb0c Ronnie Sahlberg
}
505 fa6acb0c Ronnie Sahlberg
506 98392453 Ronnie Sahlberg
#ifdef __linux__
507 98392453 Ronnie Sahlberg
static void
508 98392453 Ronnie Sahlberg
iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
509 98392453 Ronnie Sahlberg
                     void *command_data, void *opaque)
510 98392453 Ronnie Sahlberg
{
511 98392453 Ronnie Sahlberg
    IscsiAIOCB *acb = opaque;
512 98392453 Ronnie Sahlberg
513 b2090919 Paolo Bonzini
    if (acb->canceled != 0) {
514 98392453 Ronnie Sahlberg
        return;
515 98392453 Ronnie Sahlberg
    }
516 98392453 Ronnie Sahlberg
517 98392453 Ronnie Sahlberg
    acb->status = 0;
518 98392453 Ronnie Sahlberg
    if (status < 0) {
519 98392453 Ronnie Sahlberg
        error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
520 98392453 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
521 98392453 Ronnie Sahlberg
        acb->status = -EIO;
522 98392453 Ronnie Sahlberg
    }
523 98392453 Ronnie Sahlberg
524 98392453 Ronnie Sahlberg
    acb->ioh->driver_status = 0;
525 98392453 Ronnie Sahlberg
    acb->ioh->host_status   = 0;
526 98392453 Ronnie Sahlberg
    acb->ioh->resid         = 0;
527 98392453 Ronnie Sahlberg
528 98392453 Ronnie Sahlberg
#define SG_ERR_DRIVER_SENSE    0x08
529 98392453 Ronnie Sahlberg
530 98392453 Ronnie Sahlberg
    if (status == SCSI_STATUS_CHECK_CONDITION && acb->task->datain.size >= 2) {
531 98392453 Ronnie Sahlberg
        int ss;
532 98392453 Ronnie Sahlberg
533 98392453 Ronnie Sahlberg
        acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
534 98392453 Ronnie Sahlberg
535 98392453 Ronnie Sahlberg
        acb->ioh->sb_len_wr = acb->task->datain.size - 2;
536 98392453 Ronnie Sahlberg
        ss = (acb->ioh->mx_sb_len >= acb->ioh->sb_len_wr) ?
537 98392453 Ronnie Sahlberg
             acb->ioh->mx_sb_len : acb->ioh->sb_len_wr;
538 98392453 Ronnie Sahlberg
        memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
539 98392453 Ronnie Sahlberg
    }
540 98392453 Ronnie Sahlberg
541 cfb3f506 Paolo Bonzini
    iscsi_schedule_bh(acb);
542 98392453 Ronnie Sahlberg
}
543 98392453 Ronnie Sahlberg
544 98392453 Ronnie Sahlberg
static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
545 98392453 Ronnie Sahlberg
        unsigned long int req, void *buf,
546 98392453 Ronnie Sahlberg
        BlockDriverCompletionFunc *cb, void *opaque)
547 98392453 Ronnie Sahlberg
{
548 98392453 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
549 98392453 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
550 98392453 Ronnie Sahlberg
    struct iscsi_data data;
551 98392453 Ronnie Sahlberg
    IscsiAIOCB *acb;
552 98392453 Ronnie Sahlberg
553 98392453 Ronnie Sahlberg
    assert(req == SG_IO);
554 98392453 Ronnie Sahlberg
555 d7331bed Stefan Hajnoczi
    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
556 98392453 Ronnie Sahlberg
557 98392453 Ronnie Sahlberg
    acb->iscsilun = iscsilun;
558 98392453 Ronnie Sahlberg
    acb->canceled    = 0;
559 1bd075f2 Paolo Bonzini
    acb->bh          = NULL;
560 1bd075f2 Paolo Bonzini
    acb->status      = -EINPROGRESS;
561 98392453 Ronnie Sahlberg
    acb->buf         = NULL;
562 98392453 Ronnie Sahlberg
    acb->ioh         = buf;
563 98392453 Ronnie Sahlberg
564 98392453 Ronnie Sahlberg
    acb->task = malloc(sizeof(struct scsi_task));
565 98392453 Ronnie Sahlberg
    if (acb->task == NULL) {
566 98392453 Ronnie Sahlberg
        error_report("iSCSI: Failed to allocate task for scsi command. %s",
567 98392453 Ronnie Sahlberg
                     iscsi_get_error(iscsi));
568 98392453 Ronnie Sahlberg
        qemu_aio_release(acb);
569 98392453 Ronnie Sahlberg
        return NULL;
570 98392453 Ronnie Sahlberg
    }
571 98392453 Ronnie Sahlberg
    memset(acb->task, 0, sizeof(struct scsi_task));
572 98392453 Ronnie Sahlberg
573 98392453 Ronnie Sahlberg
    switch (acb->ioh->dxfer_direction) {
574 98392453 Ronnie Sahlberg
    case SG_DXFER_TO_DEV:
575 98392453 Ronnie Sahlberg
        acb->task->xfer_dir = SCSI_XFER_WRITE;
576 98392453 Ronnie Sahlberg
        break;
577 98392453 Ronnie Sahlberg
    case SG_DXFER_FROM_DEV:
578 98392453 Ronnie Sahlberg
        acb->task->xfer_dir = SCSI_XFER_READ;
579 98392453 Ronnie Sahlberg
        break;
580 98392453 Ronnie Sahlberg
    default:
581 98392453 Ronnie Sahlberg
        acb->task->xfer_dir = SCSI_XFER_NONE;
582 98392453 Ronnie Sahlberg
        break;
583 98392453 Ronnie Sahlberg
    }
584 98392453 Ronnie Sahlberg
585 98392453 Ronnie Sahlberg
    acb->task->cdb_size = acb->ioh->cmd_len;
586 98392453 Ronnie Sahlberg
    memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
587 98392453 Ronnie Sahlberg
    acb->task->expxferlen = acb->ioh->dxfer_len;
588 98392453 Ronnie Sahlberg
589 98392453 Ronnie Sahlberg
    if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
590 98392453 Ronnie Sahlberg
        data.data = acb->ioh->dxferp;
591 98392453 Ronnie Sahlberg
        data.size = acb->ioh->dxfer_len;
592 98392453 Ronnie Sahlberg
    }
593 98392453 Ronnie Sahlberg
    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
594 98392453 Ronnie Sahlberg
                                 iscsi_aio_ioctl_cb,
595 98392453 Ronnie Sahlberg
                                 (acb->task->xfer_dir == SCSI_XFER_WRITE) ?
596 98392453 Ronnie Sahlberg
                                     &data : NULL,
597 98392453 Ronnie Sahlberg
                                 acb) != 0) {
598 98392453 Ronnie Sahlberg
        scsi_free_scsi_task(acb->task);
599 98392453 Ronnie Sahlberg
        qemu_aio_release(acb);
600 98392453 Ronnie Sahlberg
        return NULL;
601 98392453 Ronnie Sahlberg
    }
602 98392453 Ronnie Sahlberg
603 98392453 Ronnie Sahlberg
    /* tell libiscsi to read straight into the buffer we got from ioctl */
604 98392453 Ronnie Sahlberg
    if (acb->task->xfer_dir == SCSI_XFER_READ) {
605 98392453 Ronnie Sahlberg
        scsi_task_add_data_in_buffer(acb->task,
606 98392453 Ronnie Sahlberg
                                     acb->ioh->dxfer_len,
607 98392453 Ronnie Sahlberg
                                     acb->ioh->dxferp);
608 98392453 Ronnie Sahlberg
    }
609 98392453 Ronnie Sahlberg
610 98392453 Ronnie Sahlberg
    iscsi_set_events(iscsilun);
611 98392453 Ronnie Sahlberg
612 98392453 Ronnie Sahlberg
    return &acb->common;
613 98392453 Ronnie Sahlberg
}
614 98392453 Ronnie Sahlberg
615 f1a12821 Ronnie Sahlberg
616 f1a12821 Ronnie Sahlberg
static void ioctl_cb(void *opaque, int status)
617 f1a12821 Ronnie Sahlberg
{
618 f1a12821 Ronnie Sahlberg
    int *p_status = opaque;
619 f1a12821 Ronnie Sahlberg
    *p_status = status;
620 f1a12821 Ronnie Sahlberg
}
621 f1a12821 Ronnie Sahlberg
622 98392453 Ronnie Sahlberg
static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
623 98392453 Ronnie Sahlberg
{
624 98392453 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
625 f1a12821 Ronnie Sahlberg
    int status;
626 98392453 Ronnie Sahlberg
627 98392453 Ronnie Sahlberg
    switch (req) {
628 98392453 Ronnie Sahlberg
    case SG_GET_VERSION_NUM:
629 98392453 Ronnie Sahlberg
        *(int *)buf = 30000;
630 98392453 Ronnie Sahlberg
        break;
631 98392453 Ronnie Sahlberg
    case SG_GET_SCSI_ID:
632 98392453 Ronnie Sahlberg
        ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
633 98392453 Ronnie Sahlberg
        break;
634 f1a12821 Ronnie Sahlberg
    case SG_IO:
635 f1a12821 Ronnie Sahlberg
        status = -EINPROGRESS;
636 f1a12821 Ronnie Sahlberg
        iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
637 f1a12821 Ronnie Sahlberg
638 f1a12821 Ronnie Sahlberg
        while (status == -EINPROGRESS) {
639 f1a12821 Ronnie Sahlberg
            qemu_aio_wait();
640 f1a12821 Ronnie Sahlberg
        }
641 f1a12821 Ronnie Sahlberg
642 f1a12821 Ronnie Sahlberg
        return 0;
643 98392453 Ronnie Sahlberg
    default:
644 98392453 Ronnie Sahlberg
        return -1;
645 98392453 Ronnie Sahlberg
    }
646 98392453 Ronnie Sahlberg
    return 0;
647 98392453 Ronnie Sahlberg
}
648 98392453 Ronnie Sahlberg
#endif
649 98392453 Ronnie Sahlberg
650 c589b249 Ronnie Sahlberg
static int64_t
651 c589b249 Ronnie Sahlberg
iscsi_getlength(BlockDriverState *bs)
652 c589b249 Ronnie Sahlberg
{
653 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
654 c589b249 Ronnie Sahlberg
    int64_t len;
655 c589b249 Ronnie Sahlberg
656 c589b249 Ronnie Sahlberg
    len  = iscsilun->num_blocks;
657 c589b249 Ronnie Sahlberg
    len *= iscsilun->block_size;
658 c589b249 Ronnie Sahlberg
659 c589b249 Ronnie Sahlberg
    return len;
660 c589b249 Ronnie Sahlberg
}
661 c589b249 Ronnie Sahlberg
662 f9dadc98 Ronnie Sahlberg
static int parse_chap(struct iscsi_context *iscsi, const char *target)
663 f9dadc98 Ronnie Sahlberg
{
664 f9dadc98 Ronnie Sahlberg
    QemuOptsList *list;
665 f9dadc98 Ronnie Sahlberg
    QemuOpts *opts;
666 f9dadc98 Ronnie Sahlberg
    const char *user = NULL;
667 f9dadc98 Ronnie Sahlberg
    const char *password = NULL;
668 f9dadc98 Ronnie Sahlberg
669 f9dadc98 Ronnie Sahlberg
    list = qemu_find_opts("iscsi");
670 f9dadc98 Ronnie Sahlberg
    if (!list) {
671 f9dadc98 Ronnie Sahlberg
        return 0;
672 f9dadc98 Ronnie Sahlberg
    }
673 f9dadc98 Ronnie Sahlberg
674 f9dadc98 Ronnie Sahlberg
    opts = qemu_opts_find(list, target);
675 f9dadc98 Ronnie Sahlberg
    if (opts == NULL) {
676 f9dadc98 Ronnie Sahlberg
        opts = QTAILQ_FIRST(&list->head);
677 f9dadc98 Ronnie Sahlberg
        if (!opts) {
678 f9dadc98 Ronnie Sahlberg
            return 0;
679 f9dadc98 Ronnie Sahlberg
        }
680 f9dadc98 Ronnie Sahlberg
    }
681 f9dadc98 Ronnie Sahlberg
682 f9dadc98 Ronnie Sahlberg
    user = qemu_opt_get(opts, "user");
683 f9dadc98 Ronnie Sahlberg
    if (!user) {
684 f9dadc98 Ronnie Sahlberg
        return 0;
685 f9dadc98 Ronnie Sahlberg
    }
686 f9dadc98 Ronnie Sahlberg
687 f9dadc98 Ronnie Sahlberg
    password = qemu_opt_get(opts, "password");
688 f9dadc98 Ronnie Sahlberg
    if (!password) {
689 f9dadc98 Ronnie Sahlberg
        error_report("CHAP username specified but no password was given");
690 f9dadc98 Ronnie Sahlberg
        return -1;
691 f9dadc98 Ronnie Sahlberg
    }
692 f9dadc98 Ronnie Sahlberg
693 f9dadc98 Ronnie Sahlberg
    if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
694 f9dadc98 Ronnie Sahlberg
        error_report("Failed to set initiator username and password");
695 f9dadc98 Ronnie Sahlberg
        return -1;
696 f9dadc98 Ronnie Sahlberg
    }
697 f9dadc98 Ronnie Sahlberg
698 f9dadc98 Ronnie Sahlberg
    return 0;
699 f9dadc98 Ronnie Sahlberg
}
700 f9dadc98 Ronnie Sahlberg
701 f9dadc98 Ronnie Sahlberg
static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
702 f9dadc98 Ronnie Sahlberg
{
703 f9dadc98 Ronnie Sahlberg
    QemuOptsList *list;
704 f9dadc98 Ronnie Sahlberg
    QemuOpts *opts;
705 f9dadc98 Ronnie Sahlberg
    const char *digest = NULL;
706 f9dadc98 Ronnie Sahlberg
707 f9dadc98 Ronnie Sahlberg
    list = qemu_find_opts("iscsi");
708 f9dadc98 Ronnie Sahlberg
    if (!list) {
709 f9dadc98 Ronnie Sahlberg
        return;
710 f9dadc98 Ronnie Sahlberg
    }
711 f9dadc98 Ronnie Sahlberg
712 f9dadc98 Ronnie Sahlberg
    opts = qemu_opts_find(list, target);
713 f9dadc98 Ronnie Sahlberg
    if (opts == NULL) {
714 f9dadc98 Ronnie Sahlberg
        opts = QTAILQ_FIRST(&list->head);
715 f9dadc98 Ronnie Sahlberg
        if (!opts) {
716 f9dadc98 Ronnie Sahlberg
            return;
717 f9dadc98 Ronnie Sahlberg
        }
718 f9dadc98 Ronnie Sahlberg
    }
719 f9dadc98 Ronnie Sahlberg
720 f9dadc98 Ronnie Sahlberg
    digest = qemu_opt_get(opts, "header-digest");
721 f9dadc98 Ronnie Sahlberg
    if (!digest) {
722 f9dadc98 Ronnie Sahlberg
        return;
723 f9dadc98 Ronnie Sahlberg
    }
724 f9dadc98 Ronnie Sahlberg
725 f9dadc98 Ronnie Sahlberg
    if (!strcmp(digest, "CRC32C")) {
726 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
727 f9dadc98 Ronnie Sahlberg
    } else if (!strcmp(digest, "NONE")) {
728 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
729 f9dadc98 Ronnie Sahlberg
    } else if (!strcmp(digest, "CRC32C-NONE")) {
730 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
731 f9dadc98 Ronnie Sahlberg
    } else if (!strcmp(digest, "NONE-CRC32C")) {
732 f9dadc98 Ronnie Sahlberg
        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
733 f9dadc98 Ronnie Sahlberg
    } else {
734 f9dadc98 Ronnie Sahlberg
        error_report("Invalid header-digest setting : %s", digest);
735 f9dadc98 Ronnie Sahlberg
    }
736 f9dadc98 Ronnie Sahlberg
}
737 f9dadc98 Ronnie Sahlberg
738 f9dadc98 Ronnie Sahlberg
static char *parse_initiator_name(const char *target)
739 f9dadc98 Ronnie Sahlberg
{
740 f9dadc98 Ronnie Sahlberg
    QemuOptsList *list;
741 f9dadc98 Ronnie Sahlberg
    QemuOpts *opts;
742 f9dadc98 Ronnie Sahlberg
    const char *name = NULL;
743 31459f46 Ronnie Sahlberg
    const char *iscsi_name = qemu_get_vm_name();
744 f9dadc98 Ronnie Sahlberg
745 f9dadc98 Ronnie Sahlberg
    list = qemu_find_opts("iscsi");
746 f2ef4a6d Paolo Bonzini
    if (list) {
747 f2ef4a6d Paolo Bonzini
        opts = qemu_opts_find(list, target);
748 f9dadc98 Ronnie Sahlberg
        if (!opts) {
749 f2ef4a6d Paolo Bonzini
            opts = QTAILQ_FIRST(&list->head);
750 f2ef4a6d Paolo Bonzini
        }
751 f2ef4a6d Paolo Bonzini
        if (opts) {
752 f2ef4a6d Paolo Bonzini
            name = qemu_opt_get(opts, "initiator-name");
753 f9dadc98 Ronnie Sahlberg
        }
754 f9dadc98 Ronnie Sahlberg
    }
755 f9dadc98 Ronnie Sahlberg
756 f2ef4a6d Paolo Bonzini
    if (name) {
757 f2ef4a6d Paolo Bonzini
        return g_strdup(name);
758 f2ef4a6d Paolo Bonzini
    } else {
759 31459f46 Ronnie Sahlberg
        return g_strdup_printf("iqn.2008-11.org.linux-kvm%s%s",
760 31459f46 Ronnie Sahlberg
                               iscsi_name ? ":" : "",
761 31459f46 Ronnie Sahlberg
                               iscsi_name ? iscsi_name : "");
762 f9dadc98 Ronnie Sahlberg
    }
763 f9dadc98 Ronnie Sahlberg
}
764 f9dadc98 Ronnie Sahlberg
765 c589b249 Ronnie Sahlberg
/*
766 c589b249 Ronnie Sahlberg
 * We support iscsi url's on the form
767 c589b249 Ronnie Sahlberg
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
768 c589b249 Ronnie Sahlberg
 */
769 c589b249 Ronnie Sahlberg
static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
770 c589b249 Ronnie Sahlberg
{
771 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
772 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = NULL;
773 c589b249 Ronnie Sahlberg
    struct iscsi_url *iscsi_url = NULL;
774 e829b0bb Peter Lieven
    struct scsi_task *task = NULL;
775 e829b0bb Peter Lieven
    struct scsi_inquiry_standard *inq = NULL;
776 e829b0bb Peter Lieven
    struct scsi_readcapacity10 *rc10 = NULL;
777 e829b0bb Peter Lieven
    struct scsi_readcapacity16 *rc16 = NULL;
778 f9dadc98 Ronnie Sahlberg
    char *initiator_name = NULL;
779 c589b249 Ronnie Sahlberg
    int ret;
780 c589b249 Ronnie Sahlberg
781 c589b249 Ronnie Sahlberg
    if ((BDRV_SECTOR_SIZE % 512) != 0) {
782 c589b249 Ronnie Sahlberg
        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
783 c589b249 Ronnie Sahlberg
                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
784 c589b249 Ronnie Sahlberg
                     "of 512", BDRV_SECTOR_SIZE);
785 c589b249 Ronnie Sahlberg
        return -EINVAL;
786 c589b249 Ronnie Sahlberg
    }
787 c589b249 Ronnie Sahlberg
788 c589b249 Ronnie Sahlberg
    iscsi_url = iscsi_parse_full_url(iscsi, filename);
789 c589b249 Ronnie Sahlberg
    if (iscsi_url == NULL) {
790 8da1e18b Peter Lieven
        error_report("Failed to parse URL : %s", filename);
791 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
792 b93c94f7 Paolo Bonzini
        goto out;
793 c589b249 Ronnie Sahlberg
    }
794 c589b249 Ronnie Sahlberg
795 f9dadc98 Ronnie Sahlberg
    memset(iscsilun, 0, sizeof(IscsiLun));
796 f9dadc98 Ronnie Sahlberg
797 f9dadc98 Ronnie Sahlberg
    initiator_name = parse_initiator_name(iscsi_url->target);
798 f9dadc98 Ronnie Sahlberg
799 f9dadc98 Ronnie Sahlberg
    iscsi = iscsi_create_context(initiator_name);
800 f9dadc98 Ronnie Sahlberg
    if (iscsi == NULL) {
801 f9dadc98 Ronnie Sahlberg
        error_report("iSCSI: Failed to create iSCSI context.");
802 f9dadc98 Ronnie Sahlberg
        ret = -ENOMEM;
803 b93c94f7 Paolo Bonzini
        goto out;
804 f9dadc98 Ronnie Sahlberg
    }
805 f9dadc98 Ronnie Sahlberg
806 c589b249 Ronnie Sahlberg
    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
807 c589b249 Ronnie Sahlberg
        error_report("iSCSI: Failed to set target name.");
808 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
809 b93c94f7 Paolo Bonzini
        goto out;
810 c589b249 Ronnie Sahlberg
    }
811 c589b249 Ronnie Sahlberg
812 c589b249 Ronnie Sahlberg
    if (iscsi_url->user != NULL) {
813 c589b249 Ronnie Sahlberg
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
814 c589b249 Ronnie Sahlberg
                                              iscsi_url->passwd);
815 c589b249 Ronnie Sahlberg
        if (ret != 0) {
816 c589b249 Ronnie Sahlberg
            error_report("Failed to set initiator username and password");
817 c589b249 Ronnie Sahlberg
            ret = -EINVAL;
818 b93c94f7 Paolo Bonzini
            goto out;
819 c589b249 Ronnie Sahlberg
        }
820 c589b249 Ronnie Sahlberg
    }
821 f9dadc98 Ronnie Sahlberg
822 f9dadc98 Ronnie Sahlberg
    /* check if we got CHAP username/password via the options */
823 f9dadc98 Ronnie Sahlberg
    if (parse_chap(iscsi, iscsi_url->target) != 0) {
824 f9dadc98 Ronnie Sahlberg
        error_report("iSCSI: Failed to set CHAP user/password");
825 f9dadc98 Ronnie Sahlberg
        ret = -EINVAL;
826 b93c94f7 Paolo Bonzini
        goto out;
827 f9dadc98 Ronnie Sahlberg
    }
828 f9dadc98 Ronnie Sahlberg
829 c589b249 Ronnie Sahlberg
    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
830 c589b249 Ronnie Sahlberg
        error_report("iSCSI: Failed to set session type to normal.");
831 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
832 b93c94f7 Paolo Bonzini
        goto out;
833 c589b249 Ronnie Sahlberg
    }
834 c589b249 Ronnie Sahlberg
835 c589b249 Ronnie Sahlberg
    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
836 c589b249 Ronnie Sahlberg
837 f9dadc98 Ronnie Sahlberg
    /* check if we got HEADER_DIGEST via the options */
838 f9dadc98 Ronnie Sahlberg
    parse_header_digest(iscsi, iscsi_url->target);
839 f9dadc98 Ronnie Sahlberg
840 e829b0bb Peter Lieven
    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
841 e829b0bb Peter Lieven
        error_report("iSCSI: Failed to connect to LUN : %s",
842 e829b0bb Peter Lieven
            iscsi_get_error(iscsi));
843 e829b0bb Peter Lieven
        ret = -EINVAL;
844 e829b0bb Peter Lieven
        goto out;
845 e829b0bb Peter Lieven
    }
846 c589b249 Ronnie Sahlberg
847 c589b249 Ronnie Sahlberg
    iscsilun->iscsi = iscsi;
848 c589b249 Ronnie Sahlberg
    iscsilun->lun   = iscsi_url->lun;
849 c589b249 Ronnie Sahlberg
850 e829b0bb Peter Lieven
    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
851 e829b0bb Peter Lieven
852 e829b0bb Peter Lieven
    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
853 e829b0bb Peter Lieven
        error_report("iSCSI: failed to send inquiry command.");
854 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
855 b93c94f7 Paolo Bonzini
        goto out;
856 c589b249 Ronnie Sahlberg
    }
857 c589b249 Ronnie Sahlberg
858 e829b0bb Peter Lieven
    inq = scsi_datain_unmarshall(task);
859 e829b0bb Peter Lieven
    if (inq == NULL) {
860 e829b0bb Peter Lieven
        error_report("iSCSI: Failed to unmarshall inquiry data.");
861 c589b249 Ronnie Sahlberg
        ret = -EINVAL;
862 b93c94f7 Paolo Bonzini
        goto out;
863 c589b249 Ronnie Sahlberg
    }
864 622695a4 Ronnie Sahlberg
865 e829b0bb Peter Lieven
    iscsilun->type = inq->periperal_device_type;
866 e829b0bb Peter Lieven
867 e829b0bb Peter Lieven
    scsi_free_scsi_task(task);
868 e829b0bb Peter Lieven
869 e829b0bb Peter Lieven
    switch (iscsilun->type) {
870 e829b0bb Peter Lieven
    case TYPE_DISK:
871 e829b0bb Peter Lieven
        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
872 e829b0bb Peter Lieven
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
873 e829b0bb Peter Lieven
            error_report("iSCSI: failed to send readcapacity16 command.");
874 e829b0bb Peter Lieven
            ret = -EINVAL;
875 e829b0bb Peter Lieven
            goto out;
876 e829b0bb Peter Lieven
        }
877 e829b0bb Peter Lieven
        rc16 = scsi_datain_unmarshall(task);
878 e829b0bb Peter Lieven
        if (rc16 == NULL) {
879 e829b0bb Peter Lieven
            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
880 e829b0bb Peter Lieven
            ret = -EINVAL;
881 e829b0bb Peter Lieven
            goto out;
882 e829b0bb Peter Lieven
        }
883 e829b0bb Peter Lieven
        iscsilun->block_size = rc16->block_length;
884 e829b0bb Peter Lieven
        iscsilun->num_blocks = rc16->returned_lba + 1;
885 e829b0bb Peter Lieven
        break;
886 e829b0bb Peter Lieven
    case TYPE_ROM:
887 e829b0bb Peter Lieven
        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
888 e829b0bb Peter Lieven
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
889 e829b0bb Peter Lieven
            error_report("iSCSI: failed to send readcapacity10 command.");
890 e829b0bb Peter Lieven
            ret = -EINVAL;
891 e829b0bb Peter Lieven
            goto out;
892 e829b0bb Peter Lieven
        }
893 e829b0bb Peter Lieven
        rc10 = scsi_datain_unmarshall(task);
894 e829b0bb Peter Lieven
        if (rc10 == NULL) {
895 e829b0bb Peter Lieven
            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
896 e829b0bb Peter Lieven
            ret = -EINVAL;
897 e829b0bb Peter Lieven
            goto out;
898 e829b0bb Peter Lieven
        }
899 e829b0bb Peter Lieven
        iscsilun->block_size = rc10->block_size;
900 e829b0bb Peter Lieven
        if (rc10->lba == 0) {
901 e829b0bb Peter Lieven
            /* blank disk loaded */
902 e829b0bb Peter Lieven
            iscsilun->num_blocks = 0;
903 e829b0bb Peter Lieven
        } else {
904 e829b0bb Peter Lieven
            iscsilun->num_blocks = rc10->lba + 1;
905 e829b0bb Peter Lieven
        }
906 e829b0bb Peter Lieven
        break;
907 e829b0bb Peter Lieven
    default:
908 e829b0bb Peter Lieven
        break;
909 e829b0bb Peter Lieven
    }
910 e829b0bb Peter Lieven
911 e829b0bb Peter Lieven
    bs->total_sectors    = iscsilun->num_blocks *
912 e829b0bb Peter Lieven
                           iscsilun->block_size / BDRV_SECTOR_SIZE ;
913 e829b0bb Peter Lieven
914 622695a4 Ronnie Sahlberg
    /* Medium changer or tape. We dont have any emulation for this so this must
915 622695a4 Ronnie Sahlberg
     * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
916 622695a4 Ronnie Sahlberg
     * to read from the device to guess the image format.
917 622695a4 Ronnie Sahlberg
     */
918 622695a4 Ronnie Sahlberg
    if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
919 622695a4 Ronnie Sahlberg
        iscsilun->type == TYPE_TAPE) {
920 622695a4 Ronnie Sahlberg
        bs->sg = 1;
921 622695a4 Ronnie Sahlberg
    }
922 622695a4 Ronnie Sahlberg
923 b93c94f7 Paolo Bonzini
    ret = 0;
924 c589b249 Ronnie Sahlberg
925 b93c94f7 Paolo Bonzini
out:
926 f9dadc98 Ronnie Sahlberg
    if (initiator_name != NULL) {
927 f9dadc98 Ronnie Sahlberg
        g_free(initiator_name);
928 f9dadc98 Ronnie Sahlberg
    }
929 c589b249 Ronnie Sahlberg
    if (iscsi_url != NULL) {
930 c589b249 Ronnie Sahlberg
        iscsi_destroy_url(iscsi_url);
931 c589b249 Ronnie Sahlberg
    }
932 e829b0bb Peter Lieven
    if (task != NULL) {
933 e829b0bb Peter Lieven
        scsi_free_scsi_task(task);
934 e829b0bb Peter Lieven
    }
935 b93c94f7 Paolo Bonzini
936 b93c94f7 Paolo Bonzini
    if (ret) {
937 b93c94f7 Paolo Bonzini
        if (iscsi != NULL) {
938 b93c94f7 Paolo Bonzini
            iscsi_destroy_context(iscsi);
939 b93c94f7 Paolo Bonzini
        }
940 b93c94f7 Paolo Bonzini
        memset(iscsilun, 0, sizeof(IscsiLun));
941 c589b249 Ronnie Sahlberg
    }
942 c589b249 Ronnie Sahlberg
    return ret;
943 c589b249 Ronnie Sahlberg
}
944 c589b249 Ronnie Sahlberg
945 c589b249 Ronnie Sahlberg
static void iscsi_close(BlockDriverState *bs)
946 c589b249 Ronnie Sahlberg
{
947 c589b249 Ronnie Sahlberg
    IscsiLun *iscsilun = bs->opaque;
948 c589b249 Ronnie Sahlberg
    struct iscsi_context *iscsi = iscsilun->iscsi;
949 c589b249 Ronnie Sahlberg
950 bafbd6a1 Paolo Bonzini
    qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
951 c589b249 Ronnie Sahlberg
    iscsi_destroy_context(iscsi);
952 c589b249 Ronnie Sahlberg
    memset(iscsilun, 0, sizeof(IscsiLun));
953 c589b249 Ronnie Sahlberg
}
954 c589b249 Ronnie Sahlberg
955 f807ecd5 Peter Lieven
static int iscsi_has_zero_init(BlockDriverState *bs)
956 f807ecd5 Peter Lieven
{
957 f807ecd5 Peter Lieven
    return 0;
958 f807ecd5 Peter Lieven
}
959 f807ecd5 Peter Lieven
960 c589b249 Ronnie Sahlberg
static BlockDriver bdrv_iscsi = {
961 c589b249 Ronnie Sahlberg
    .format_name     = "iscsi",
962 c589b249 Ronnie Sahlberg
    .protocol_name   = "iscsi",
963 c589b249 Ronnie Sahlberg
964 c589b249 Ronnie Sahlberg
    .instance_size   = sizeof(IscsiLun),
965 c589b249 Ronnie Sahlberg
    .bdrv_file_open  = iscsi_open,
966 c589b249 Ronnie Sahlberg
    .bdrv_close      = iscsi_close,
967 c589b249 Ronnie Sahlberg
968 c589b249 Ronnie Sahlberg
    .bdrv_getlength  = iscsi_getlength,
969 c589b249 Ronnie Sahlberg
970 c589b249 Ronnie Sahlberg
    .bdrv_aio_readv  = iscsi_aio_readv,
971 c589b249 Ronnie Sahlberg
    .bdrv_aio_writev = iscsi_aio_writev,
972 c589b249 Ronnie Sahlberg
    .bdrv_aio_flush  = iscsi_aio_flush,
973 fa6acb0c Ronnie Sahlberg
974 fa6acb0c Ronnie Sahlberg
    .bdrv_aio_discard = iscsi_aio_discard,
975 f807ecd5 Peter Lieven
    .bdrv_has_zero_init = iscsi_has_zero_init,
976 98392453 Ronnie Sahlberg
977 98392453 Ronnie Sahlberg
#ifdef __linux__
978 98392453 Ronnie Sahlberg
    .bdrv_ioctl       = iscsi_ioctl,
979 98392453 Ronnie Sahlberg
    .bdrv_aio_ioctl   = iscsi_aio_ioctl,
980 98392453 Ronnie Sahlberg
#endif
981 c589b249 Ronnie Sahlberg
};
982 c589b249 Ronnie Sahlberg
983 c589b249 Ronnie Sahlberg
static void iscsi_block_init(void)
984 c589b249 Ronnie Sahlberg
{
985 c589b249 Ronnie Sahlberg
    bdrv_register(&bdrv_iscsi);
986 c589b249 Ronnie Sahlberg
}
987 c589b249 Ronnie Sahlberg
988 c589b249 Ronnie Sahlberg
block_init(iscsi_block_init);