Statistics
| Branch: | Revision:

root / blockdev.c @ 319ae529

History | View | Annotate | Download (20.3 kB)

1
/*
2
 * QEMU host block devices
3
 *
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 * This work is licensed under the terms of the GNU GPL, version 2 or
7
 * later.  See the COPYING file in the top-level directory.
8
 */
9

    
10
#include "block.h"
11
#include "blockdev.h"
12
#include "monitor.h"
13
#include "qerror.h"
14
#include "qemu-option.h"
15
#include "qemu-config.h"
16
#include "sysemu.h"
17
#include "hw/qdev.h"
18
#include "block_int.h"
19

    
20
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
21

    
22
static const char *const if_name[IF_COUNT] = {
23
    [IF_NONE] = "none",
24
    [IF_IDE] = "ide",
25
    [IF_SCSI] = "scsi",
26
    [IF_FLOPPY] = "floppy",
27
    [IF_PFLASH] = "pflash",
28
    [IF_MTD] = "mtd",
29
    [IF_SD] = "sd",
30
    [IF_VIRTIO] = "virtio",
31
    [IF_XEN] = "xen",
32
};
33

    
34
static const int if_max_devs[IF_COUNT] = {
35
    /*
36
     * Do not change these numbers!  They govern how drive option
37
     * index maps to unit and bus.  That mapping is ABI.
38
     *
39
     * All controllers used to imlement if=T drives need to support
40
     * if_max_devs[T] units, for any T with if_max_devs[T] != 0.
41
     * Otherwise, some index values map to "impossible" bus, unit
42
     * values.
43
     *
44
     * For instance, if you change [IF_SCSI] to 255, -drive
45
     * if=scsi,index=12 no longer means bus=1,unit=5, but
46
     * bus=0,unit=12.  With an lsi53c895a controller (7 units max),
47
     * the drive can't be set up.  Regression.
48
     */
49
    [IF_IDE] = 2,
50
    [IF_SCSI] = 7,
51
};
52

    
53
/*
54
 * We automatically delete the drive when a device using it gets
55
 * unplugged.  Questionable feature, but we can't just drop it.
56
 * Device models call blockdev_mark_auto_del() to schedule the
57
 * automatic deletion, and generic qdev code calls blockdev_auto_del()
58
 * when deletion is actually safe.
59
 */
60
void blockdev_mark_auto_del(BlockDriverState *bs)
61
{
62
    DriveInfo *dinfo = drive_get_by_blockdev(bs);
63

    
64
    if (dinfo) {
65
        dinfo->auto_del = 1;
66
    }
67
}
68

    
69
void blockdev_auto_del(BlockDriverState *bs)
70
{
71
    DriveInfo *dinfo = drive_get_by_blockdev(bs);
72

    
73
    if (dinfo && dinfo->auto_del) {
74
        drive_uninit(dinfo);
75
    }
76
}
77

    
78
static int drive_index_to_bus_id(BlockInterfaceType type, int index)
79
{
80
    int max_devs = if_max_devs[type];
81
    return max_devs ? index / max_devs : 0;
82
}
83

    
84
static int drive_index_to_unit_id(BlockInterfaceType type, int index)
85
{
86
    int max_devs = if_max_devs[type];
87
    return max_devs ? index % max_devs : index;
88
}
89

    
90
QemuOpts *drive_def(const char *optstr)
91
{
92
    return qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
93
}
94

    
95
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
96
                    const char *optstr)
