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