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