root / blockdev.c @ 904ebffe
History | View | Annotate | Download (19.4 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 | 9063f814 | Ryan Harper | #include "hw/qdev.h" |
18 | 9063f814 | Ryan Harper | #include "block_int.h" |
19 | 666daa68 | Markus Armbruster | |
20 | c9b62a7e | Markus Armbruster | static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
|
21 | 666daa68 | Markus Armbruster | |
22 | 14bafc54 | Markus Armbruster | /*
|
23 | 14bafc54 | Markus Armbruster | * We automatically delete the drive when a device using it gets
|
24 | 14bafc54 | Markus Armbruster | * unplugged. Questionable feature, but we can't just drop it.
|
25 | 14bafc54 | Markus Armbruster | * Device models call blockdev_mark_auto_del() to schedule the
|
26 | 14bafc54 | Markus Armbruster | * automatic deletion, and generic qdev code calls blockdev_auto_del()
|
27 | 14bafc54 | Markus Armbruster | * when deletion is actually safe.
|
28 | 14bafc54 | Markus Armbruster | */
|
29 | 14bafc54 | Markus Armbruster | void blockdev_mark_auto_del(BlockDriverState *bs)
|
30 | 14bafc54 | Markus Armbruster | { |
31 | 14bafc54 | Markus Armbruster | DriveInfo *dinfo = drive_get_by_blockdev(bs); |
32 | 14bafc54 | Markus Armbruster | |
33 | 0fc0f1fa | Ryan Harper | if (dinfo) {
|
34 | 0fc0f1fa | Ryan Harper | dinfo->auto_del = 1;
|
35 | 0fc0f1fa | Ryan Harper | } |
36 | 14bafc54 | Markus Armbruster | } |
37 | 14bafc54 | Markus Armbruster | |
38 | 14bafc54 | Markus Armbruster | void blockdev_auto_del(BlockDriverState *bs)
|
39 | 14bafc54 | Markus Armbruster | { |
40 | 14bafc54 | Markus Armbruster | DriveInfo *dinfo = drive_get_by_blockdev(bs); |
41 | 14bafc54 | Markus Armbruster | |
42 | 0fc0f1fa | Ryan Harper | if (dinfo && dinfo->auto_del) {
|
43 | 14bafc54 | Markus Armbruster | drive_uninit(dinfo); |
44 | 14bafc54 | Markus Armbruster | } |
45 | 14bafc54 | Markus Armbruster | } |
46 | 14bafc54 | Markus Armbruster | |
47 | 666daa68 | Markus Armbruster | QemuOpts *drive_add(const char *file, const char *fmt, ...) |
48 | 666daa68 | Markus Armbruster | { |
49 | 666daa68 | Markus Armbruster | va_list ap; |
50 | 666daa68 | Markus Armbruster | char optstr[1024]; |
51 | 666daa68 | Markus Armbruster | QemuOpts *opts; |
52 | 666daa68 | Markus Armbruster | |
53 | 666daa68 | Markus Armbruster | va_start(ap, fmt); |
54 | 666daa68 | Markus Armbruster | vsnprintf(optstr, sizeof(optstr), fmt, ap);
|
55 | 666daa68 | Markus Armbruster | va_end(ap); |
56 | 666daa68 | Markus Armbruster | |
57 | 3329f07b | Gerd Hoffmann | opts = qemu_opts_parse(qemu_find_opts("drive"), optstr, 0); |
58 | 666daa68 | Markus Armbruster | if (!opts) {
|
59 | 666daa68 | Markus Armbruster | return NULL; |
60 | 666daa68 | Markus Armbruster | } |
61 | 666daa68 | Markus Armbruster | if (file)
|
62 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "file", file);
|
63 | 666daa68 | Markus Armbruster | return opts;
|
64 | 666daa68 | Markus Armbruster | } |
65 | 666daa68 | Markus Armbruster | |
66 | 666daa68 | Markus Armbruster | DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) |
67 | 666daa68 | Markus Armbruster | { |
68 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
69 | 666daa68 | Markus Armbruster | |
70 | 666daa68 | Markus Armbruster | /* seek interface, bus and unit */
|
71 | 666daa68 | Markus Armbruster | |
72 | 666daa68 | Markus Armbruster | QTAILQ_FOREACH(dinfo, &drives, next) { |
73 | 666daa68 | Markus Armbruster | if (dinfo->type == type &&
|
74 | 666daa68 | Markus Armbruster | dinfo->bus == bus && |
75 | 666daa68 | Markus Armbruster | dinfo->unit == unit) |
76 | 666daa68 | Markus Armbruster | return dinfo;
|
77 | 666daa68 | Markus Armbruster | } |
78 | 666daa68 | Markus Armbruster | |
79 | 666daa68 | Markus Armbruster | return NULL; |
80 | 666daa68 | Markus Armbruster | } |
81 | 666daa68 | Markus Armbruster | |
82 | 666daa68 | Markus Armbruster | int drive_get_max_bus(BlockInterfaceType type)
|
83 | 666daa68 | Markus Armbruster | { |
84 | 666daa68 | Markus Armbruster | int max_bus;
|
85 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
86 | 666daa68 | Markus Armbruster | |
87 | 666daa68 | Markus Armbruster | max_bus = -1;
|
88 | 666daa68 | Markus Armbruster | QTAILQ_FOREACH(dinfo, &drives, next) { |
89 | 666daa68 | Markus Armbruster | if(dinfo->type == type &&
|
90 | 666daa68 | Markus Armbruster | dinfo->bus > max_bus) |
91 | 666daa68 | Markus Armbruster | max_bus = dinfo->bus; |
92 | 666daa68 | Markus Armbruster | } |
93 | 666daa68 | Markus Armbruster | return max_bus;
|
94 | 666daa68 | Markus Armbruster | } |
95 | 666daa68 | Markus Armbruster | |
96 | 13839974 | Markus Armbruster | /* Get a block device. This should only be used for single-drive devices
|
97 | 13839974 | Markus Armbruster | (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
|
98 | 13839974 | Markus Armbruster | appropriate bus. */
|
99 | 13839974 | Markus Armbruster | DriveInfo *drive_get_next(BlockInterfaceType type) |
100 | 13839974 | Markus Armbruster | { |
101 | 13839974 | Markus Armbruster | static int next_block_unit[IF_COUNT]; |
102 | 13839974 | Markus Armbruster | |
103 | 13839974 | Markus Armbruster | return drive_get(type, 0, next_block_unit[type]++); |
104 | 13839974 | Markus Armbruster | } |
105 | 13839974 | Markus Armbruster | |
106 | e4700e59 | Markus Armbruster | DriveInfo *drive_get_by_blockdev(BlockDriverState *bs) |
107 | 666daa68 | Markus Armbruster | { |
108 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
109 | 666daa68 | Markus Armbruster | |
110 | 666daa68 | Markus Armbruster | QTAILQ_FOREACH(dinfo, &drives, next) { |
111 | e4700e59 | Markus Armbruster | if (dinfo->bdrv == bs) {
|
112 | e4700e59 | Markus Armbruster | return dinfo;
|
113 | e4700e59 | Markus Armbruster | } |
114 | 666daa68 | Markus Armbruster | } |
115 | e4700e59 | Markus Armbruster | return NULL; |
116 | 666daa68 | Markus Armbruster | } |
117 | 666daa68 | Markus Armbruster | |
118 | 666daa68 | Markus Armbruster | static void bdrv_format_print(void *opaque, const char *name) |
119 | 666daa68 | Markus Armbruster | { |
120 | 807105a7 | Markus Armbruster | error_printf(" %s", name);
|
121 | 666daa68 | Markus Armbruster | } |
122 | 666daa68 | Markus Armbruster | |
123 | 666daa68 | Markus Armbruster | void drive_uninit(DriveInfo *dinfo)
|
124 | 666daa68 | Markus Armbruster | { |
125 | 666daa68 | Markus Armbruster | qemu_opts_del(dinfo->opts); |
126 | 666daa68 | Markus Armbruster | bdrv_delete(dinfo->bdrv); |
127 | 666daa68 | Markus Armbruster | QTAILQ_REMOVE(&drives, dinfo, next); |
128 | 666daa68 | Markus Armbruster | qemu_free(dinfo); |
129 | 666daa68 | Markus Armbruster | } |
130 | 666daa68 | Markus Armbruster | |
131 | 666daa68 | Markus Armbruster | static int parse_block_error_action(const char *buf, int is_read) |
132 | 666daa68 | Markus Armbruster | { |
133 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "ignore")) { |
134 | 666daa68 | Markus Armbruster | return BLOCK_ERR_IGNORE;
|
135 | 666daa68 | Markus Armbruster | } else if (!is_read && !strcmp(buf, "enospc")) { |
136 | 666daa68 | Markus Armbruster | return BLOCK_ERR_STOP_ENOSPC;
|
137 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "stop")) { |
138 | 666daa68 | Markus Armbruster | return BLOCK_ERR_STOP_ANY;
|
139 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "report")) { |
140 | 666daa68 | Markus Armbruster | return BLOCK_ERR_REPORT;
|
141 | 666daa68 | Markus Armbruster | } else {
|
142 | 807105a7 | Markus Armbruster | error_report("'%s' invalid %s error action",
|
143 | 807105a7 | Markus Armbruster | buf, is_read ? "read" : "write"); |
144 | 666daa68 | Markus Armbruster | return -1; |
145 | 666daa68 | Markus Armbruster | } |
146 | 666daa68 | Markus Armbruster | } |
147 | 666daa68 | Markus Armbruster | |
148 | 666daa68 | Markus Armbruster | DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) |
149 | 666daa68 | Markus Armbruster | { |
150 | 666daa68 | Markus Armbruster | const char *buf; |
151 | 666daa68 | Markus Armbruster | const char *file = NULL; |
152 | 666daa68 | Markus Armbruster | char devname[128]; |
153 | 666daa68 | Markus Armbruster | const char *serial; |
154 | 666daa68 | Markus Armbruster | const char *mediastr = ""; |
155 | 666daa68 | Markus Armbruster | BlockInterfaceType type; |
156 | 666daa68 | Markus Armbruster | enum { MEDIA_DISK, MEDIA_CDROM } media;
|
157 | 666daa68 | Markus Armbruster | int bus_id, unit_id;
|
158 | 666daa68 | Markus Armbruster | int cyls, heads, secs, translation;
|
159 | 666daa68 | Markus Armbruster | BlockDriver *drv = NULL;
|
160 | 666daa68 | Markus Armbruster | int max_devs;
|
161 | 666daa68 | Markus Armbruster | int index;
|
162 | 666daa68 | Markus Armbruster | int ro = 0; |
163 | 666daa68 | Markus Armbruster | int bdrv_flags = 0; |
164 | 666daa68 | Markus Armbruster | int on_read_error, on_write_error;
|
165 | 666daa68 | Markus Armbruster | const char *devaddr; |
166 | 666daa68 | Markus Armbruster | DriveInfo *dinfo; |
167 | 666daa68 | Markus Armbruster | int snapshot = 0; |
168 | 666daa68 | Markus Armbruster | int ret;
|
169 | 666daa68 | Markus Armbruster | |
170 | 666daa68 | Markus Armbruster | *fatal_error = 1;
|
171 | 666daa68 | Markus Armbruster | |
172 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_AUTO; |
173 | 666daa68 | Markus Armbruster | |
174 | 666daa68 | Markus Armbruster | if (default_to_scsi) {
|
175 | 666daa68 | Markus Armbruster | type = IF_SCSI; |
176 | 666daa68 | Markus Armbruster | max_devs = MAX_SCSI_DEVS; |
177 | 666daa68 | Markus Armbruster | pstrcpy(devname, sizeof(devname), "scsi"); |
178 | 666daa68 | Markus Armbruster | } else {
|
179 | 666daa68 | Markus Armbruster | type = IF_IDE; |
180 | 666daa68 | Markus Armbruster | max_devs = MAX_IDE_DEVS; |
181 | 666daa68 | Markus Armbruster | pstrcpy(devname, sizeof(devname), "ide"); |
182 | 666daa68 | Markus Armbruster | } |
183 | 666daa68 | Markus Armbruster | media = MEDIA_DISK; |
184 | 666daa68 | Markus Armbruster | |
185 | 666daa68 | Markus Armbruster | /* extract parameters */
|
186 | 666daa68 | Markus Armbruster | bus_id = qemu_opt_get_number(opts, "bus", 0); |
187 | 666daa68 | Markus Armbruster | unit_id = qemu_opt_get_number(opts, "unit", -1); |
188 | 666daa68 | Markus Armbruster | index = qemu_opt_get_number(opts, "index", -1); |
189 | 666daa68 | Markus Armbruster | |
190 | 666daa68 | Markus Armbruster | cyls = qemu_opt_get_number(opts, "cyls", 0); |
191 | 666daa68 | Markus Armbruster | heads = qemu_opt_get_number(opts, "heads", 0); |
192 | 666daa68 | Markus Armbruster | secs = qemu_opt_get_number(opts, "secs", 0); |
193 | 666daa68 | Markus Armbruster | |
194 | 666daa68 | Markus Armbruster | snapshot = qemu_opt_get_bool(opts, "snapshot", 0); |
195 | 666daa68 | Markus Armbruster | ro = qemu_opt_get_bool(opts, "readonly", 0); |
196 | 666daa68 | Markus Armbruster | |
197 | 666daa68 | Markus Armbruster | file = qemu_opt_get(opts, "file");
|
198 | 666daa68 | Markus Armbruster | serial = qemu_opt_get(opts, "serial");
|
199 | 666daa68 | Markus Armbruster | |
200 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "if")) != NULL) { |
201 | 666daa68 | Markus Armbruster | pstrcpy(devname, sizeof(devname), buf);
|
202 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "ide")) { |
203 | 666daa68 | Markus Armbruster | type = IF_IDE; |
204 | 666daa68 | Markus Armbruster | max_devs = MAX_IDE_DEVS; |
205 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "scsi")) { |
206 | 666daa68 | Markus Armbruster | type = IF_SCSI; |
207 | 666daa68 | Markus Armbruster | max_devs = MAX_SCSI_DEVS; |
208 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "floppy")) { |
209 | 666daa68 | Markus Armbruster | type = IF_FLOPPY; |
210 | 666daa68 | Markus Armbruster | max_devs = 0;
|
211 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "pflash")) { |
212 | 666daa68 | Markus Armbruster | type = IF_PFLASH; |
213 | 666daa68 | Markus Armbruster | max_devs = 0;
|
214 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "mtd")) { |
215 | 666daa68 | Markus Armbruster | type = IF_MTD; |
216 | 666daa68 | Markus Armbruster | max_devs = 0;
|
217 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "sd")) { |
218 | 666daa68 | Markus Armbruster | type = IF_SD; |
219 | 666daa68 | Markus Armbruster | max_devs = 0;
|
220 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "virtio")) { |
221 | 666daa68 | Markus Armbruster | type = IF_VIRTIO; |
222 | 666daa68 | Markus Armbruster | max_devs = 0;
|
223 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "xen")) { |
224 | 666daa68 | Markus Armbruster | type = IF_XEN; |
225 | 666daa68 | Markus Armbruster | max_devs = 0;
|
226 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "none")) { |
227 | 666daa68 | Markus Armbruster | type = IF_NONE; |
228 | 666daa68 | Markus Armbruster | max_devs = 0;
|
229 | 666daa68 | Markus Armbruster | } else {
|
230 | 807105a7 | Markus Armbruster | error_report("unsupported bus type '%s'", buf);
|
231 | 666daa68 | Markus Armbruster | return NULL; |
232 | 666daa68 | Markus Armbruster | } |
233 | 666daa68 | Markus Armbruster | } |
234 | 666daa68 | Markus Armbruster | |
235 | 666daa68 | Markus Armbruster | if (cyls || heads || secs) {
|
236 | 666daa68 | Markus Armbruster | if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { |
237 | 807105a7 | Markus Armbruster | error_report("invalid physical cyls number");
|
238 | 666daa68 | Markus Armbruster | return NULL; |
239 | 666daa68 | Markus Armbruster | } |
240 | 666daa68 | Markus Armbruster | if (heads < 1 || (type == IF_IDE && heads > 16)) { |
241 | 807105a7 | Markus Armbruster | error_report("invalid physical heads number");
|
242 | 666daa68 | Markus Armbruster | return NULL; |
243 | 666daa68 | Markus Armbruster | } |
244 | 666daa68 | Markus Armbruster | if (secs < 1 || (type == IF_IDE && secs > 63)) { |
245 | 807105a7 | Markus Armbruster | error_report("invalid physical secs number");
|
246 | 666daa68 | Markus Armbruster | return NULL; |
247 | 666daa68 | Markus Armbruster | } |
248 | 666daa68 | Markus Armbruster | } |
249 | 666daa68 | Markus Armbruster | |
250 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "trans")) != NULL) { |
251 | 666daa68 | Markus Armbruster | if (!cyls) {
|
252 | 807105a7 | Markus Armbruster | error_report("'%s' trans must be used with cyls,heads and secs",
|
253 | 807105a7 | Markus Armbruster | buf); |
254 | 666daa68 | Markus Armbruster | return NULL; |
255 | 666daa68 | Markus Armbruster | } |
256 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "none")) |
257 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_NONE; |
258 | 666daa68 | Markus Armbruster | else if (!strcmp(buf, "lba")) |
259 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_LBA; |
260 | 666daa68 | Markus Armbruster | else if (!strcmp(buf, "auto")) |
261 | 666daa68 | Markus Armbruster | translation = BIOS_ATA_TRANSLATION_AUTO; |
262 | 666daa68 | Markus Armbruster | else {
|
263 | 807105a7 | Markus Armbruster | error_report("'%s' invalid translation type", buf);
|
264 | 666daa68 | Markus Armbruster | return NULL; |
265 | 666daa68 | Markus Armbruster | } |
266 | 666daa68 | Markus Armbruster | } |
267 | 666daa68 | Markus Armbruster | |
268 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "media")) != NULL) { |
269 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "disk")) { |
270 | 666daa68 | Markus Armbruster | media = MEDIA_DISK; |
271 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "cdrom")) { |
272 | 666daa68 | Markus Armbruster | if (cyls || secs || heads) {
|
273 | 807105a7 | Markus Armbruster | error_report("'%s' invalid physical CHS format", buf);
|
274 | 666daa68 | Markus Armbruster | return NULL; |
275 | 666daa68 | Markus Armbruster | } |
276 | 666daa68 | Markus Armbruster | media = MEDIA_CDROM; |
277 | 666daa68 | Markus Armbruster | } else {
|
278 | 807105a7 | Markus Armbruster | error_report("'%s' invalid media", buf);
|
279 | 666daa68 | Markus Armbruster | return NULL; |
280 | 666daa68 | Markus Armbruster | } |
281 | 666daa68 | Markus Armbruster | } |
282 | 666daa68 | Markus Armbruster | |
283 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "cache")) != NULL) { |
284 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "off") || !strcmp(buf, "none")) { |
285 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_NOCACHE; |
286 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "writeback")) { |
287 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_CACHE_WB; |
288 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "unsafe")) { |
289 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_CACHE_WB; |
290 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_NO_FLUSH; |
291 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "writethrough")) { |
292 | 666daa68 | Markus Armbruster | /* this is the default */
|
293 | 666daa68 | Markus Armbruster | } else {
|
294 | 807105a7 | Markus Armbruster | error_report("invalid cache option");
|
295 | 666daa68 | Markus Armbruster | return NULL; |
296 | 666daa68 | Markus Armbruster | } |
297 | 666daa68 | Markus Armbruster | } |
298 | 666daa68 | Markus Armbruster | |
299 | 666daa68 | Markus Armbruster | #ifdef CONFIG_LINUX_AIO
|
300 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "aio")) != NULL) { |
301 | 666daa68 | Markus Armbruster | if (!strcmp(buf, "native")) { |
302 | 666daa68 | Markus Armbruster | bdrv_flags |= BDRV_O_NATIVE_AIO; |
303 | 666daa68 | Markus Armbruster | } else if (!strcmp(buf, "threads")) { |
304 | 666daa68 | Markus Armbruster | /* this is the default */
|
305 | 666daa68 | Markus Armbruster | } else {
|
306 | 807105a7 | Markus Armbruster | error_report("invalid aio option");
|
307 | 666daa68 | Markus Armbruster | return NULL; |
308 | 666daa68 | Markus Armbruster | } |
309 | 666daa68 | Markus Armbruster | } |
310 | 666daa68 | Markus Armbruster | #endif
|
311 | 666daa68 | Markus Armbruster | |
312 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "format")) != NULL) { |
313 | 666daa68 | Markus Armbruster | if (strcmp(buf, "?") == 0) { |
314 | 807105a7 | Markus Armbruster | error_printf("Supported formats:");
|
315 | 807105a7 | Markus Armbruster | bdrv_iterate_format(bdrv_format_print, NULL);
|
316 | 807105a7 | Markus Armbruster | error_printf("\n");
|
317 | 807105a7 | Markus Armbruster | return NULL; |
318 | 666daa68 | Markus Armbruster | } |
319 | 666daa68 | Markus Armbruster | drv = bdrv_find_whitelisted_format(buf); |
320 | 666daa68 | Markus Armbruster | if (!drv) {
|
321 | 807105a7 | Markus Armbruster | error_report("'%s' invalid format", buf);
|
322 | 666daa68 | Markus Armbruster | return NULL; |
323 | 666daa68 | Markus Armbruster | } |
324 | 666daa68 | Markus Armbruster | } |
325 | 666daa68 | Markus Armbruster | |
326 | 666daa68 | Markus Armbruster | on_write_error = BLOCK_ERR_STOP_ENOSPC; |
327 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "werror")) != NULL) { |
328 | 666daa68 | Markus Armbruster | if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
|
329 | 807105a7 | Markus Armbruster | error_report("werror is not supported by this bus type");
|
330 | 666daa68 | Markus Armbruster | return NULL; |
331 | 666daa68 | Markus Armbruster | } |
332 | 666daa68 | Markus Armbruster | |
333 | 666daa68 | Markus Armbruster | on_write_error = parse_block_error_action(buf, 0);
|
334 | 666daa68 | Markus Armbruster | if (on_write_error < 0) { |
335 | 666daa68 | Markus Armbruster | return NULL; |
336 | 666daa68 | Markus Armbruster | } |
337 | 666daa68 | Markus Armbruster | } |
338 | 666daa68 | Markus Armbruster | |
339 | 666daa68 | Markus Armbruster | on_read_error = BLOCK_ERR_REPORT; |
340 | 666daa68 | Markus Armbruster | if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { |
341 | 5dba48a8 | Kevin Wolf | if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
|
342 | 807105a7 | Markus Armbruster | error_report("rerror is not supported by this bus type");
|
343 | 666daa68 | Markus Armbruster | return NULL; |
344 | 666daa68 | Markus Armbruster | } |
345 | 666daa68 | Markus Armbruster | |
346 | 666daa68 | Markus Armbruster | on_read_error = parse_block_error_action(buf, 1);
|
347 | 666daa68 | Markus Armbruster | if (on_read_error < 0) { |
348 | 666daa68 | Markus Armbruster | return NULL; |
349 | 666daa68 | Markus Armbruster | } |
350 | 666daa68 | Markus Armbruster | } |
351 | 666daa68 | Markus Armbruster | |
352 | 666daa68 | Markus Armbruster | if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { |
353 | 666daa68 | Markus Armbruster | if (type != IF_VIRTIO) {
|
354 | 807105a7 | Markus Armbruster | error_report("addr is not supported by this bus type");
|
355 | 666daa68 | Markus Armbruster | return NULL; |
356 | 666daa68 | Markus Armbruster | } |
357 | 666daa68 | Markus Armbruster | } |
358 | 666daa68 | Markus Armbruster | |
359 | 666daa68 | Markus Armbruster | /* compute bus and unit according index */
|
360 | 666daa68 | Markus Armbruster | |
361 | 666daa68 | Markus Armbruster | if (index != -1) { |
362 | 666daa68 | Markus Armbruster | if (bus_id != 0 || unit_id != -1) { |
363 | 807105a7 | Markus Armbruster | error_report("index cannot be used with bus and unit");
|
364 | 666daa68 | Markus Armbruster | return NULL; |
365 | 666daa68 | Markus Armbruster | } |
366 | 666daa68 | Markus Armbruster | if (max_devs == 0) |
367 | 666daa68 | Markus Armbruster | { |
368 | 666daa68 | Markus Armbruster | unit_id = index; |
369 | 666daa68 | Markus Armbruster | bus_id = 0;
|
370 | 666daa68 | Markus Armbruster | } else {
|
371 | 666daa68 | Markus Armbruster | unit_id = index % max_devs; |
372 | 666daa68 | Markus Armbruster | bus_id = index / max_devs; |
373 | 666daa68 | Markus Armbruster | } |
374 | 666daa68 | Markus Armbruster | } |
375 | 666daa68 | Markus Armbruster | |
376 | 666daa68 | Markus Armbruster | /* if user doesn't specify a unit_id,
|
377 | 666daa68 | Markus Armbruster | * try to find the first free
|
378 | 666daa68 | Markus Armbruster | */
|
379 | 666daa68 | Markus Armbruster | |
380 | 666daa68 | Markus Armbruster | if (unit_id == -1) { |
381 | 666daa68 | Markus Armbruster | unit_id = 0;
|
382 | 666daa68 | Markus Armbruster | while (drive_get(type, bus_id, unit_id) != NULL) { |
383 | 666daa68 | Markus Armbruster | unit_id++; |
384 | 666daa68 | Markus Armbruster | if (max_devs && unit_id >= max_devs) {
|
385 | 666daa68 | Markus Armbruster | unit_id -= max_devs; |
386 | 666daa68 | Markus Armbruster | bus_id++; |
387 | 666daa68 | Markus Armbruster | } |
388 | 666daa68 | Markus Armbruster | } |
389 | 666daa68 | Markus Armbruster | } |
390 | 666daa68 | Markus Armbruster | |
391 | 666daa68 | Markus Armbruster | /* check unit id */
|
392 | 666daa68 | Markus Armbruster | |
393 | 666daa68 | Markus Armbruster | if (max_devs && unit_id >= max_devs) {
|
394 | 807105a7 | Markus Armbruster | error_report("unit %d too big (max is %d)",
|
395 | 807105a7 | Markus Armbruster | unit_id, max_devs - 1);
|
396 | 666daa68 | Markus Armbruster | return NULL; |
397 | 666daa68 | Markus Armbruster | } |
398 | 666daa68 | Markus Armbruster | |
399 | 666daa68 | Markus Armbruster | /*
|
400 | 666daa68 | Markus Armbruster | * ignore multiple definitions
|
401 | 666daa68 | Markus Armbruster | */
|
402 | 666daa68 | Markus Armbruster | |
403 | 666daa68 | Markus Armbruster | if (drive_get(type, bus_id, unit_id) != NULL) { |
404 | 666daa68 | Markus Armbruster | *fatal_error = 0;
|
405 | 666daa68 | Markus Armbruster | return NULL; |
406 | 666daa68 | Markus Armbruster | } |
407 | 666daa68 | Markus Armbruster | |
408 | 666daa68 | Markus Armbruster | /* init */
|
409 | 666daa68 | Markus Armbruster | |
410 | 666daa68 | Markus Armbruster | dinfo = qemu_mallocz(sizeof(*dinfo));
|
411 | 666daa68 | Markus Armbruster | if ((buf = qemu_opts_id(opts)) != NULL) { |
412 | 666daa68 | Markus Armbruster | dinfo->id = qemu_strdup(buf); |
413 | 666daa68 | Markus Armbruster | } else {
|
414 | 666daa68 | Markus Armbruster | /* no id supplied -> create one */
|
415 | 666daa68 | Markus Armbruster | dinfo->id = qemu_mallocz(32);
|
416 | 666daa68 | Markus Armbruster | if (type == IF_IDE || type == IF_SCSI)
|
417 | 666daa68 | Markus Armbruster | mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; |
418 | 666daa68 | Markus Armbruster | if (max_devs)
|
419 | 666daa68 | Markus Armbruster | snprintf(dinfo->id, 32, "%s%i%s%i", |
420 | 666daa68 | Markus Armbruster | devname, bus_id, mediastr, unit_id); |
421 | 666daa68 | Markus Armbruster | else
|
422 | 666daa68 | Markus Armbruster | snprintf(dinfo->id, 32, "%s%s%i", |
423 | 666daa68 | Markus Armbruster | devname, mediastr, unit_id); |
424 | 666daa68 | Markus Armbruster | } |
425 | 666daa68 | Markus Armbruster | dinfo->bdrv = bdrv_new(dinfo->id); |
426 | 666daa68 | Markus Armbruster | dinfo->devaddr = devaddr; |
427 | 666daa68 | Markus Armbruster | dinfo->type = type; |
428 | 666daa68 | Markus Armbruster | dinfo->bus = bus_id; |
429 | 666daa68 | Markus Armbruster | dinfo->unit = unit_id; |
430 | 666daa68 | Markus Armbruster | dinfo->opts = opts; |
431 | 666daa68 | Markus Armbruster | if (serial)
|
432 | 653dbec7 | Luiz Capitulino | strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1); |
433 | 666daa68 | Markus Armbruster | QTAILQ_INSERT_TAIL(&drives, dinfo, next); |
434 | 666daa68 | Markus Armbruster | |
435 | abd7f68d | Markus Armbruster | bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error); |
436 | abd7f68d | Markus Armbruster | |
437 | 666daa68 | Markus Armbruster | switch(type) {
|
438 | 666daa68 | Markus Armbruster | case IF_IDE:
|
439 | 666daa68 | Markus Armbruster | case IF_SCSI:
|
440 | 666daa68 | Markus Armbruster | case IF_XEN:
|
441 | 666daa68 | Markus Armbruster | case IF_NONE:
|
442 | 666daa68 | Markus Armbruster | switch(media) {
|
443 | 666daa68 | Markus Armbruster | case MEDIA_DISK:
|
444 | 666daa68 | Markus Armbruster | if (cyls != 0) { |
445 | 666daa68 | Markus Armbruster | bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); |
446 | 666daa68 | Markus Armbruster | bdrv_set_translation_hint(dinfo->bdrv, translation); |
447 | 666daa68 | Markus Armbruster | } |
448 | 666daa68 | Markus Armbruster | break;
|
449 | 666daa68 | Markus Armbruster | case MEDIA_CDROM:
|
450 | 666daa68 | Markus Armbruster | bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); |
451 | 666daa68 | Markus Armbruster | break;
|
452 | 666daa68 | Markus Armbruster | } |
453 | 666daa68 | Markus Armbruster | break;
|
454 | 666daa68 | Markus Armbruster | case IF_SD:
|
455 | 666daa68 | Markus Armbruster | /* FIXME: This isn't really a floppy, but it's a reasonable
|
456 | 666daa68 | Markus Armbruster | approximation. */
|
457 | 666daa68 | Markus Armbruster | case IF_FLOPPY:
|
458 | 666daa68 | Markus Armbruster | bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); |
459 | 666daa68 | Markus Armbruster | break;
|
460 | 666daa68 | Markus Armbruster | case IF_PFLASH:
|
461 | 666daa68 | Markus Armbruster | case IF_MTD:
|
462 | 666daa68 | Markus Armbruster | break;
|
463 | 666daa68 | Markus Armbruster | case IF_VIRTIO:
|
464 | 666daa68 | Markus Armbruster | /* add virtio block device */
|
465 | 3329f07b | Gerd Hoffmann | opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0); |
466 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "driver", "virtio-blk-pci"); |
467 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "drive", dinfo->id);
|
468 | 666daa68 | Markus Armbruster | if (devaddr)
|
469 | 666daa68 | Markus Armbruster | qemu_opt_set(opts, "addr", devaddr);
|
470 | 666daa68 | Markus Armbruster | break;
|
471 | 666daa68 | Markus Armbruster | case IF_COUNT:
|
472 | 666daa68 | Markus Armbruster | abort(); |
473 | 666daa68 | Markus Armbruster | } |
474 | dd5b0d71 | Markus Armbruster | if (!file || !*file) {
|
475 | 666daa68 | Markus Armbruster | *fatal_error = 0;
|
476 | 666daa68 | Markus Armbruster | return NULL; |
477 | 666daa68 | Markus Armbruster | } |
478 | 666daa68 | Markus Armbruster | if (snapshot) {
|
479 | 666daa68 | Markus Armbruster | /* always use cache=unsafe with snapshot */
|
480 | 666daa68 | Markus Armbruster | bdrv_flags &= ~BDRV_O_CACHE_MASK; |
481 | 666daa68 | Markus Armbruster | bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); |
482 | 666daa68 | Markus Armbruster | } |
483 | 666daa68 | Markus Armbruster | |
484 | 666daa68 | Markus Armbruster | if (media == MEDIA_CDROM) {
|
485 | 666daa68 | Markus Armbruster | /* CDROM is fine for any interface, don't check. */
|
486 | 666daa68 | Markus Armbruster | ro = 1;
|
487 | 666daa68 | Markus Armbruster | } else if (ro == 1) { |
488 | 666daa68 | Markus Armbruster | if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
|
489 | 807105a7 | Markus Armbruster | error_report("readonly not supported by this bus type");
|
490 | 666daa68 | Markus Armbruster | return NULL; |
491 | 666daa68 | Markus Armbruster | } |
492 | 666daa68 | Markus Armbruster | } |
493 | 666daa68 | Markus Armbruster | |
494 | 666daa68 | Markus Armbruster | bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
|
495 | 666daa68 | Markus Armbruster | |
496 | 666daa68 | Markus Armbruster | ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); |
497 | 666daa68 | Markus Armbruster | if (ret < 0) { |
498 | 807105a7 | Markus Armbruster | error_report("could not open disk image %s: %s",
|
499 | 807105a7 | Markus Armbruster | file, strerror(-ret)); |
500 | 666daa68 | Markus Armbruster | return NULL; |
501 | 666daa68 | Markus Armbruster | } |
502 | 666daa68 | Markus Armbruster | |
503 | 666daa68 | Markus Armbruster | if (bdrv_key_required(dinfo->bdrv))
|
504 | 666daa68 | Markus Armbruster | autostart = 0;
|
505 | 666daa68 | Markus Armbruster | *fatal_error = 0;
|
506 | 666daa68 | Markus Armbruster | return dinfo;
|
507 | 666daa68 | Markus Armbruster | } |
508 | 666daa68 | Markus Armbruster | |
509 | 666daa68 | Markus Armbruster | void do_commit(Monitor *mon, const QDict *qdict) |
510 | 666daa68 | Markus Armbruster | { |
511 | 666daa68 | Markus Armbruster | const char *device = qdict_get_str(qdict, "device"); |
512 | 6ab4b5ab | Markus Armbruster | BlockDriverState *bs; |
513 | 666daa68 | Markus Armbruster | |
514 | 6ab4b5ab | Markus Armbruster | if (!strcmp(device, "all")) { |
515 | 6ab4b5ab | Markus Armbruster | bdrv_commit_all(); |
516 | 6ab4b5ab | Markus Armbruster | } else {
|
517 | 6ab4b5ab | Markus Armbruster | bs = bdrv_find(device); |
518 | ac59eb95 | Markus Armbruster | if (!bs) {
|
519 | ac59eb95 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, device); |
520 | ac59eb95 | Markus Armbruster | return;
|
521 | 6ab4b5ab | Markus Armbruster | } |
522 | ac59eb95 | Markus Armbruster | bdrv_commit(bs); |
523 | 666daa68 | Markus Armbruster | } |
524 | 666daa68 | Markus Armbruster | } |
525 | 666daa68 | Markus Armbruster | |
526 | f8882568 | Jes Sorensen | int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data) |
527 | f8882568 | Jes Sorensen | { |
528 | f8882568 | Jes Sorensen | const char *device = qdict_get_str(qdict, "device"); |
529 | f8882568 | Jes Sorensen | const char *filename = qdict_get_try_str(qdict, "snapshot_file"); |
530 | f8882568 | Jes Sorensen | const char *format = qdict_get_try_str(qdict, "format"); |
531 | f8882568 | Jes Sorensen | BlockDriverState *bs; |
532 | f8882568 | Jes Sorensen | BlockDriver *drv, *proto_drv; |
533 | f8882568 | Jes Sorensen | int ret = 0; |
534 | f8882568 | Jes Sorensen | int flags;
|
535 | f8882568 | Jes Sorensen | |
536 | c90f1b32 | Jes Sorensen | if (!filename) {
|
537 | c90f1b32 | Jes Sorensen | qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
|
538 | c90f1b32 | Jes Sorensen | ret = -1;
|
539 | c90f1b32 | Jes Sorensen | goto out;
|
540 | c90f1b32 | Jes Sorensen | } |
541 | c90f1b32 | Jes Sorensen | |
542 | f8882568 | Jes Sorensen | bs = bdrv_find(device); |
543 | f8882568 | Jes Sorensen | if (!bs) {
|
544 | f8882568 | Jes Sorensen | qerror_report(QERR_DEVICE_NOT_FOUND, device); |
545 | f8882568 | Jes Sorensen | ret = -1;
|
546 | f8882568 | Jes Sorensen | goto out;
|
547 | f8882568 | Jes Sorensen | } |
548 | f8882568 | Jes Sorensen | |
549 | f8882568 | Jes Sorensen | if (!format) {
|
550 | f8882568 | Jes Sorensen | format = "qcow2";
|
551 | f8882568 | Jes Sorensen | } |
552 | f8882568 | Jes Sorensen | |
553 | f8882568 | Jes Sorensen | drv = bdrv_find_format(format); |
554 | f8882568 | Jes Sorensen | if (!drv) {
|
555 | f8882568 | Jes Sorensen | qerror_report(QERR_INVALID_BLOCK_FORMAT, format); |
556 | f8882568 | Jes Sorensen | ret = -1;
|
557 | f8882568 | Jes Sorensen | goto out;
|
558 | f8882568 | Jes Sorensen | } |
559 | f8882568 | Jes Sorensen | |
560 | f8882568 | Jes Sorensen | proto_drv = bdrv_find_protocol(filename); |
561 | f8882568 | Jes Sorensen | if (!proto_drv) {
|
562 | f8882568 | Jes Sorensen | qerror_report(QERR_INVALID_BLOCK_FORMAT, format); |
563 | f8882568 | Jes Sorensen | ret = -1;
|
564 | f8882568 | Jes Sorensen | goto out;
|
565 | f8882568 | Jes Sorensen | } |
566 | f8882568 | Jes Sorensen | |
567 | f8882568 | Jes Sorensen | ret = bdrv_img_create(filename, format, bs->filename, |
568 | f8882568 | Jes Sorensen | bs->drv->format_name, NULL, -1, bs->open_flags); |
569 | f8882568 | Jes Sorensen | if (ret) {
|
570 | f8882568 | Jes Sorensen | goto out;
|
571 | f8882568 | Jes Sorensen | } |
572 | f8882568 | Jes Sorensen | |
573 | f8882568 | Jes Sorensen | qemu_aio_flush(); |
574 | f8882568 | Jes Sorensen | bdrv_flush(bs); |
575 | f8882568 | Jes Sorensen | |
576 | f8882568 | Jes Sorensen | flags = bs->open_flags; |
577 | f8882568 | Jes Sorensen | bdrv_close(bs); |
578 | f8882568 | Jes Sorensen | ret = bdrv_open(bs, filename, flags, drv); |
579 | f8882568 | Jes Sorensen | /*
|
580 | f8882568 | Jes Sorensen | * If reopening the image file we just created fails, we really
|
581 | f8882568 | Jes Sorensen | * are in trouble :(
|
582 | f8882568 | Jes Sorensen | */
|
583 | f8882568 | Jes Sorensen | if (ret != 0) { |
584 | f8882568 | Jes Sorensen | abort(); |
585 | f8882568 | Jes Sorensen | } |
586 | f8882568 | Jes Sorensen | out:
|
587 | f8882568 | Jes Sorensen | if (ret) {
|
588 | f8882568 | Jes Sorensen | ret = -1;
|
589 | f8882568 | Jes Sorensen | } |
590 | f8882568 | Jes Sorensen | |
591 | f8882568 | Jes Sorensen | return ret;
|
592 | f8882568 | Jes Sorensen | } |
593 | f8882568 | Jes Sorensen | |
594 | 666daa68 | Markus Armbruster | static int eject_device(Monitor *mon, BlockDriverState *bs, int force) |
595 | 666daa68 | Markus Armbruster | { |
596 | 3b5276b5 | Eduardo Habkost | if (!force) {
|
597 | 3b5276b5 | Eduardo Habkost | if (!bdrv_is_removable(bs)) {
|
598 | 3b5276b5 | Eduardo Habkost | qerror_report(QERR_DEVICE_NOT_REMOVABLE, |
599 | 3b5276b5 | Eduardo Habkost | bdrv_get_device_name(bs)); |
600 | 3b5276b5 | Eduardo Habkost | return -1; |
601 | 3b5276b5 | Eduardo Habkost | } |
602 | 3b5276b5 | Eduardo Habkost | if (bdrv_is_locked(bs)) {
|
603 | 3b5276b5 | Eduardo Habkost | qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); |
604 | 3b5276b5 | Eduardo Habkost | return -1; |
605 | 666daa68 | Markus Armbruster | } |
606 | 666daa68 | Markus Armbruster | } |
607 | 3b5276b5 | Eduardo Habkost | bdrv_close(bs); |
608 | 666daa68 | Markus Armbruster | return 0; |
609 | 666daa68 | Markus Armbruster | } |
610 | 666daa68 | Markus Armbruster | |
611 | 666daa68 | Markus Armbruster | int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data) |
612 | 666daa68 | Markus Armbruster | { |
613 | 666daa68 | Markus Armbruster | BlockDriverState *bs; |
614 | eb159d13 | Luiz Capitulino | int force = qdict_get_try_bool(qdict, "force", 0); |
615 | 666daa68 | Markus Armbruster | const char *filename = qdict_get_str(qdict, "device"); |
616 | 666daa68 | Markus Armbruster | |
617 | 666daa68 | Markus Armbruster | bs = bdrv_find(filename); |
618 | 666daa68 | Markus Armbruster | if (!bs) {
|
619 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, filename); |
620 | 666daa68 | Markus Armbruster | return -1; |
621 | 666daa68 | Markus Armbruster | } |
622 | 666daa68 | Markus Armbruster | return eject_device(mon, bs, force);
|
623 | 666daa68 | Markus Armbruster | } |
624 | 666daa68 | Markus Armbruster | |
625 | 666daa68 | Markus Armbruster | int do_block_set_passwd(Monitor *mon, const QDict *qdict, |
626 | 666daa68 | Markus Armbruster | QObject **ret_data) |
627 | 666daa68 | Markus Armbruster | { |
628 | 666daa68 | Markus Armbruster | BlockDriverState *bs; |
629 | 666daa68 | Markus Armbruster | int err;
|
630 | 666daa68 | Markus Armbruster | |
631 | 666daa68 | Markus Armbruster | bs = bdrv_find(qdict_get_str(qdict, "device"));
|
632 | 666daa68 | Markus Armbruster | if (!bs) {
|
633 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
|
634 | 666daa68 | Markus Armbruster | return -1; |
635 | 666daa68 | Markus Armbruster | } |
636 | 666daa68 | Markus Armbruster | |
637 | 666daa68 | Markus Armbruster | err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
|
638 | 666daa68 | Markus Armbruster | if (err == -EINVAL) {
|
639 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); |
640 | 666daa68 | Markus Armbruster | return -1; |
641 | 666daa68 | Markus Armbruster | } else if (err < 0) { |
642 | 666daa68 | Markus Armbruster | qerror_report(QERR_INVALID_PASSWORD); |
643 | 666daa68 | Markus Armbruster | return -1; |
644 | 666daa68 | Markus Armbruster | } |
645 | 666daa68 | Markus Armbruster | |
646 | 666daa68 | Markus Armbruster | return 0; |
647 | 666daa68 | Markus Armbruster | } |
648 | 666daa68 | Markus Armbruster | |
649 | 666daa68 | Markus Armbruster | int do_change_block(Monitor *mon, const char *device, |
650 | 666daa68 | Markus Armbruster | const char *filename, const char *fmt) |
651 | 666daa68 | Markus Armbruster | { |
652 | 666daa68 | Markus Armbruster | BlockDriverState *bs; |
653 | 666daa68 | Markus Armbruster | BlockDriver *drv = NULL;
|
654 | 666daa68 | Markus Armbruster | int bdrv_flags;
|
655 | 666daa68 | Markus Armbruster | |
656 | 666daa68 | Markus Armbruster | bs = bdrv_find(device); |
657 | 666daa68 | Markus Armbruster | if (!bs) {
|
658 | 666daa68 | Markus Armbruster | qerror_report(QERR_DEVICE_NOT_FOUND, device); |
659 | 666daa68 | Markus Armbruster | return -1; |
660 | 666daa68 | Markus Armbruster | } |
661 | 666daa68 | Markus Armbruster | if (fmt) {
|
662 | 666daa68 | Markus Armbruster | drv = bdrv_find_whitelisted_format(fmt); |
663 | 666daa68 | Markus Armbruster | if (!drv) {
|
664 | 666daa68 | Markus Armbruster | qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); |
665 | 666daa68 | Markus Armbruster | return -1; |
666 | 666daa68 | Markus Armbruster | } |
667 | 666daa68 | Markus Armbruster | } |
668 | 666daa68 | Markus Armbruster | if (eject_device(mon, bs, 0) < 0) { |
669 | 666daa68 | Markus Armbruster | return -1; |
670 | 666daa68 | Markus Armbruster | } |
671 | 528f7663 | Markus Armbruster | bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
|
672 | 199630b6 | Blue Swirl | bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
|
673 | 666daa68 | Markus Armbruster | if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { |
674 | 666daa68 | Markus Armbruster | qerror_report(QERR_OPEN_FILE_FAILED, filename); |
675 | 666daa68 | Markus Armbruster | return -1; |
676 | 666daa68 | Markus Armbruster | } |
677 | 666daa68 | Markus Armbruster | return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); |
678 | 666daa68 | Markus Armbruster | } |
679 | 9063f814 | Ryan Harper | |
680 | 9063f814 | Ryan Harper | int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) |
681 | 9063f814 | Ryan Harper | { |
682 | 9063f814 | Ryan Harper | const char *id = qdict_get_str(qdict, "id"); |
683 | 9063f814 | Ryan Harper | BlockDriverState *bs; |
684 | 9063f814 | Ryan Harper | BlockDriverState **ptr; |
685 | 9063f814 | Ryan Harper | Property *prop; |
686 | 9063f814 | Ryan Harper | |
687 | 9063f814 | Ryan Harper | bs = bdrv_find(id); |
688 | 9063f814 | Ryan Harper | if (!bs) {
|
689 | 9063f814 | Ryan Harper | qerror_report(QERR_DEVICE_NOT_FOUND, id); |
690 | 9063f814 | Ryan Harper | return -1; |
691 | 9063f814 | Ryan Harper | } |
692 | 9063f814 | Ryan Harper | |
693 | 9063f814 | Ryan Harper | /* quiesce block driver; prevent further io */
|
694 | 9063f814 | Ryan Harper | qemu_aio_flush(); |
695 | 9063f814 | Ryan Harper | bdrv_flush(bs); |
696 | 9063f814 | Ryan Harper | bdrv_close(bs); |
697 | 9063f814 | Ryan Harper | |
698 | 9063f814 | Ryan Harper | /* clean up guest state from pointing to host resource by
|
699 | 9063f814 | Ryan Harper | * finding and removing DeviceState "drive" property */
|
700 | 850ec113 | Markus Armbruster | if (bs->peer) {
|
701 | 850ec113 | Markus Armbruster | for (prop = bs->peer->info->props; prop && prop->name; prop++) {
|
702 | 850ec113 | Markus Armbruster | if (prop->info->type == PROP_TYPE_DRIVE) {
|
703 | 850ec113 | Markus Armbruster | ptr = qdev_get_prop_ptr(bs->peer, prop); |
704 | 850ec113 | Markus Armbruster | if (*ptr == bs) {
|
705 | 850ec113 | Markus Armbruster | bdrv_detach(bs, bs->peer); |
706 | 850ec113 | Markus Armbruster | *ptr = NULL;
|
707 | 850ec113 | Markus Armbruster | break;
|
708 | 850ec113 | Markus Armbruster | } |
709 | 9063f814 | Ryan Harper | } |
710 | 9063f814 | Ryan Harper | } |
711 | 9063f814 | Ryan Harper | } |
712 | 9063f814 | Ryan Harper | |
713 | 9063f814 | Ryan Harper | /* clean up host side */
|
714 | 9063f814 | Ryan Harper | drive_uninit(drive_get_by_blockdev(bs)); |
715 | 9063f814 | Ryan Harper | |
716 | 9063f814 | Ryan Harper | return 0; |
717 | 9063f814 | Ryan Harper | } |
718 | 6d4a2b3a | Christoph Hellwig | |
719 | 6d4a2b3a | Christoph Hellwig | /*
|
720 | 6d4a2b3a | Christoph Hellwig | * XXX: replace the QERR_UNDEFINED_ERROR errors with real values once the
|
721 | 6d4a2b3a | Christoph Hellwig | * existing QERR_ macro mess is cleaned up. A good example for better
|
722 | 6d4a2b3a | Christoph Hellwig | * error reports can be found in the qemu-img resize code.
|
723 | 6d4a2b3a | Christoph Hellwig | */
|
724 | 6d4a2b3a | Christoph Hellwig | int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data) |
725 | 6d4a2b3a | Christoph Hellwig | { |
726 | 6d4a2b3a | Christoph Hellwig | const char *device = qdict_get_str(qdict, "device"); |
727 | 6d4a2b3a | Christoph Hellwig | int64_t size = qdict_get_int(qdict, "size");
|
728 | 6d4a2b3a | Christoph Hellwig | BlockDriverState *bs; |
729 | 6d4a2b3a | Christoph Hellwig | |
730 | 6d4a2b3a | Christoph Hellwig | bs = bdrv_find(device); |
731 | 6d4a2b3a | Christoph Hellwig | if (!bs) {
|
732 | 6d4a2b3a | Christoph Hellwig | qerror_report(QERR_DEVICE_NOT_FOUND, device); |
733 | 6d4a2b3a | Christoph Hellwig | return -1; |
734 | 6d4a2b3a | Christoph Hellwig | } |
735 | 6d4a2b3a | Christoph Hellwig | |
736 | 6d4a2b3a | Christoph Hellwig | if (size < 0) { |
737 | 6d4a2b3a | Christoph Hellwig | qerror_report(QERR_UNDEFINED_ERROR); |
738 | 6d4a2b3a | Christoph Hellwig | return -1; |
739 | 6d4a2b3a | Christoph Hellwig | } |
740 | 6d4a2b3a | Christoph Hellwig | |
741 | 6d4a2b3a | Christoph Hellwig | if (bdrv_truncate(bs, size)) {
|
742 | 6d4a2b3a | Christoph Hellwig | qerror_report(QERR_UNDEFINED_ERROR); |
743 | 6d4a2b3a | Christoph Hellwig | return -1; |
744 | 6d4a2b3a | Christoph Hellwig | } |
745 | 6d4a2b3a | Christoph Hellwig | |
746 | 6d4a2b3a | Christoph Hellwig | return 0; |
747 | 6d4a2b3a | Christoph Hellwig | } |