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