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