97
{
98
    QemuOpts *opts;
99
    char buf[32];
100

    
101
    opts = drive_def(optstr);
102
    if (!opts) {
103
        return NULL;
104
    }
105
    if (type != IF_DEFAULT) {
106
        qemu_opt_set(opts, "if", if_name[type]);
107
    }
108
    if (index >= 0) {
109
        snprintf(buf, sizeof(buf), "%d", index);
110
        qemu_opt_set(opts, "index", buf);
111
    }
112
    if (file)
113
        qemu_opt_set(opts, "file", file);
114
    return opts;
115
}
116

    
117
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
118
{
119
    DriveInfo *dinfo;
120

    
121
    /* seek interface, bus and unit */
122

    
123
    QTAILQ_FOREACH(dinfo, &drives, next) {
124
        if (dinfo->type == type &&
125
            dinfo->bus == bus &&
126
            dinfo->unit == unit)
127
            return dinfo;
128
    }
129

    
130
    return NULL;
131
}
132

    
133
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
134
{
135
    return drive_get(type,
136
                     drive_index_to_bus_id(type, index),
137
                     drive_index_to_unit_id(type, index));
138
}
139

    
140
int drive_get_max_bus(BlockInterfaceType type)
141
{
142
    int max_bus;
143
    DriveInfo *dinfo;
144

    
145
    max_bus = -1;
146
    QTAILQ_FOREACH(dinfo, &drives, next) {
147
        if(dinfo->type == type &&
148
           dinfo->bus > max_bus)
149
            max_bus = dinfo->bus;
150
    }
151
    return max_bus;
152
}
153

    
154
/* Get a block device.  This should only be used for single-drive devices
155
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
156
   appropriate bus.  */
157
DriveInfo *drive_get_next(BlockInterfaceType type)
158
{
159
    static int next_block_unit[IF_COUNT];
160

    
161
    return drive_get(type, 0, next_block_unit[type]++);
162
}
163

    
164
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
165
{
166
    DriveInfo *dinfo;
167

    
168
    QTAILQ_FOREACH(dinfo, &drives, next) {
169
        if (dinfo->bdrv == bs) {
170
            return dinfo;
171
        }
172
    }
173
    return NULL;
174
}
175

    
176
static void bdrv_format_print(void *opaque, const char *name)
177
{
178
    error_printf(" %s", name);
179
}
180

    
181
void drive_uninit(DriveInfo *dinfo)
182
{
183
    qemu_opts_del(dinfo->opts);
184
    bdrv_delete(dinfo->bdrv);
185
    QTAILQ_REMOVE(&drives, dinfo, next);
186
    qemu_free(dinfo);
187
}
188

    
189
static int parse_block_error_action(const char *buf, int is_read)
190
{
191
    if (!strcmp(buf, "ignore")) {
192
        return BLOCK_ERR_IGNORE;
193
    } else if (!is_read && !strcmp(buf, "enospc")) {
194
        return BLOCK_ERR_STOP_ENOSPC;
195
    } else if (!strcmp(buf, "stop")) {
196
        return BLOCK_ERR_STOP_ANY;
197
    } else if (!strcmp(buf, "report")) {
198
        return BLOCK_ERR_REPORT;
199
    } else {
200
        error_report("'%s' invalid %s error action",
201
                     buf, is_read ? "read" : "write");
202
        return -1;
203
    }
204
}
205

    
206
DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
207
{
208
    const char *buf;
209
    const char *file = NULL;
210
    char devname[128];
211
    const char *serial;
212
    const char *mediastr = "";
213
    BlockInterfaceType type;
214
    enum { MEDIA_DISK, MEDIA_CDROM } media;
215
    int bus_id, unit_id;
216
    int cyls, heads, secs, translation;
217
    BlockDriver *drv = NULL;
218
    int max_devs;
219
    int index;
220
    int ro = 0;
221
    int bdrv_flags = 0;
222
    int on_read_error, on_write_error;
223
    const char *devaddr;
224
    DriveInfo *dinfo;
225
    int snapshot = 0;
226
    int ret;
227

    
228
    translation = BIOS_ATA_TRANSLATION_AUTO;
229

    
230
    if (default_to_scsi) {
231
        type = IF_SCSI;
232
        pstrcpy(devname, sizeof(devname), "scsi");
233
    } else {
234
        type = IF_IDE;
235
        pstrcpy(devname, sizeof(devname), "ide");
236
    }
237
    media = MEDIA_DISK;
238

    
239
    /* extract parameters */
240
    bus_id  = qemu_opt_get_number(opts, "bus", 0);
241
    unit_id = qemu_opt_get_number(opts, "unit", -1);
242
    index   = qemu_opt_get_number(opts, "index", -1);
243

    
244
    cyls  = qemu_opt_get_number(opts, "cyls", 0);
245
    heads = qemu_opt_get_number(opts, "heads", 0);
246
    secs  = qemu_opt_get_number(opts, "secs", 0);
247

    
248
    snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
249
    ro = qemu_opt_get_bool(opts, "readonly", 0);
250

    
251
    file = qemu_opt_get(opts, "file");
252
    serial = qemu_opt_get(opts, "serial");
253

    
254
    if ((buf = qemu_opt_get(opts, "if")) != NULL) {
255
        pstrcpy(devname, sizeof(devname), buf);
256
        for (type = 0; type < IF_COUNT && strcmp(buf, if_name[type]); type++)
257
            ;
258
        if (type == IF_COUNT) {
259
            error_report("unsupported bus type '%s'", buf);
260
            return NULL;
261
        }
262
    }
263
    max_devs = if_max_devs[type];
264

    
265
    if (cyls || heads || secs) {
266
        if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
267
            error_report("invalid physical cyls number");
268
            return NULL;
269
        }
270
        if (heads < 1 || (type == IF_IDE && heads > 16)) {
271
            error_report("invalid physical heads number");
272
            return NULL;
273
        }
274
        if (secs < 1 || (type == IF_IDE && secs > 63)) {
275
            error_report("invalid physical secs number");
276
            return NULL;
277
        }
278
    }
