xref: /kvmtool/disk/core.c (revision 145a86fedfe8321e857e1370a42b2a24b0bcda2c)
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 
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 
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 
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 
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 				return ERR_PTR(-ENOMEM);
176 			disks[i]->wwpn = wwpn;
177 			continue;
178 		}
179 
180 		if (!filename)
181 			continue;
182 
183 		disks[i] = disk_image__open(filename, readonly, direct);
184 		if (IS_ERR_OR_NULL(disks[i])) {
185 			pr_err("Loading disk image '%s' failed", filename);
186 			err = disks[i];
187 			goto error;
188 		}
189 		disks[i]->debug_iodelay = kvm->cfg.debug_iodelay;
190 	}
191 
192 	return disks;
193 error:
194 	for (i = 0; i < count; i++)
195 		if (!IS_ERR_OR_NULL(disks[i]))
196 			disk_image__close(disks[i]);
197 
198 	free(disks);
199 	return err;
200 }
201 
202 int disk_image__wait(struct disk_image *disk)
203 {
204 	if (disk->ops->wait)
205 		return disk->ops->wait(disk);
206 
207 	return 0;
208 }
209 
210 int disk_image__flush(struct disk_image *disk)
211 {
212 	if (disk->ops->flush)
213 		return disk->ops->flush(disk);
214 
215 	return fsync(disk->fd);
216 }
217 
218 static int disk_image__close(struct disk_image *disk)
219 {
220 	/* If there was no disk image then there's nothing to do: */
221 	if (!disk)
222 		return 0;
223 
224 	disk_aio_destroy(disk);
225 
226 	if (disk->ops->close)
227 		return disk->ops->close(disk);
228 
229 	if (close(disk->fd) < 0)
230 		pr_warning("close() failed");
231 
232 	free(disk);
233 
234 	return 0;
235 }
236 
237 static int disk_image__close_all(struct disk_image **disks, int count)
238 {
239 	while (count)
240 		disk_image__close(disks[--count]);
241 
242 	free(disks);
243 
244 	return 0;
245 }
246 
247 /*
248  * Fill iov with disk data, starting from sector 'sector'.
249  * Return amount of bytes read.
250  */
251 ssize_t disk_image__read(struct disk_image *disk, u64 sector,
252 			 const struct iovec *iov, int iovcount, void *param)
253 {
254 	ssize_t total = 0;
255 
256 	if (debug_iodelay)
257 		msleep(debug_iodelay);
258 
259 	if (disk->ops->read) {
260 		total = disk->ops->read(disk, sector, iov, iovcount, param);
261 		if (total < 0) {
262 			pr_info("disk_image__read error: total=%ld\n", (long)total);
263 			return total;
264 		}
265 	}
266 
267 	if (!disk->async && disk->disk_req_cb)
268 		disk->disk_req_cb(param, total);
269 
270 	return total;
271 }
272 
273 /*
274  * Write iov to disk, starting from sector 'sector'.
275  * Return amount of bytes written.
276  */
277 ssize_t disk_image__write(struct disk_image *disk, u64 sector,
278 			  const struct iovec *iov, int iovcount, void *param)
279 {
280 	ssize_t total = 0;
281 
282 	if (debug_iodelay)
283 		msleep(debug_iodelay);
284 
285 	if (disk->ops->write) {
286 		/*
287 		 * Try writev based operation first
288 		 */
289 
290 		total = disk->ops->write(disk, sector, iov, iovcount, param);
291 		if (total < 0) {
292 			pr_info("disk_image__write error: total=%ld\n", (long)total);
293 			return total;
294 		}
295 	} else {
296 		/* Do nothing */
297 	}
298 
299 	if (!disk->async && disk->disk_req_cb)
300 		disk->disk_req_cb(param, total);
301 
302 	return total;
303 }
304 
305 ssize_t disk_image__get_serial(struct disk_image *disk, struct iovec *iov,
306 			       int iovcount, ssize_t len)
307 {
308 	struct stat st;
309 	void *buf;
310 	int r;
311 
312 	r = fstat(disk->fd, &st);
313 	if (r)
314 		return r;
315 
316 	buf = malloc(len);
317 	if (!buf)
318 		return -ENOMEM;
319 
320 	len = snprintf(buf, len, "%llu%llu%llu",
321 		       (unsigned long long)st.st_dev,
322 		       (unsigned long long)st.st_rdev,
323 		       (unsigned long long)st.st_ino);
324 	if (len < 0 || (size_t)len > iov_size(iov, iovcount)) {
325 		free(buf);
326 		return -ENOMEM;
327 	}
328 
329 	memcpy_toiovec(iov, buf, len);
330 	free(buf);
331 	return len;
332 }
333 
334 void disk_image__set_callback(struct disk_image *disk,
335 			      void (*disk_req_cb)(void *param, long len))
336 {
337 	disk->disk_req_cb = disk_req_cb;
338 }
339 
340 int disk_image__init(struct kvm *kvm)
341 {
342 	if (kvm->nr_disks) {
343 		kvm->disks = disk_image__open_all(kvm);
344 		if (IS_ERR(kvm->disks))
345 			return PTR_ERR(kvm->disks);
346 	}
347 
348 	return 0;
349 }
350 dev_base_init(disk_image__init);
351 
352 int disk_image__exit(struct kvm *kvm)
353 {
354 	return disk_image__close_all(kvm->disks, kvm->nr_disks);
355 }
356 dev_base_exit(disk_image__exit);
357