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