279

    
280
    if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
281
        if (!cyls) {
282
            error_report("'%s' trans must be used with cyls,heads and secs",
283
                         buf);
284
            return NULL;
285
        }
286
        if (!strcmp(buf, "none"))
287
            translation = BIOS_ATA_TRANSLATION_NONE;
288
        else if (!strcmp(buf, "lba"))
289
            translation = BIOS_ATA_TRANSLATION_LBA;
290
        else if (!strcmp(buf, "auto"))
291
            translation = BIOS_ATA_TRANSLATION_AUTO;
292
        else {
293
            error_report("'%s' invalid translation type", buf);
294
            return NULL;
295
        }
296
    }
297

    
298
    if ((buf = qemu_opt_get(opts, "media")) != NULL) {
299
        if (!strcmp(buf, "disk")) {
300
            media = MEDIA_DISK;
301
        } else if (!strcmp(buf, "cdrom")) {
302
            if (cyls || secs || heads) {
303
                error_report("'%s' invalid physical CHS format", buf);
304
                return NULL;
305
            }
306
            media = MEDIA_CDROM;
307
        } else {
308
            error_report("'%s' invalid media", buf);
309
            return NULL;
310
        }
311
    }
312

    
313
    if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
314
        if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
315
            bdrv_flags |= BDRV_O_NOCACHE;
316
        } else if (!strcmp(buf, "writeback")) {
317
            bdrv_flags |= BDRV_O_CACHE_WB;
318
        } else if (!strcmp(buf, "unsafe")) {
319
            bdrv_flags |= BDRV_O_CACHE_WB;
320
            bdrv_flags |= BDRV_O_NO_FLUSH;
321
        } else if (!strcmp(buf, "writethrough")) {
322
            /* this is the default */
323
        } else {
324
           error_report("invalid cache option");
325
           return NULL;
326
        }
327
    }
328

    
329
#ifdef CONFIG_LINUX_AIO
330
    if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
331
        if (!strcmp(buf, "native")) {
332
            bdrv_flags |= BDRV_O_NATIVE_AIO;
333
        } else if (!strcmp(buf, "threads")) {
334
            /* this is the default */
335
        } else {
336
           error_report("invalid aio option");
337
           return NULL;
338
        }
339
    }
340
#endif
341

    
342
    if ((buf = qemu_opt_get(opts, "format")) != NULL) {
343
       if (strcmp(buf, "?") == 0) {
344
           error_printf("Supported formats:");
345
           bdrv_iterate_format(bdrv_format_print, NULL);
346
           error_printf("\n");
347
           return NULL;
348
        }
349
        drv = bdrv_find_whitelisted_format(buf);
350
        if (!drv) {
351
            error_report("'%s' invalid format", buf);
352
            return NULL;
353
        }
354
    }
