1 #include "kvm/disk-image.h"
2 #include "kvm/qcow.h"
3 #include "kvm/virtio-blk.h"
4 #include "kvm/kvm.h"
5 #include "kvm/iovec.h"
6
7 #include <linux/err.h>
8 #include <poll.h>
9
10 int debug_iodelay;
11
12 static int disk_image__close(struct disk_image *disk);
13
disk_img_name_parser(const struct option * opt,const char * arg,int unset)14 int disk_img_name_parser(const struct option *opt, const char *arg, int unset)
15 {
16 const char *cur;
17 char *sep;
18 struct kvm *kvm = opt->ptr;
19
20 if (kvm->nr_disks >= MAX_DISK_IMAGES)
21 die("Currently only 4 images are supported");
22
23 kvm->cfg.disk_image[kvm->nr_disks].filename = arg;
24 cur = arg;
25
26 if (strncmp(arg, "scsi:", 5) == 0) {
27 sep = strstr(arg, ":");
28 kvm->cfg.disk_image[kvm->nr_disks].wwpn = sep + 1;
29
30 /* Old invocation had two parameters. Ignore the second one. */
31 sep = strstr(sep + 1, ":");
32 if (sep) {
33 *sep = 0;
34 cur = sep + 1;
35 }
36 }
37
38 do {
39 sep = strstr(cur, ",");
40 if (sep) {
41 if (strncmp(sep + 1, "ro", 2) == 0)
42 kvm->cfg.disk_image[kvm->nr_disks].readonly = true;
43 else if (strncmp(sep + 1, "direct", 6) == 0)
44 kvm->cfg.disk_image[kvm->nr_disks].direct = true;
45 *sep = 0;
46 cur = sep + 1;
47 }
48 } while (sep);
49
50 kvm->nr_disks++;
51
52 return 0;
53 }
54
disk_image__new(int fd,u64 size,struct disk_image_operations * ops,int use_mmap)55 struct disk_image *disk_image__new(int fd, u64 size,
56 struct disk_image_operations *ops,
57 int use_mmap)
58 {
59 struct disk_image *disk;
60 int r;
61
62 disk = malloc(sizeof *disk);
63 if (!disk)
64 return ERR_PTR(-ENOMEM);
65
66 *disk = (struct disk_image) {
67 .fd = fd,
68 .size = size,
69 .ops = ops,
70 };
71
72 if (use_mmap == DISK_IMAGE_MMAP) {
73 /*
74 * The write to disk image will be discarded
75 */
76 disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
77 if (disk->priv == MAP_FAILED) {
78 r = -errno;
79 goto err_free_disk;
80 }
81 }
82
83 r = disk_aio_setup(disk);
84 if (r)
85 goto err_unmap_disk;
86
87 return disk;
88
89 err_unmap_disk:
90 if (disk->priv)
91 munmap(disk->priv, size);
92 err_free_disk:
93 free(disk);
94 return ERR_PTR(r);
95 }
96
disk_image__open(const char * filename,bool readonly,bool direct)97 static struct disk_image *disk_image__open(const char *filename, bool readonly, bool direct)
98 {
99 struct disk_image *disk;
100 struct stat st;
101 int fd, flags;
102
103 if (readonly)
104 flags = O_RDONLY;
105 else
106 flags = O_RDWR;
107 if (direct)
108 flags |= O_DIRECT;
109
110 if (stat(filename, &st) < 0)
111 return ERR_PTR(-errno);
112
113 /* blk device ?*/
114 disk = blkdev__probe(filename, flags, &st);
115 if (!IS_ERR_OR_NULL(disk)) {
116 disk->readonly = readonly;
117 return disk;
118 }
119
120 fd = open(filename, flags);
121 if (fd < 0)
122 return ERR_PTR(fd);
123
124 /* qcow image ?*/
125 disk = qcow_probe(fd, true);
126 if (!IS_ERR_OR_NULL(disk)) {
127 pr_warning("Forcing read-only support for QCOW");
128 disk->readonly = true;
129 return disk;
130 }
131
132 /* raw image ?*/
133 disk = raw_image__probe(fd, &st, readonly);
134 if (!IS_ERR_OR_NULL(disk)) {
135 disk->readonly = readonly;
136 return disk;
137 }
138
139 if (close(fd) < 0)
140 pr_warning("close() failed");
141
142 return ERR_PTR(-ENOSYS);
143 }
144
disk_image__open_all(struct kvm * kvm)145 static struct disk_image **disk_image__open_all(struct kvm *kvm)
146 {
147 struct disk_image **disks;
148 const char *filename;
149 const char *wwpn;
150 bool readonly;
151 bool direct;
152 void *err;
153 int i;
154 struct disk_image_params *params = (struct disk_image_params *)&kvm->cfg.disk_image;
155 int count = kvm->nr_disks;
156
157 if (!count)
158 return ERR_PTR(-EINVAL);
159 if (count > MAX_DISK_IMAGES)
160 return ERR_PTR(-ENOSPC);
161
162 disks = calloc(count, sizeof(*disks));
163 if (!disks)
164 return ERR_PTR(-ENOMEM);
165
166 for (i = 0; i < count; i++) {
167 filename = params[i].filename;
168 readonly = params[i].readonly;
169 direct = params[i].direct;
170 wwpn = params[i].wwpn;
171
172 if (wwpn) {
173 disks[i] = malloc(sizeof(struct disk_image));
174 if (!disks[i]) {
175 err = ERR_PTR(-ENOMEM);
176 goto error;
177 }
178 disks[i]->wwpn = wwpn;
179 continue;
180 }
181
182 if (!filename)
183 continue;
184
185 disks[i] = disk_image__open(filename, readonly, direct);
186 if (IS_ERR_OR_NULL(disks[i])) {
187 pr_err("Loading disk image '%s' failed", filename);
188 err = disks[i];
189 goto error;
190 }
191 disks[i]->debug_iodelay = kvm->cfg.debug_iodelay;
192 }
193
194 return disks;
195 error:
196 for (i = 0; i < count; i++) {
197 if (IS_ERR_OR_NULL(disks[i]))
198 continue;
199
200 if (disks[i]->wwpn)
201 free(disks[i]);
202 else
203 disk_image__close(disks[i]);
204 }
205 free(disks);
206 return err;
207 }
208
disk_image__wait(struct disk_image * disk)209 int disk_image__wait(struct disk_image *disk)
210 {
211 if (disk->ops->wait)
212 return disk->ops->wait(disk);
213
214 return 0;
215 }
216
disk_image__flush(struct disk_image * disk)217 int disk_image__flush(struct disk_image *disk)
218 {
219 if (disk->ops->flush)
220 return disk->ops->flush(disk);
221
222 return fsync(disk->fd);
223 }
224
disk_image__close(struct disk_image * disk)225 static int disk_image__close(struct disk_image *disk)
226 {
227 /* If there was no disk image then there's nothing to do: */
228 if (!disk)
229 return 0;
230
231 disk_aio_destroy(disk);
232
233 if (disk->ops && disk->ops->close)
234 return disk->ops->close(disk);
235
236 if (disk->fd && close(disk->fd) < 0)
237 pr_warning("close() failed");
238
239 free(disk);
240
241 return 0;
242 }
243
disk_image__close_all(struct disk_image ** disks,int count)244 static int disk_image__close_all(struct disk_image **disks, int count)
245 {
246 while (count)
247 disk_image__close(disks[--count]);
248
249 free(disks);
250
251 return 0;
252 }
253
254 /*
255 * Fill iov with disk data, starting from sector 'sector'.
256 * Return amount of bytes read.
257 */
disk_image__read(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)258 ssize_t disk_image__read(struct disk_image *disk, u64 sector,
259 const struct iovec *iov, int iovcount, void *param)
260 {
261 ssize_t total = 0;
262
263 if (debug_iodelay)
264 msleep(debug_iodelay);
265
266 if (disk->ops->read) {
267 total = disk->ops->read(disk, sector, iov, iovcount, param);
268 if (total < 0) {
269 pr_info("disk_image__read error: total=%ld\n", (long)total);
270 return total;
271 }
272 }
273
274 if (!disk->async && disk->disk_req_cb)
275 disk->disk_req_cb(param, total);
276
277 return total;
278 }
279
280 /*
281 * Write iov to disk, starting from sector 'sector'.
282 * Return amount of bytes written.
283 */
disk_image__write(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)284 ssize_t disk_image__write(struct disk_image *disk, u64 sector,
285 const struct iovec *iov, int iovcount, void *param)
286 {
287 ssize_t total = 0;
288
289 if (debug_iodelay)
290 msleep(debug_iodelay);
291
292 if (disk->ops->write) {
293 /*
294 * Try writev based operation first
295 */
296
297 total = disk->ops->write(disk, sector, iov, iovcount, param);
298 if (total < 0) {
299 pr_info("disk_image__write error: total=%ld\n", (long)total);
300 return total;
301 }
302 } else {
303 /* Do nothing */
304 }
305
306 if (!disk->async && disk->disk_req_cb)
307 disk->disk_req_cb(param, total);
308
309 return total;
310 }
311
disk_image__get_serial(struct disk_image * disk,struct iovec * iov,int iovcount,ssize_t len)312 ssize_t disk_image__get_serial(struct disk_image *disk, struct iovec *iov,
313 int iovcount, ssize_t len)
314 {
315 struct stat st;
316 void *buf;
317 int r;
318
319 r = fstat(disk->fd, &st);
320 if (r)
321 return r;
322
323 buf = malloc(len);
324 if (!buf)
325 return -ENOMEM;
326
327 len = snprintf(buf, len, "%llu%llu%llu",
328 (unsigned long long)st.st_dev,
329 (unsigned long long)st.st_rdev,
330 (unsigned long long)st.st_ino);
331 if (len < 0 || (size_t)len > iov_size(iov, iovcount)) {
332 free(buf);
333 return -ENOMEM;
334 }
335
336 memcpy_toiovec(iov, buf, len);
337 free(buf);
338 return len;
339 }
340
disk_image__set_callback(struct disk_image * disk,void (* disk_req_cb)(void * param,long len))341 void disk_image__set_callback(struct disk_image *disk,
342 void (*disk_req_cb)(void *param, long len))
343 {
344 disk->disk_req_cb = disk_req_cb;
345 }
346
disk_image__init(struct kvm * kvm)347 int disk_image__init(struct kvm *kvm)
348 {
349 if (kvm->nr_disks) {
350 kvm->disks = disk_image__open_all(kvm);
351 if (IS_ERR(kvm->disks))
352 return PTR_ERR(kvm->disks);
353 }
354
355 return 0;
356 }
357 dev_base_init(disk_image__init);
358
disk_image__exit(struct kvm * kvm)359 int disk_image__exit(struct kvm *kvm)
360 {
361 return disk_image__close_all(kvm->disks, kvm->nr_disks);
362 }
363 dev_base_exit(disk_image__exit);
364