root / blockdev.c @ 528f7663
History | View | Annotate | Download (16 kB)
1 | 666daa68 | Markus Armbruster | /*
|
---|---|---|---|
2 | 666daa68 | Markus Armbruster | * QEMU host block devices
|
3 | 666daa68 | Markus Armbruster | *
|
4 | 666daa68 | Markus Armbruster | * Copyright (c) 2003-2008 Fabrice Bellard
|
5 | 666daa68 | Markus Armbruster | *
|
6 | 666daa68 | Markus Armbruster | * This work is licensed under the terms of the GNU GPL, version 2 or
|
7 | 666daa68 | Markus Armbruster | * later. See the COPYING file in the top-level directory.
|
8 | 666daa68 | Markus Armbruster | */
|
9 | 666daa68 | Markus Armbruster | |
10 | 666daa68 | Markus Armbruster | #include "block.h" |
11 | 666daa68 | Markus Armbruster | #include "blockdev.h" |
12 | 666daa68 | Markus Armbruster | #include "monitor.h" |
13 | 666daa68 | Markus Armbruster | #include "qerror.h" |
14 | 666daa68 | Markus Armbruster | #include "qemu-option.h" |
15 | 666daa68 | Markus Armbruster | #include "qemu-config.h" |
16 | 666daa68 | Markus Armbruster | #include "sysemu.h" |
17 | 666daa68 | Markus Armbruster | |
18 | c9b62a7e | Markus Armbruster | static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
|
19 | 666daa68 | Markus Armbruster | |
20 | 14bafc54 | Markus Armbruster | /*
|
21 | 14bafc54 | Markus Armbruster | * We automatically delete the drive when a device using it gets
|
22 | 14bafc54 | Markus Armbruster | * unplugged. Questionable feature, but we can't just drop it.
|
23 | 14bafc54 | Markus Armbruster | * Device models call blockdev_mark_auto_del() to schedule the
|
24 | 14bafc54 | Markus Armbruster | * automatic deletion, and generic qdev code calls blockdev_auto_del()
|
25 | 14bafc54 | Markus Armbruster | * when deletion is actually safe.
|
26 | 14bafc54 | Markus Armbruster | */
|
27 | 14bafc54 | Markus Armbruster | void blockdev_mark_auto_del(BlockDriverState *bs)
|
28 | 14bafc54 | Markus Armbruster | { |
29 | 14bafc54 | Markus Armbruster | DriveInfo *dinfo = drive_get_by_blockdev(bs); |
30 | 14bafc54 | Markus Armbruster | |
31 | 14bafc54 | Markus Armbruster | dinfo->auto_del = 1;
|
32 | 14bafc54 | Markus Armbruster | } |
33 | 14bafc54 | Markus Armbruster | |
34 | 14bafc54 | Markus Armbruster | void blockdev_auto_del(BlockDriverState *bs)
|
35 | 14bafc54 | Markus Armbruster | { |
36 | 14bafc54 | Markus Armbruster | DriveInfo *dinfo = drive_get_by_blockdev(bs); |
37 | 14bafc54 | Markus Armbruster | |
38 | 14bafc54 | Markus Armbruster | if (dinfo->auto_del) {
|
39 | 14bafc54 | Markus Armbruster | drive_uninit(dinfo); |
40 | 14bafc54 | Markus Armbruster | } |
41 | 14bafc54 | Markus Armbruster | } |
42 | 14bafc54 | Markus Armbruster | |
43 | 666daa68 | Markus Armbruster | QemuOpts *drive_add(const char *file, const char *fmt, ...) |
44 | 666daa68 | Markus Armbruster | { |
45 | 666daa68 | Markus Armbruster | va_list ap; |
46 | 666daa68 | Markus Armbruster | char optstr[1024]; |
47 | 666daa68 | Markus Armbruster | QemuOpts *opts; |
48 | 666daa68 | Markus Armbruster | |
49 | 666daa68 | Markus Armbruster | va_start(ap, fmt); |
50 | 666daa68 | Markus Armbruster | vsnprintf(optstr, sizeof(optstr), fmt, ap);
|
51 | 666daa68 | Markus Armbruster | va_end(ap); |
52 | 666daa68 | Markus Armbruster | |
53 | 666daa68 | Markus Armbruster | opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
|
54 | 666daa68 | Markus Armbruster | if (!opts) {
|
55 | 666daa68 | Markus Armbruster | return NULL; |
56 | 666daa68 | Markus Armbruster | } |
57 | 666daa68 | Markus Armbruster | if (file)
|
58 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "file", file);
|
59 | 666daa68 | Markus Armbruster | return opts;
|
60 | 666daa68 | Markus Armbruster | } |
61 | 666daa68 | Markus Armbruster | |
62 | 666daa68 | Markus Armbruster | DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) |
63 | 666daa68 | Markus Armbruster | { |
64 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
65 | 666daa68 | Markus Armbruster | |
66 | 666daa68 | Markus Armbruster | /* seek interface, bus and unit */
|
67 | 666daa68 | Markus Armbruster | |
68 | 666daa68 | Markus Armbruster | QTAILQ_FOREACH(dinfo, &drives, next) { |
69 | 666daa68 | Markus Armbruster | if (dinfo->type == type &&
|
70 | 666daa68 | Markus Armbruster | dinfo->bus == bus && |
71 | 666daa68 | Markus Armbruster | dinfo->unit == unit) |
72 | 666daa68 | Markus Armbruster | return dinfo;
|
73 | 666daa68 | Markus Armbruster | } |
74 | 666daa68 | Markus Armbruster | |
75 | 666daa68 | Markus Armbruster | return NULL; |
76 | 666daa68 | Markus Armbruster | } |
77 | 666daa68 | Markus Armbruster | |
78 | 666daa68 | Markus Armbruster | int drive_get_max_bus(BlockInterfaceType type)
|
79 | 666daa68 | Markus Armbruster | { |
80 | 666daa68 | Markus Armbruster | int max_bus;
|
81 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
82 | 666daa68 | Markus Armbruster | |
83 | 666daa68 | Markus Armbruster | max_bus = -1;
|
84 | 666daa68 | Markus Armbruster | QTAILQ_FOREACH(dinfo, &drives, next) { |
85 | 666daa68 | Markus Armbruster | if(dinfo->type == type &&
|
86 | 666daa68 | Markus Armbruster | dinfo->bus > max_bus) |
87 | 666daa68 | Markus Armbruster | max_bus = dinfo->bus; |
88 | 666daa68 | Markus Armbruster | } |
89 | 666daa68 | Markus Armbruster | return max_bus;
|
90 | 666daa68 | Markus Armbruster | } |
91 | 666daa68 | Markus Armbruster | |
92 | e4700e59 | Markus Armbruster | DriveInfo *drive_get_by_blockdev(BlockDriverState *bs) |
93 | 666daa68 | Markus Armbruster | { |
94 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
95 | 666daa68 | Markus Armbruster | |
96 | 666daa68 | Markus Armbruster | QTAILQ_FOREACH(dinfo, &drives, next) { |
97 | e4700e59 | Markus Armbruster | if (dinfo->bdrv == bs) {
|
98 | e4700e59 | Markus Armbruster | return dinfo;
|
99 | e4700e59 | Markus Armbruster | } |
100 | 666daa68 | Markus Armbruster | } |
101 | e4700e59 | Markus Armbruster | return NULL; |
102 | 666daa68 | Markus Armbruster | } |
103 | 666daa68 | Markus Armbruster | |
104 | 666daa68 | Markus Armbruster | static void bdrv_format_print(void *opaque, const char *name) |
105 | 666daa68 | Markus Armbruster | { |
106 | 666daa68 | Markus Armbruster | fprintf(stderr, " %s", name);
|
107 | 666daa68 | Markus Armbruster | } |
108 | 666daa68 | Markus Armbruster | |
109 | 666daa68 | Markus Armbruster | void drive_uninit(DriveInfo *dinfo)
|
110 | 666daa68 | Markus Armbruster | { |
111 | 666daa68 | Markus Armbruster | qemu_opts_del(dinfo->opts); |
112 | 666daa68 | Markus Armbruster | bdrv_delete(dinfo->bdrv); |
113 | 666daa68 | Markus Armbruster | QTAILQ_REMOVE(&drives, dinfo, next); |
114 | 666daa68 | Markus Armbruster | qemu_free(dinfo); |
115 | 666daa68 | Markus Armbruster | } |
116 | 666daa68 | Markus Armbruster | |
117 | 666daa68 | Markus Armbruster | static int parse_block_error_action(const char *buf, int is_read) |
118 | 666daa68 | Markus Armbruster | { |
119 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "ignore")) { |
120 | 666daa68 | Markus Armbruster | return BLOCK_ERR_IGNORE;
|
121 | 666daa68 | Markus Armbruster | } else if (!is_read && !strcmp(buf, "enospc")) { |
122 | 666daa68 | Markus Armbruster | return BLOCK_ERR_STOP_ENOSPC;
|
123 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "stop")) { |
124 | 666daa68 | Markus Armbruster | return BLOCK_ERR_STOP_ANY;
|
125 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "report")) { |
126 | 666daa68 | Markus Armbruster | return BLOCK_ERR_REPORT;
|
127 | 666daa68 | Markus Armbruster | } else {
|
128 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid %s error action\n",
|
129 | 666daa68 | Markus Armbruster | buf, is_read ? "read" : "write"); |
130 | 666daa68 | Markus Armbruster | return -1; |
131 | 666daa68 | Markus Armbruster | } |
132 | 666daa68 | Markus Armbruster | } |
133 | 666daa68 | Markus Armbruster | |
134 | 666daa68 | Markus Armbruster | DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) |
135 | 666daa68 | Markus Armbruster | { |
136 | 666daa68 | Markus Armbruster | const char *buf; |
137 | 666daa68 | Markus Armbruster | const char *file = NULL; |
138 | 666daa68 | Markus Armbruster | char devname[128]; |
139 | 666daa68 | Markus Armbruster | const char *serial; |
140 | 666daa68 | Markus Armbruster | const char *mediastr = ""; |
141 | 666daa68 | Markus Armbruster | BlockInterfaceType type; |
142 | 666daa68 | Markus Armbruster | enum { MEDIA_DISK, MEDIA_CDROM } media;
|
143 | 666daa68 | Markus Armbruster | int bus_id, unit_id;
|
144 | 666daa68 | Markus Armbruster | int cyls, heads, secs, translation;
|
145 | 666daa68 | Markus Armbruster | BlockDriver *drv = NULL;
|
146 | 666daa68 | Markus Armbruster | int max_devs;
|
147 | 666daa68 | Markus Armbruster | int index;
|
148 | 666daa68 | Markus Armbruster | int ro = 0; |
149 | 666daa68 | Markus Armbruster | int bdrv_flags = 0; |
150 | 666daa68 | Markus Armbruster | int on_read_error, on_write_error;
|
151 | 666daa68 | Markus Armbruster | const char *devaddr; |
152 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
153 | 666daa68 | Markus Armbruster | int snapshot = 0; |
154 | 666daa68 | Markus Armbruster | int ret;
|
155 | 666daa68 | Markus Armbruster | |
156 | 666daa68 | Markus Armbruster | *fatal_error = 1;
|
157 | 666daa68 | Markus Armbruster | |
158 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_AUTO; |
159 | 666daa68 | Markus Armbruster | |
160 | 666daa68 | Markus Armbruster | if (default_to_scsi) {
|
161 | 666daa68 | Markus Armbruster | type = IF_SCSI; |
162 | 666daa68 | Markus Armbruster | max_devs = MAX_SCSI_DEVS; |
163 | 666daa68 | Markus Armbruster | pstrcpy(devname, sizeof(devname), "scsi"); |
164 | 666daa68 | Markus Armbruster | } else {
|
165 | 666daa68 | Markus Armbruster | type = IF_IDE; |
166 | 666daa68 | Markus Armbruster | max_devs = MAX_IDE_DEVS; |
167 | 666daa68 | Markus Armbruster | pstrcpy(devname, sizeof(devname), "ide"); |
168 | 666daa68 | Markus Armbruster | } |
169 | 666daa68 | Markus Armbruster | media = MEDIA_DISK; |
170 | 666daa68 | Markus Armbruster | |
171 | 666daa68 | Markus Armbruster | /* extract parameters */
|
172 | 666daa68 | Markus Armbruster | bus_id = qemu_opt_get_number(opts, "bus", 0); |
173 | 666daa68 | Markus Armbruster | unit_id = qemu_opt_get_number(opts, "unit", -1); |
174 | 666daa68 | Markus Armbruster | index = qemu_opt_get_number(opts, "index", -1); |
175 | 666daa68 | Markus Armbruster | |
176 | 666daa68 | Markus Armbruster | cyls = qemu_opt_get_number(opts, "cyls", 0); |
177 | 666daa68 | Markus Armbruster | heads = qemu_opt_get_number(opts, "heads", 0); |
178 | 666daa68 | Markus Armbruster | secs = qemu_opt_get_number(opts, "secs", 0); |
179 | 666daa68 | Markus Armbruster | |
180 | 666daa68 | Markus Armbruster | snapshot = qemu_opt_get_bool(opts, "snapshot", 0); |
181 | 666daa68 | Markus Armbruster | ro = qemu_opt_get_bool(opts, "readonly", 0); |
182 | 666daa68 | Markus Armbruster | |
183 | 666daa68 | Markus Armbruster | file = qemu_opt_get(opts, "file");
|
184 | 666daa68 | Markus Armbruster | serial = qemu_opt_get(opts, "serial");
|
185 | 666daa68 | Markus Armbruster | |
186 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "if")) != NULL) { |
187 | 666daa68 | Markus Armbruster | pstrcpy(devname, sizeof(devname), buf);
|
188 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "ide")) { |
189 | 666daa68 | Markus Armbruster | type = IF_IDE; |
190 | 666daa68 | Markus Armbruster | max_devs = MAX_IDE_DEVS; |
191 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "scsi")) { |
192 | 666daa68 | Markus Armbruster | type = IF_SCSI; |
193 | 666daa68 | Markus Armbruster | max_devs = MAX_SCSI_DEVS; |
194 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "floppy")) { |
195 | 666daa68 | Markus Armbruster | type = IF_FLOPPY; |
196 | 666daa68 | Markus Armbruster | max_devs = 0;
|
197 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "pflash")) { |
198 | 666daa68 | Markus Armbruster | type = IF_PFLASH; |
199 | 666daa68 | Markus Armbruster | max_devs = 0;
|
200 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "mtd")) { |
201 | 666daa68 | Markus Armbruster | type = IF_MTD; |
202 | 666daa68 | Markus Armbruster | max_devs = 0;
|
203 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "sd")) { |
204 | 666daa68 | Markus Armbruster | type = IF_SD; |
205 | 666daa68 | Markus Armbruster | max_devs = 0;
|
206 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "virtio")) { |
207 | 666daa68 | Markus Armbruster | type = IF_VIRTIO; |
208 | 666daa68 | Markus Armbruster | max_devs = 0;
|
209 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "xen")) { |
210 | 666daa68 | Markus Armbruster | type = IF_XEN; |
211 | 666daa68 | Markus Armbruster | max_devs = 0;
|
212 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "none")) { |
213 | 666daa68 | Markus Armbruster | type = IF_NONE; |
214 | 666daa68 | Markus Armbruster | max_devs = 0;
|
215 | 666daa68 | Markus Armbruster | } else {
|
216 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
|
217 | 666daa68 | Markus Armbruster | return NULL; |
218 | 666daa68 | Markus Armbruster | } |
219 | 666daa68 | Markus Armbruster | } |
220 | 666daa68 | Markus Armbruster | |
221 | 666daa68 | Markus Armbruster | if (cyls || heads || secs) {
|
222 | 666daa68 | Markus Armbruster | if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { |
223 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
|
224 | 666daa68 | Markus Armbruster | return NULL; |
225 | 666daa68 | Markus Armbruster | } |
226 | 666daa68 | Markus Armbruster | if (heads < 1 || (type == IF_IDE && heads > 16)) { |
227 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
|
228 | 666daa68 | Markus Armbruster | return NULL; |
229 | 666daa68 | Markus Armbruster | } |
230 | 666daa68 | Markus Armbruster | if (secs < 1 || (type == IF_IDE && secs > 63)) { |
231 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
|
232 | 666daa68 | Markus Armbruster | return NULL; |
233 | 666daa68 | Markus Armbruster | } |
234 | 666daa68 | Markus Armbruster | } |
235 | 666daa68 | Markus Armbruster | |
236 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "trans")) != NULL) { |
237 | 666daa68 | Markus Armbruster | if (!cyls) {
|
238 | 666daa68 | Markus Armbruster | fprintf(stderr, |
239 | 666daa68 | Markus Armbruster | "qemu: '%s' trans must be used with cyls,heads and secs\n",
|
240 | 666daa68 | Markus Armbruster | buf); |
241 | 666daa68 | Markus Armbruster | return NULL; |
242 | 666daa68 | Markus Armbruster | } |
243 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "none")) |
244 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_NONE; |
245 | 666daa68 | Markus Armbruster | else if (!strcmp(buf, "lba")) |
246 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_LBA; |
247 | 666daa68 | Markus Armbruster | else if (!strcmp(buf, "auto")) |
248 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_AUTO; |
249 | 666daa68 | Markus Armbruster | else {
|
250 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
|
251 | 666daa68 | Markus Armbruster | return NULL; |
252 | 666daa68 | Markus Armbruster | } |
253 | 666daa68 | Markus Armbruster | } |
254 | 666daa68 | Markus Armbruster | |
255 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "media")) != NULL) { |
256 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "disk")) { |
257 | 666daa68 | Markus Armbruster | media = MEDIA_DISK; |
258 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "cdrom")) { |
259 | 666daa68 | Markus Armbruster | if (cyls || secs || heads) {
|
260 | 666daa68 | Markus Armbruster | fprintf(stderr, |
261 | 666daa68 | Markus Armbruster | "qemu: '%s' invalid physical CHS format\n", buf);
|
262 | 666daa68 | Markus Armbruster | return NULL; |
263 | 666daa68 | Markus Armbruster | } |
264 | 666daa68 | Markus Armbruster | media = MEDIA_CDROM; |
265 | 666daa68 | Markus Armbruster | } else {
|
266 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid media\n", buf);
|
267 | 666daa68 | Markus Armbruster | return NULL; |
268 | 666daa68 | Markus Armbruster | } |
269 | 666daa68 | Markus Armbruster | } |
270 | 666daa68 | Markus Armbruster | |
271 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "cache")) != NULL) { |
272 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "off") || !strcmp(buf, "none")) { |
273 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_NOCACHE; |
274 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "writeback")) { |
275 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_CACHE_WB; |
276 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "unsafe")) { |
277 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_CACHE_WB; |
278 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_NO_FLUSH; |
279 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "writethrough")) { |
280 | 666daa68 | Markus Armbruster | /* this is the default */
|
281 | 666daa68 | Markus Armbruster | } else {
|
282 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: invalid cache option\n");
|
283 | 666daa68 | Markus Armbruster | return NULL; |
284 | 666daa68 | Markus Armbruster | } |
285 | 666daa68 | Markus Armbruster | } |
286 | 666daa68 | Markus Armbruster | |
287 | 666daa68 | Markus Armbruster | #ifdef CONFIG_LINUX_AIO
|
288 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "aio")) != NULL) { |
289 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "native")) { |
290 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_NATIVE_AIO; |
291 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "threads")) { |
292 | 666daa68 | Markus Armbruster | /* this is the default */
|
293 | 666daa68 | Markus Armbruster | } else {
|
294 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: invalid aio option\n");
|
295 | 666daa68 | Markus Armbruster | return NULL; |
296 | 666daa68 | Markus Armbruster | } |
297 | 666daa68 | Markus Armbruster | } |
298 | 666daa68 | Markus Armbruster | #endif
|
299 | 666daa68 | Markus Armbruster | |
300 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "format")) != NULL) { |
301 | 666daa68 | Markus Armbruster | if (strcmp(buf, "?") == 0) { |
302 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: Supported formats:");
|
303 | 666daa68 | Markus Armbruster | bdrv_iterate_format(bdrv_format_print, NULL);
|
304 | 666daa68 | Markus Armbruster | fprintf(stderr, "\n");
|
305 | 666daa68 | Markus Armbruster | return NULL; |
306 | 666daa68 | Markus Armbruster | } |
307 | 666daa68 | Markus Armbruster | drv = bdrv_find_whitelisted_format(buf); |
308 | 666daa68 | Markus Armbruster | if (!drv) {
|
309 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: '%s' invalid format\n", buf);
|
310 | 666daa68 | Markus Armbruster | return NULL; |
311 | 666daa68 | Markus Armbruster | } |
312 | 666daa68 | Markus Armbruster | } |
313 | 666daa68 | Markus Armbruster | |
314 | 666daa68 | Markus Armbruster | on_write_error = BLOCK_ERR_STOP_ENOSPC; |
315 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "werror")) != NULL) { |
316 | 666daa68 | Markus Armbruster | if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
|
317 | 666daa68 | Markus Armbruster | fprintf(stderr, "werror is no supported by this format\n");
|
318 | 666daa68 | Markus Armbruster | return NULL; |
319 | 666daa68 | Markus Armbruster | } |
320 | 666daa68 | Markus Armbruster | |
321 | 666daa68 | Markus Armbruster | on_write_error = parse_block_error_action(buf, 0);
|
322 | 666daa68 | Markus Armbruster | if (on_write_error < 0) { |
323 | 666daa68 | Markus Armbruster | return NULL; |
324 | 666daa68 | Markus Armbruster | } |
325 | 666daa68 | Markus Armbruster | } |
326 | 666daa68 | Markus Armbruster | |
327 | 666daa68 | Markus Armbruster | on_read_error = BLOCK_ERR_REPORT; |
328 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { |
329 | 666daa68 | Markus Armbruster | if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
|
330 | 666daa68 | Markus Armbruster | fprintf(stderr, "rerror is no supported by this format\n");
|
331 | 666daa68 | Markus Armbruster | return NULL; |
332 | 666daa68 | Markus Armbruster | } |
333 | 666daa68 | Markus Armbruster | |
334 | 666daa68 | Markus Armbruster | on_read_error = parse_block_error_action(buf, 1);
|
335 | 666daa68 | Markus Armbruster | if (on_read_error < 0) { |
336 | 666daa68 | Markus Armbruster | return NULL; |
337 | 666daa68 | Markus Armbruster | } |
338 | 666daa68 | Markus Armbruster | } |
339 | 666daa68 | Markus Armbruster | |
340 | 666daa68 | Markus Armbruster | if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { |
341 | 666daa68 | Markus Armbruster | if (type != IF_VIRTIO) {
|
342 | 666daa68 | Markus Armbruster | fprintf(stderr, "addr is not supported\n");
|
343 | 666daa68 | Markus Armbruster | return NULL; |
344 | 666daa68 | Markus Armbruster | } |
345 | 666daa68 | Markus Armbruster | } |
346 | 666daa68 | Markus Armbruster | |
347 | 666daa68 | Markus Armbruster | /* compute bus and unit according index */
|
348 | 666daa68 | Markus Armbruster | |
349 | 666daa68 | Markus Armbruster | if (index != -1) { |
350 | 666daa68 | Markus Armbruster | if (bus_id != 0 || unit_id != -1) { |
351 | 666daa68 | Markus Armbruster | fprintf(stderr, |
352 | 666daa68 | Markus Armbruster | "qemu: index cannot be used with bus and unit\n");
|
353 | 666daa68 | Markus Armbruster | return NULL; |
354 | 666daa68 | Markus Armbruster | } |
355 | 666daa68 | Markus Armbruster | if (max_devs == 0) |
356 | 666daa68 | Markus Armbruster | { |
357 | 666daa68 | Markus Armbruster | unit_id = index; |
358 | 666daa68 | Markus Armbruster | bus_id = 0;
|
359 | 666daa68 | Markus Armbruster | } else {
|
360 | 666daa68 | Markus Armbruster | unit_id = index % max_devs; |
361 | 666daa68 | Markus Armbruster | bus_id = index / max_devs; |
362 | 666daa68 | Markus Armbruster | } |
363 | 666daa68 | Markus Armbruster | } |
364 | 666daa68 | Markus Armbruster | |
365 | 666daa68 | Markus Armbruster | /* if user doesn't specify a unit_id,
|
366 | 666daa68 | Markus Armbruster | * try to find the first free
|
367 | 666daa68 | Markus Armbruster | */
|
368 | 666daa68 | Markus Armbruster | |
369 | 666daa68 | Markus Armbruster | if (unit_id == -1) { |
370 | 666daa68 | Markus Armbruster | unit_id = 0;
|
371 | 666daa68 | Markus Armbruster | while (drive_get(type, bus_id, unit_id) != NULL) { |
372 | 666daa68 | Markus Armbruster | unit_id++; |
373 | 666daa68 | Markus Armbruster | if (max_devs && unit_id >= max_devs) {
|
374 | 666daa68 | Markus Armbruster | unit_id -= max_devs; |
375 | 666daa68 | Markus Armbruster | bus_id++; |
376 | 666daa68 | Markus Armbruster | } |
377 | 666daa68 | Markus Armbruster | } |
378 | 666daa68 | Markus Armbruster | } |
379 | 666daa68 | Markus Armbruster | |
380 | 666daa68 | Markus Armbruster | /* check unit id */
|
381 | 666daa68 | Markus Armbruster | |
382 | 666daa68 | Markus Armbruster | if (max_devs && unit_id >= max_devs) {
|
383 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
|
384 | 666daa68 | Markus Armbruster | unit_id, max_devs - 1);
|
385 | 666daa68 | Markus Armbruster | return NULL; |
386 | 666daa68 | Markus Armbruster | } |
387 | 666daa68 | Markus Armbruster | |
388 | 666daa68 | Markus Armbruster | /*
|
389 | 666daa68 | Markus Armbruster | * ignore multiple definitions
|
390 | 666daa68 | Markus Armbruster | */
|
391 | 666daa68 | Markus Armbruster | |
392 | 666daa68 | Markus Armbruster | if (drive_get(type, bus_id, unit_id) != NULL) { |
393 | 666daa68 | Markus Armbruster | *fatal_error = 0;
|
394 | 666daa68 | Markus Armbruster | return NULL; |
395 | 666daa68 | Markus Armbruster | } |
396 | 666daa68 | Markus Armbruster | |
397 | 666daa68 | Markus Armbruster | /* init */
|
398 | 666daa68 | Markus Armbruster | |
399 | 666daa68 | Markus Armbruster | dinfo = qemu_mallocz(sizeof(*dinfo));
|
400 | 666daa68 | Markus Armbruster | if ((buf = qemu_opts_id(opts)) != NULL) { |
401 | 666daa68 | Markus Armbruster | dinfo->id = qemu_strdup(buf); |
402 | 666daa68 | Markus Armbruster | } else {
|
403 | 666daa68 | Markus Armbruster | /* no id supplied -> create one */
|
404 | 666daa68 | Markus Armbruster | dinfo->id = qemu_mallocz(32);
|
405 | 666daa68 | Markus Armbruster | if (type == IF_IDE || type == IF_SCSI)
|
406 | 666daa68 | Markus Armbruster | mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; |
407 | 666daa68 | Markus Armbruster | if (max_devs)
|
408 | 666daa68 | Markus Armbruster | snprintf(dinfo->id, 32, "%s%i%s%i", |
409 | 666daa68 | Markus Armbruster | devname, bus_id, mediastr, unit_id); |
410 | 666daa68 | Markus Armbruster | else
|
411 | 666daa68 | Markus Armbruster | snprintf(dinfo->id, 32, "%s%s%i", |
412 | 666daa68 | Markus Armbruster | devname, mediastr, unit_id); |
413 | 666daa68 | Markus Armbruster | } |
414 | 666daa68 | Markus Armbruster | dinfo->bdrv = bdrv_new(dinfo->id); |
415 | 666daa68 | Markus Armbruster | dinfo->devaddr = devaddr; |
416 | 666daa68 | Markus Armbruster | dinfo->type = type; |
417 | 666daa68 | Markus Armbruster | dinfo->bus = bus_id; |
418 | 666daa68 | Markus Armbruster | dinfo->unit = unit_id; |
419 | 666daa68 | Markus Armbruster | dinfo->opts = opts; |
420 | 666daa68 | Markus Armbruster | if (serial)
|
421 | 653dbec7 | Luiz Capitulino | strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1); |
422 | 666daa68 | Markus Armbruster | QTAILQ_INSERT_TAIL(&drives, dinfo, next); |
423 | 666daa68 | Markus Armbruster | |
424 | abd7f68d | Markus Armbruster | bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error); |
425 | abd7f68d | Markus Armbruster | |
426 | 666daa68 | Markus Armbruster | switch(type) {
|
427 | 666daa68 | Markus Armbruster | case IF_IDE:
|
428 | 666daa68 | Markus Armbruster | case IF_SCSI:
|
429 | 666daa68 | Markus Armbruster | case IF_XEN:
|
430 | 666daa68 | Markus Armbruster | case IF_NONE:
|
431 | 666daa68 | Markus Armbruster | switch(media) {
|
432 | 666daa68 | Markus Armbruster | case MEDIA_DISK:
|
433 | 666daa68 | Markus Armbruster | if (cyls != 0) { |
434 | 666daa68 | Markus Armbruster | bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); |
435 | 666daa68 | Markus Armbruster | bdrv_set_translation_hint(dinfo->bdrv, translation); |
436 | 666daa68 | Markus Armbruster | } |
437 | 666daa68 | Markus Armbruster | break;
|
438 | 666daa68 | Markus Armbruster | case MEDIA_CDROM:
|
439 | 666daa68 | Markus Armbruster | bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); |
440 | 666daa68 | Markus Armbruster | break;
|
441 | 666daa68 | Markus Armbruster | } |
442 | 666daa68 | Markus Armbruster | break;
|
443 | 666daa68 | Markus Armbruster | case IF_SD:
|
444 | 666daa68 | Markus Armbruster | /* FIXME: This isn't really a floppy, but it's a reasonable
|
445 | 666daa68 | Markus Armbruster | approximation. */
|
446 | 666daa68 | Markus Armbruster | case IF_FLOPPY:
|
447 | 666daa68 | Markus Armbruster | bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); |
448 | 666daa68 | Markus Armbruster | break;
|
449 | 666daa68 | Markus Armbruster | case IF_PFLASH:
|
450 | 666daa68 | Markus Armbruster | case IF_MTD:
|
451 | 666daa68 | Markus Armbruster | break;
|
452 | 666daa68 | Markus Armbruster | case IF_VIRTIO:
|
453 | 666daa68 | Markus Armbruster | /* add virtio block device */
|
454 | 666daa68 | Markus Armbruster | opts = qemu_opts_create(&qemu_device_opts, NULL, 0); |
455 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "driver", "virtio-blk-pci"); |
456 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "drive", dinfo->id);
|
457 | 666daa68 | Markus Armbruster | if (devaddr)
|
458 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "addr", devaddr);
|
459 | 666daa68 | Markus Armbruster | break;
|
460 | 666daa68 | Markus Armbruster | case IF_COUNT:
|
461 | 666daa68 | Markus Armbruster | abort(); |
462 | 666daa68 | Markus Armbruster | } |
463 | dd5b0d71 | Markus Armbruster | if (!file || !*file) {
|
464 | 666daa68 | Markus Armbruster | *fatal_error = 0;
|
465 | 666daa68 | Markus Armbruster | return NULL; |
466 | 666daa68 | Markus Armbruster | } |
467 | 666daa68 | Markus Armbruster | if (snapshot) {
|
468 | 666daa68 | Markus Armbruster | /* always use cache=unsafe with snapshot */
|
469 | 666daa68 | Markus Armbruster | bdrv_flags &= ~BDRV_O_CACHE_MASK; |
470 | 666daa68 | Markus Armbruster | bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); |
471 | 666daa68 | Markus Armbruster | } |
472 | 666daa68 | Markus Armbruster | |
473 | 666daa68 | Markus Armbruster | if (media == MEDIA_CDROM) {
|
474 | 666daa68 | Markus Armbruster | /* CDROM is fine for any interface, don't check. */
|
475 | 666daa68 | Markus Armbruster | ro = 1;
|
476 | 666daa68 | Markus Armbruster | } else if (ro == 1) { |
477 | 666daa68 | Markus Armbruster | if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
|
478 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
|
479 | 666daa68 | Markus Armbruster | return NULL; |
480 | 666daa68 | Markus Armbruster | } |
481 | 666daa68 | Markus Armbruster | } |
482 | 666daa68 | Markus Armbruster | |
483 | 666daa68 | Markus Armbruster | bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
|
484 | 666daa68 | Markus Armbruster | |
485 | 666daa68 | Markus Armbruster | ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); |
486 | 666daa68 | Markus Armbruster | if (ret < 0) { |
487 | 666daa68 | Markus Armbruster | fprintf(stderr, "qemu: could not open disk image %s: %s\n",
|
488 | 666daa68 | Markus Armbruster | file, strerror(-ret)); |
489 | 666daa68 | Markus Armbruster | return NULL; |
490 | 666daa68 | Markus Armbruster | } |
491 | 666daa68 | Markus Armbruster | |
492 | 666daa68 | Markus Armbruster | if (bdrv_key_required(dinfo->bdrv))
|
493 | 666daa68 | Markus Armbruster | autostart = 0;
|
494 | 666daa68 | Markus Armbruster | *fatal_error = 0;
|
495 | 666daa68 | Markus Armbruster | return dinfo;
|
496 | 666daa68 | Markus Armbruster | } |
497 | 666daa68 | Markus Armbruster | |
498 | 666daa68 | Markus Armbruster | void do_commit(Monitor *mon, const QDict *qdict) |
499 | 666daa68 | Markus Armbruster | { |
500 | 666daa68 | Markus Armbruster | const char *device = qdict_get_str(qdict, "device"); |
501 | 6ab4b5ab | Markus Armbruster | BlockDriverState *bs; |
502 | 666daa68 | Markus Armbruster | |
503 | 6ab4b5ab | Markus Armbruster | if (!strcmp(device, "all")) { |
504 | 6ab4b5ab | Markus Armbruster | bdrv_commit_all(); |
505 | 6ab4b5ab | Markus Armbruster | } else {
|
506 | 6ab4b5ab | Markus Armbruster | bs = bdrv_find(device); |
507 | ac59eb95 | Markus Armbruster | if (!bs) {
|
508 | ac59eb95 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, device); |
509 | ac59eb95 | Markus Armbruster | return;
|
510 | 6ab4b5ab | Markus Armbruster | } |
511 | ac59eb95 | Markus Armbruster | bdrv_commit(bs); |
512 | 666daa68 | Markus Armbruster | } |
513 | 666daa68 | Markus Armbruster | } |
514 | 666daa68 | Markus Armbruster | |
515 | 666daa68 | Markus Armbruster | static int eject_device(Monitor *mon, BlockDriverState *bs, int force) |
516 | 666daa68 | Markus Armbruster | { |
517 | 3b5276b5 | Eduardo Habkost | if (!force) {
|
518 | 3b5276b5 | Eduardo Habkost | if (!bdrv_is_removable(bs)) {
|
519 | 3b5276b5 | Eduardo Habkost | qerror_report(QERR_DEVICE_NOT_REMOVABLE, |
520 | 3b5276b5 | Eduardo Habkost | bdrv_get_device_name(bs)); |
521 | 3b5276b5 | Eduardo Habkost | return -1; |
522 | 3b5276b5 | Eduardo Habkost | } |
523 | 3b5276b5 | Eduardo Habkost | if (bdrv_is_locked(bs)) {
|
524 | 3b5276b5 | Eduardo Habkost | qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); |
525 | 3b5276b5 | Eduardo Habkost | return -1; |
526 | 666daa68 | Markus Armbruster | } |
527 | 666daa68 | Markus Armbruster | } |
528 | 3b5276b5 | Eduardo Habkost | bdrv_close(bs); |
529 | 666daa68 | Markus Armbruster | return 0; |
530 | 666daa68 | Markus Armbruster | } |
531 | 666daa68 | Markus Armbruster | |
532 | 666daa68 | Markus Armbruster | int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data) |
533 | 666daa68 | Markus Armbruster | { |
534 | 666daa68 | Markus Armbruster | BlockDriverState *bs; |
535 | eb159d13 | Luiz Capitulino | int force = qdict_get_try_bool(qdict, "force", 0); |
536 | 666daa68 | Markus Armbruster | const char *filename = qdict_get_str(qdict, "device"); |
537 | 666daa68 | Markus Armbruster | |
538 | 666daa68 | Markus Armbruster | bs = bdrv_find(filename); |
539 | 666daa68 | Markus Armbruster | if (!bs) {
|
540 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, filename); |
541 | 666daa68 | Markus Armbruster | return -1; |
542 | 666daa68 | Markus Armbruster | } |
543 | 666daa68 | Markus Armbruster | return eject_device(mon, bs, force);
|
544 | 666daa68 | Markus Armbruster | } |
545 | 666daa68 | Markus Armbruster | |
546 | 666daa68 | Markus Armbruster | int do_block_set_passwd(Monitor *mon, const QDict *qdict, |
547 | 666daa68 | Markus Armbruster | QObject **ret_data) |
548 | 666daa68 | Markus Armbruster | { |
549 | 666daa68 | Markus Armbruster | BlockDriverState *bs; |
550 | 666daa68 | Markus Armbruster | int err;
|
551 | 666daa68 | Markus Armbruster | |
552 | 666daa68 | Markus Armbruster | bs = bdrv_find(qdict_get_str(qdict, "device"));
|
553 | 666daa68 | Markus Armbruster | if (!bs) {
|
554 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
|
555 | 666daa68 | Markus Armbruster | return -1; |
556 | 666daa68 | Markus Armbruster | } |
557 | 666daa68 | Markus Armbruster | |
558 | 666daa68 | Markus Armbruster | err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
|
559 | 666daa68 | Markus Armbruster | if (err == -EINVAL) {
|
560 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); |
561 | 666daa68 | Markus Armbruster | return -1; |
562 | 666daa68 | Markus Armbruster | } else if (err < 0) { |
563 | 666daa68 | Markus Armbruster | qerror_report(QERR_INVALID_PASSWORD); |
564 | 666daa68 | Markus Armbruster | return -1; |
565 | 666daa68 | Markus Armbruster | } |
566 | 666daa68 | Markus Armbruster | |
567 | 666daa68 | Markus Armbruster | return 0; |
568 | 666daa68 | Markus Armbruster | } |
569 | 666daa68 | Markus Armbruster | |
570 | 666daa68 | Markus Armbruster | int do_change_block(Monitor *mon, const char *device, |
571 | 666daa68 | Markus Armbruster | const char *filename, const char *fmt) |
572 | 666daa68 | Markus Armbruster | { |
573 | 666daa68 | Markus Armbruster | BlockDriverState *bs; |
574 | 666daa68 | Markus Armbruster | BlockDriver *drv = NULL;
|
575 | 666daa68 | Markus Armbruster | int bdrv_flags;
|
576 | 666daa68 | Markus Armbruster | |
577 | 666daa68 | Markus Armbruster | bs = bdrv_find(device); |
578 | 666daa68 | Markus Armbruster | if (!bs) {
|
579 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, device); |
580 | 666daa68 | Markus Armbruster | return -1; |
581 | 666daa68 | Markus Armbruster | } |
582 | 666daa68 | Markus Armbruster | if (fmt) {
|
583 | 666daa68 | Markus Armbruster | drv = bdrv_find_whitelisted_format(fmt); |
584 | 666daa68 | Markus Armbruster | if (!drv) {
|
585 | 666daa68 | Markus Armbruster | qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); |
586 | 666daa68 | Markus Armbruster | return -1; |
587 | 666daa68 | Markus Armbruster | } |
588 | 666daa68 | Markus Armbruster | } |
589 | 666daa68 | Markus Armbruster | if (eject_device(mon, bs, 0) < 0) { |
590 | 666daa68 | Markus Armbruster | return -1; |
591 | 666daa68 | Markus Armbruster | } |
592 | 528f7663 | Markus Armbruster | bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
|
593 | 666daa68 | Markus Armbruster | if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { |
594 | 666daa68 | Markus Armbruster | qerror_report(QERR_OPEN_FILE_FAILED, filename); |
595 | 666daa68 | Markus Armbruster | return -1; |
596 | 666daa68 | Markus Armbruster | } |
597 | 666daa68 | Markus Armbruster | return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); |
598 | 666daa68 | Markus Armbruster | } |