355

    
356
    on_write_error = BLOCK_ERR_STOP_ENOSPC;
357
    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
358
        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
359
            error_report("werror is not supported by this bus type");
360
            return NULL;
361
        }
362

    
363
        on_write_error = parse_block_error_action(buf, 0);
364
        if (on_write_error < 0) {
365
            return NULL;
366
        }
367
    }
368

    
369
    on_read_error = BLOCK_ERR_REPORT;
370
    if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
371
        if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
372
            error_report("rerror is not supported by this bus type");
373
            return NULL;
374
        }
375

    
376
        on_read_error = parse_block_error_action(buf, 1);
377
        if (on_read_error < 0) {
378
            return NULL;
379
        }
380
    }
381

    
382
    if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
383
        if (type != IF_VIRTIO) {
384
            error_report("addr is not supported by this bus type");
385
            return NULL;
386
        }
387
    }
388

    
389
    /* compute bus and unit according index */
390

    
391
    if (index != -1) {
392
        if (bus_id != 0 || unit_id != -1) {
393
            error_report("index cannot be used with bus and unit");
394
            return NULL;
395
        }
396
        bus_id = drive_index_to_bus_id(type, index);
397
        unit_id = drive_index_to_unit_id(type, index);
398
    }
399

    
400
    /* if user doesn't specify a unit_id,
401
     * try to find the first free
402
     */
403

    
404
    if (unit_id == -1) {
405
       unit_id = 0;
406
       while (drive_get(type, bus_id, unit_id) != NULL) {
407
           unit_id++;
408
           if (max_devs && unit_id >= max_devs) {
409
               unit_id -= max_devs;
410
               bus_id++;
411
           }
412
       }
413
    }
414

    
415
    /* check unit id */
416

    
417
    if (max_devs && unit_id >= max_devs) {
418
        error_report("unit %d too big (max is %d)",
419
                     unit_id, max_devs - 1);
420
        return NULL;
421
    }
422

    
423
    /*
424
     * catch multiple definitions
425
     */
426

    
427
    if (drive_get(type, bus_id, unit_id) != NULL) {
428
        error_report("drive with bus=%d, unit=%d (index=%d) exists",
429
                     bus_id, unit_id, index);
430
        return NULL;
431
    }
432

    
433
    /* init */
434

    
435
    dinfo = qemu_mallocz(sizeof(*dinfo));
436
    if ((buf = qemu_opts_id(opts)) != NULL) {
437
        dinfo->id = qemu_strdup(buf);
438
    } else {
439
        /* no id supplied -> create one */
440
        dinfo->id = qemu_mallocz(32);
441
        if (type == IF_IDE || type == IF_SCSI)
442
            mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
443
        if (max_devs)
444
            snprintf(dinfo->id, 32, "%s%i%s%i",
445
                     devname, bus_id, mediastr, unit_id);
446
        else
447
            snprintf(dinfo->id, 32, "%s%s%i",
448
                     devname, mediastr, unit_id);
449
    }
450
    dinfo->bdrv = bdrv_new(dinfo->id);
451
    dinfo->devaddr = devaddr;
452
    dinfo->type = type;
453
    dinfo->bus = bus_id;
454
    dinfo->unit = unit_id;
455
    dinfo->opts = opts;
456
    if (serial)
457
        strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
458
    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
459

    
460
    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
461

    
462
    switch(type) {
463
    case IF_IDE:
464
    case IF_SCSI:
465
    case IF_XEN:
466
    case IF_NONE:
467
        switch(media) {
468
        case MEDIA_DISK:
469
            if (cyls != 0) {
470
                bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
471
                bdrv_set_translation_hint(dinfo->bdrv, translation);
472
            }
473
            break;
474
        case MEDIA_CDROM:
475
            bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
476
            break;
477
        }
478
        break;
479
    case IF_SD:
480
        /* FIXME: This isn't really a floppy, but it's a reasonable
481
           approximation.  */
482
    case IF_FLOPPY:
483
        bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
484
        break;
485
    case IF_PFLASH:
486
    case IF_MTD:
487
        break;
488
    case IF_VIRTIO:
489
        /* add virtio block device */
490
        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
491
        qemu_opt_set(opts, "driver", "virtio-blk-pci");
492
        qemu_opt_set(opts, "drive", dinfo->id);
493
        if (devaddr)
494
            qemu_opt_set(opts, "addr", devaddr);
495
        break;
496
    default:
497
        abort();
498
    }
