root / block / iscsi.c @ 1b1ed8dc
History | View | Annotate | Download (27 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 | 4d454574 | Paolo Bonzini | static QemuOptsList qemu_iscsi_opts = {
|
984 | 4d454574 | Paolo Bonzini | .name = "iscsi",
|
985 | 4d454574 | Paolo Bonzini | .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head), |
986 | 4d454574 | Paolo Bonzini | .desc = { |
987 | 4d454574 | Paolo Bonzini | { |
988 | 4d454574 | Paolo Bonzini | .name = "user",
|
989 | 4d454574 | Paolo Bonzini | .type = QEMU_OPT_STRING, |
990 | 4d454574 | Paolo Bonzini | .help = "username for CHAP authentication to target",
|
991 | 4d454574 | Paolo Bonzini | },{ |
992 | 4d454574 | Paolo Bonzini | .name = "password",
|
993 | 4d454574 | Paolo Bonzini | .type = QEMU_OPT_STRING, |
994 | 4d454574 | Paolo Bonzini | .help = "password for CHAP authentication to target",
|
995 | 4d454574 | Paolo Bonzini | },{ |
996 | 4d454574 | Paolo Bonzini | .name = "header-digest",
|
997 | 4d454574 | Paolo Bonzini | .type = QEMU_OPT_STRING, |
998 | 4d454574 | Paolo Bonzini | .help = "HeaderDigest setting. "
|
999 | 4d454574 | Paolo Bonzini | "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
|
1000 | 4d454574 | Paolo Bonzini | },{ |
1001 | 4d454574 | Paolo Bonzini | .name = "initiator-name",
|
1002 | 4d454574 | Paolo Bonzini | .type = QEMU_OPT_STRING, |
1003 | 4d454574 | Paolo Bonzini | .help = "Initiator iqn name to use when connecting",
|
1004 | 4d454574 | Paolo Bonzini | }, |
1005 | 4d454574 | Paolo Bonzini | { /* end of list */ }
|
1006 | 4d454574 | Paolo Bonzini | }, |
1007 | 4d454574 | Paolo Bonzini | }; |
1008 | 4d454574 | Paolo Bonzini | |
1009 | c589b249 | Ronnie Sahlberg | static void iscsi_block_init(void) |
1010 | c589b249 | Ronnie Sahlberg | { |
1011 | c589b249 | Ronnie Sahlberg | bdrv_register(&bdrv_iscsi); |
1012 | 4d454574 | Paolo Bonzini | qemu_add_opts(&qemu_iscsi_opts); |
1013 | c589b249 | Ronnie Sahlberg | } |
1014 | c589b249 | Ronnie Sahlberg | |
1015 | c589b249 | Ronnie Sahlberg | block_init(iscsi_block_init); |