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