499
    if (!file || !*file) {
500
        return dinfo;
501
    }
502
    if (snapshot) {
503
        /* always use cache=unsafe with snapshot */
504
        bdrv_flags &= ~BDRV_O_CACHE_MASK;
505
        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
506
    }
507

    
508
    if (media == MEDIA_CDROM) {
509
        /* CDROM is fine for any interface, don't check.  */
510
        ro = 1;
511
    } else if (ro == 1) {
512
        if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
513
            error_report("readonly not supported by this bus type");
514
            return NULL;
515
        }
516
    }
517

    
518
    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
519

    
520
    ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
521
    if (ret < 0) {
522
        error_report("could not open disk image %s: %s",
523
                     file, strerror(-ret));
524
        return NULL;
525
    }
526

    
527
    if (bdrv_key_required(dinfo->bdrv))
528
        autostart = 0;
529
    return dinfo;
530
}
531

    
532
void do_commit(Monitor *mon, const QDict *qdict)
533
{
534
    const char *device = qdict_get_str(qdict, "device");
535
    BlockDriverState *bs;
536

    
537
    if (!strcmp(device, "all")) {
538
        bdrv_commit_all();
539
    } else {
540
        bs = bdrv_find(device);
541
        if (!bs) {
542
            qerror_report(QERR_DEVICE_NOT_FOUND, device);
543
            return;
544
        }
545
        bdrv_commit(bs);
546
    }
547
}
548

    
549
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
550
{
551
    const char *device = qdict_get_str(qdict, "device");
552
    const char *filename = qdict_get_try_str(qdict, "snapshot_file");
553
    const char *format = qdict_get_try_str(qdict, "format");
554
    BlockDriverState *bs;
555
    BlockDriver *drv, *proto_drv;
556
    int ret = 0;
557
    int flags;
558

    
559
    if (!filename) {
560
        qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
561
        ret = -1;
562
        goto out;
563
    }
564

    
565
    bs = bdrv_find(device);
566
    if (!bs) {
567
        qerror_report(QERR_DEVICE_NOT_FOUND, device);
568
        ret = -1;
569
        goto out;
570
    }
571

    
572
    if (!format) {
573
        format = "qcow2";
574
    }
575

    
576
    drv = bdrv_find_format(format);
577
    if (!drv) {
578
        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
579
        ret = -1;
580
        goto out;
581
    }
582

    
583
    proto_drv = bdrv_find_protocol(filename);
584
    if (!proto_drv) {
585
        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
586
        ret = -1;
587
        goto out;
588
    }
589

    
590
    ret = bdrv_img_create(filename, format, bs->filename,
591
                          bs->drv->format_name, NULL, -1, bs->open_flags);
592
    if (ret) {
593
        goto out;
594
    }
595

    
596
    qemu_aio_flush();
597
    bdrv_flush(bs);
598

    
599
    flags = bs->open_flags;
600
    bdrv_close(bs);
601
    ret = bdrv_open(bs, filename, flags, drv);
602
    /*
603
     * If reopening the image file we just created fails, we really
604
     * are in trouble :(
605
     */
606
    if (ret != 0) {
607
        abort();
608
    }
609
out:
610
    if (ret) {
611
        ret = -1;
612
    }
613

    
614
    return ret;
615
}
616

    
617
static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
618
{
619
    if (!force) {
620
        if (!bdrv_is_removable(bs)) {
621
            qerror_report(QERR_DEVICE_NOT_REMOVABLE,
622
                           bdrv_get_device_name(bs));
623
            return -1;
624
        }
625
        if (bdrv_is_locked(bs)) {
626
            qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
627
            return -1;
628
        }
629
    }
630
    bdrv_close(bs);
631
    return 0;
632
}
633

    
634
int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
635
{
636
    BlockDriverState *bs;
637
    int force = qdict_get_try_bool(qdict, "force", 0);
638
    const char *filename = qdict_get_str(qdict, "device");
639

    
640
    bs = bdrv_find(filename);
641
    if (!bs) {
642
        qerror_report(QERR_DEVICE_NOT_FOUND, filename);
643
        return -1;
644
    }
645
    return eject_device(mon, bs, force);
646
}
647

    
648
int do_block_set_passwd(Monitor *mon, const QDict *qdict,
649
                        QObject **ret_data)
