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