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