xref: /kvmtool/disk/core.c (revision a4d8c55eb29a7344befcec02a7834c7cbeedcaa1)
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 <sys/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 	if (disk) {
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 		return disk;
144 
145 	fd = open(filename, flags);
146 	if (fd < 0)
147 		return ERR_PTR(fd);
148 
149 	/* qcow image ?*/
150 	disk = qcow_probe(fd, true);
151 	if (!IS_ERR_OR_NULL(disk)) {
152 		pr_warning("Forcing read-only support for QCOW");
153 		return disk;
154 	}
155 
156 	/* raw image ?*/
157 	disk = raw_image__probe(fd, &st, readonly);
158 	if (!IS_ERR_OR_NULL(disk))
159 		return disk;
160 
161 	if (close(fd) < 0)
162 		pr_warning("close() failed");
163 
164 	return ERR_PTR(-ENOSYS);
165 }
166 
167 static struct disk_image **disk_image__open_all(struct kvm *kvm)
168 {
169 	struct disk_image **disks;
170 	const char *filename;
171 	const char *wwpn;
172 	const char *tpgt;
173 	bool readonly;
174 	bool direct;
175 	void *err;
176 	int i;
177 	struct disk_image_params *params = (struct disk_image_params *)&kvm->cfg.disk_image;
178 	int count = kvm->cfg.image_count;
179 
180 	if (!count)
181 		return ERR_PTR(-EINVAL);
182 	if (count > MAX_DISK_IMAGES)
183 		return ERR_PTR(-ENOSPC);
184 
185 	disks = calloc(count, sizeof(*disks));
186 	if (!disks)
187 		return ERR_PTR(-ENOMEM);
188 
189 	for (i = 0; i < count; i++) {
190 		filename = params[i].filename;
191 		readonly = params[i].readonly;
192 		direct = params[i].direct;
193 		wwpn = params[i].wwpn;
194 		tpgt = params[i].tpgt;
195 
196 		if (wwpn) {
197 			disks[i] = malloc(sizeof(struct disk_image));
198 			if (!disks[i])
199 				return ERR_PTR(-ENOMEM);
200 			disks[i]->wwpn = wwpn;
201 			disks[i]->tpgt = tpgt;
202 			continue;
203 		}
204 
205 		if (!filename)
206 			continue;
207 
208 		disks[i] = disk_image__open(filename, readonly, direct);
209 		if (IS_ERR_OR_NULL(disks[i])) {
210 			pr_err("Loading disk image '%s' failed", filename);
211 			err = disks[i];
212 			goto error;
213 		}
214 		disks[i]->debug_iodelay = kvm->cfg.debug_iodelay;
215 	}
216 
217 	return disks;
218 error:
219 	for (i = 0; i < count; i++)
220 		if (!IS_ERR_OR_NULL(disks[i]))
221 			disk_image__close(disks[i]);
222 
223 	free(disks);
224 	return err;
225 }
226 
227 int disk_image__flush(struct disk_image *disk)
228 {
229 	if (disk->ops->flush)
230 		return disk->ops->flush(disk);
231 
232 	return fsync(disk->fd);
233 }
234 
235 static int disk_image__close(struct disk_image *disk)
236 {
237 	/* If there was no disk image then there's nothing to do: */
238 	if (!disk)
239 		return 0;
240 
241 	if (disk->ops->close)
242 		return disk->ops->close(disk);
243 
244 	if (close(disk->fd) < 0)
245 		pr_warning("close() failed");
246 
247 	free(disk);
248 
249 	return 0;
250 }
251 
252 static int disk_image__close_all(struct disk_image **disks, int count)
253 {
254 	while (count)
255 		disk_image__close(disks[--count]);
256 
257 	free(disks);
258 
259 	return 0;
260 }
261 
262 /*
263  * Fill iov with disk data, starting from sector 'sector'.
264  * Return amount of bytes read.
265  */
266 ssize_t disk_image__read(struct disk_image *disk, u64 sector,
267 			 const struct iovec *iov, int iovcount, void *param)
268 {
269 	ssize_t total = 0;
270 
271 	if (debug_iodelay)
272 		msleep(debug_iodelay);
273 
274 	if (disk->ops->read) {
275 		total = disk->ops->read(disk, sector, iov, iovcount, param);
276 		if (total < 0) {
277 			pr_info("disk_image__read error: total=%ld\n", (long)total);
278 			return total;
279 		}
280 	}
281 
282 	if (!disk->async && disk->disk_req_cb)
283 		disk->disk_req_cb(param, total);
284 
285 	return total;
286 }
287 
288 /*
289  * Write iov to disk, starting from sector 'sector'.
290  * Return amount of bytes written.
291  */
292 ssize_t disk_image__write(struct disk_image *disk, u64 sector,
293 			  const struct iovec *iov, int iovcount, void *param)
294 {
295 	ssize_t total = 0;
296 
297 	if (debug_iodelay)
298 		msleep(debug_iodelay);
299 
300 	if (disk->ops->write) {
301 		/*
302 		 * Try writev based operation first
303 		 */
304 
305 		total = disk->ops->write(disk, sector, iov, iovcount, param);
306 		if (total < 0) {
307 			pr_info("disk_image__write error: total=%ld\n", (long)total);
308 			return total;
309 		}
310 	} else {
311 		/* Do nothing */
312 	}
313 
314 	if (!disk->async && disk->disk_req_cb)
315 		disk->disk_req_cb(param, total);
316 
317 	return total;
318 }
319 
320 ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len)
321 {
322 	struct stat st;
323 	int r;
324 
325 	r = fstat(disk->fd, &st);
326 	if (r)
327 		return r;
328 
329 	*len = snprintf(buffer, *len, "%llu%llu%llu",
330 			(u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino);
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->cfg.image_count) {
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