650
{
651
    BlockDriverState *bs;
652
    int err;
653

    
654
    bs = bdrv_find(qdict_get_str(qdict, "device"));
655
    if (!bs) {
656
        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
657
        return -1;
658
    }
659

    
660
    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
661
    if (err == -EINVAL) {
662
        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
663
        return -1;
664
    } else if (err < 0) {
665
        qerror_report(QERR_INVALID_PASSWORD);
666
        return -1;
667
    }
668

    
669
    return 0;
670
}
671

    
672
int do_change_block(Monitor *mon, const char *device,
673
                    const char *filename, const char *fmt)
674
{
675
    BlockDriverState *bs;
676
    BlockDriver *drv = NULL;
677
    int bdrv_flags;
678

    
679
    bs = bdrv_find(device);
680
    if (!bs) {
681
        qerror_report(QERR_DEVICE_NOT_FOUND, device);
682
        return -1;
683
    }
684
    if (fmt) {
685
        drv = bdrv_find_whitelisted_format(fmt);
686
        if (!drv) {
687
            qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
688
            return -1;
689
        }
690
    }
691
    if (eject_device(mon, bs, 0) < 0) {
692
        return -1;
693
    }
694
    bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
695
    bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
696
    if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
697
        qerror_report(QERR_OPEN_FILE_FAILED, filename);
698
        return -1;
699
    }
700
    return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
701
}
702

    
703
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
704
{
705
    const char *id = qdict_get_str(qdict, "id");
706
    BlockDriverState *bs;
707
    BlockDriverState **ptr;
708
    Property *prop;
709

    
710
    bs = bdrv_find(id);
711
    if (!bs) {
712
        qerror_report(QERR_DEVICE_NOT_FOUND, id);
713
        return -1;
714
    }
715

    
716
    /* quiesce block driver; prevent further io */
717
    qemu_aio_flush();
718
    bdrv_flush(bs);
719
    bdrv_close(bs);
720

    
721
    /* clean up guest state from pointing to host resource by
722
     * finding and removing DeviceState "drive" property */
723
    if (bs->peer) {
724
        for (prop = bs->peer->info->props; prop && prop->name; prop++) {
725
            if (prop->info->type == PROP_TYPE_DRIVE) {
726
                ptr = qdev_get_prop_ptr(bs->peer, prop);
727
                if (*ptr == bs) {
728
                    bdrv_detach(bs, bs->peer);
729
                    *ptr = NULL;
730
                    break;
731
                }
732
            }
733
        }
734
    }
735

    
736
    /* clean up host side */
737
    drive_uninit(drive_get_by_blockdev(bs));
738

    
739
    return 0;
740
}
741

    
742
/*
743
 * XXX: replace the QERR_UNDEFINED_ERROR errors with real values once the
744
 * existing QERR_ macro mess is cleaned up.  A good example for better
745
 * error reports can be found in the qemu-img resize code.
746
 */
747
int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
748
{
749
    const char *device = qdict_get_str(qdict, "device");
750
    int64_t size = qdict_get_int(qdict, "size");
751
    BlockDriverState *bs;
752

    
753
    bs = bdrv_find(device);
754
    if (!bs) {
755
        qerror_report(QERR_DEVICE_NOT_FOUND, device);
756
        return -1;
757
    }
758

    
759
    if (size < 0) {
760
        qerror_report(QERR_UNDEFINED_ERROR);
761
        return -1;
762
    }
763

    
764
    if (bdrv_truncate(bs, size)) {
765
        qerror_report(QERR_UNDEFINED_ERROR);
766
        return -1;
767
    }
768

    
769
    return 0;
770
}