Statistics
| Branch: | Revision:

root / blockdev.c @ 904ebffe

History | View | Annotate | Download (19.4 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
/*
23
 * We automatically delete the drive when a device using it gets
24
 * unplugged.  Questionable feature, but we can't just drop it.
25
 * Device models call blockdev_mark_auto_del() to schedule the
26
 * automatic deletion, and generic qdev code calls blockdev_auto_del()
27
 * when deletion is actually safe.
28
 */
29
void blockdev_mark_auto_del(BlockDriverState *bs)
30
{
31
    DriveInfo *dinfo = drive_get_by_blockdev(bs);
32

    
33
    if (dinfo) {
34
        dinfo->auto_del = 1;
35
    }
36
}
37

    
38
void blockdev_auto_del(BlockDriverState *bs)
39
{
40
    DriveInfo *dinfo = drive_get_by_blockdev(bs);
41

    
42
    if (dinfo && dinfo->auto_del) {
43
        drive_uninit(dinfo);
44
    }
45
}
46

    
47
QemuOpts *drive_add(const char *file, const char *fmt, ...)
48
{
49
    va_list ap;
50
    char optstr[1024];
51
    QemuOpts *opts;
52

    
53
    va_start(ap, fmt);
54
    vsnprintf(optstr, sizeof(optstr), fmt, ap);
55
    va_end(ap);
56

    
57
    opts = qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
58
    if (!opts) {
59
        return NULL;
60
    }
61
    if (file)
62
        qemu_opt_set(opts, "file", file);
63
    return opts;
64
}
65

    
66
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
67
{
68
    DriveInfo *dinfo;
69

    
70
    /* seek interface, bus and unit */
71

    
72
    QTAILQ_FOREACH(dinfo, &drives, next) {
73
        if (dinfo->type == type &&
74
            dinfo->bus == bus &&
75
            dinfo->unit == unit)
76
            return dinfo;
77
    }
78

    
79
    return NULL;
80
}
81

    
82
int drive_get_max_bus(BlockInterfaceType type)
83
{
84
    int max_bus;
85
    DriveInfo *dinfo;
86

    
87
    max_bus = -1;
88
    QTAILQ_FOREACH(dinfo, &drives, next) {
89
        if(dinfo->type == type &&
90
           dinfo->bus > max_bus)
91
            max_bus = dinfo->bus;
92
    }
93
    return max_bus;
94
}
95

    
96
/* Get a block device.  This should only be used for single-drive devices
97
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
98
   appropriate bus.  */
99
DriveInfo *drive_get_next(BlockInterfaceType type)
100
{
101
    static int next_block_unit[IF_COUNT];
102

    
103
    return drive_get(type, 0, next_block_unit[type]++);
104
}
105

    
106
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
107
{
108
    DriveInfo *dinfo;
109

    
110
    QTAILQ_FOREACH(dinfo, &drives, next) {
111
        if (dinfo->bdrv == bs) {
112
            return dinfo;
113
        }
114
    }
115
    return NULL;
116
}
117

    
118
static void bdrv_format_print(void *opaque, const char *name)
119
{
120
    error_printf(" %s", name);
121
}
122

    
123
void drive_uninit(DriveInfo *dinfo)
124
{
125
    qemu_opts_del(dinfo->opts);
126
    bdrv_delete(dinfo->bdrv);
127
    QTAILQ_REMOVE(&drives, dinfo, next);
128
    qemu_free(dinfo);
129
}
130

    
131
static int parse_block_error_action(const char *buf, int is_read)
132
{
133
    if (!strcmp(buf, "ignore")) {
134
        return BLOCK_ERR_IGNORE;
135
    } else if (!is_read && !strcmp(buf, "enospc")) {
136
        return BLOCK_ERR_STOP_ENOSPC;
137
    } else if (!strcmp(buf, "stop")) {
138
        return BLOCK_ERR_STOP_ANY;
139
    } else if (!strcmp(buf, "report")) {
140
        return BLOCK_ERR_REPORT;
141
    } else {
142
        error_report("'%s' invalid %s error action",
143
                     buf, is_read ? "read" : "write");
144
        return -1;
145
    }
146
}
147

    
148
DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
149
{
150
    const char *buf;
151
    const char *file = NULL;
152
    char devname[128];
153
    const char *serial;
154
    const char *mediastr = "";
155
    BlockInterfaceType type;
156
    enum { MEDIA_DISK, MEDIA_CDROM } media;
157
    int bus_id, unit_id;
158
    int cyls, heads, secs, translation;
159
    BlockDriver *drv = NULL;
160
    int max_devs;
161
    int index;
162
    int ro = 0;
163
    int bdrv_flags = 0;
164
    int on_read_error, on_write_error;
165
    const char *devaddr;
166
    DriveInfo *dinfo;
167
    int snapshot = 0;
168
    int ret;
169

    
170
    *fatal_error = 1;
171

    
172
    translation = BIOS_ATA_TRANSLATION_AUTO;
173

    
174
    if (default_to_scsi) {
175
        type = IF_SCSI;
176
        max_devs = MAX_SCSI_DEVS;
177
        pstrcpy(devname, sizeof(devname), "scsi");
178
    } else {
179
        type = IF_IDE;
180
        max_devs = MAX_IDE_DEVS;
181
        pstrcpy(devname, sizeof(devname), "ide");
182
    }
183
    media = MEDIA_DISK;
184

    
185
    /* extract parameters */
186
    bus_id  = qemu_opt_get_number(opts, "bus", 0);
187
    unit_id = qemu_opt_get_number(opts, "unit", -1);
188
    index   = qemu_opt_get_number(opts, "index", -1);
189

    
190
    cyls  = qemu_opt_get_number(opts, "cyls", 0);
191
    heads = qemu_opt_get_number(opts, "heads", 0);
192
    secs  = qemu_opt_get_number(opts, "secs", 0);
193

    
194
    snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
195
    ro = qemu_opt_get_bool(opts, "readonly", 0);
196

    
197
    file = qemu_opt_get(opts, "file");
198
    serial = qemu_opt_get(opts, "serial");
199

    
200
    if ((buf = qemu_opt_get(opts, "if")) != NULL) {
201
        pstrcpy(devname, sizeof(devname), buf);
202
        if (!strcmp(buf, "ide")) {
203
            type = IF_IDE;
204
            max_devs = MAX_IDE_DEVS;
205
        } else if (!strcmp(buf, "scsi")) {
206
            type = IF_SCSI;
207
            max_devs = MAX_SCSI_DEVS;
208
        } else if (!strcmp(buf, "floppy")) {
209
            type = IF_FLOPPY;
210
            max_devs = 0;
211
        } else if (!strcmp(buf, "pflash")) {
212
            type = IF_PFLASH;
213
            max_devs = 0;
214
        } else if (!strcmp(buf, "mtd")) {
215
            type = IF_MTD;
216
            max_devs = 0;
217
        } else if (!strcmp(buf, "sd")) {
218
            type = IF_SD;
219
            max_devs = 0;
220
        } else if (!strcmp(buf, "virtio")) {
221
            type = IF_VIRTIO;
222
            max_devs = 0;
223
        } else if (!strcmp(buf, "xen")) {
224
            type = IF_XEN;
225
            max_devs = 0;
226
        } else if (!strcmp(buf, "none")) {
227
            type = IF_NONE;
228
            max_devs = 0;
229
        } else {
230
            error_report("unsupported bus type '%s'", buf);
231
            return NULL;
232
        }
233
    }
234

    
235
    if (cyls || heads || secs) {
236
        if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
237
            error_report("invalid physical cyls number");
238
            return NULL;
239
        }
240
        if (heads < 1 || (type == IF_IDE && heads > 16)) {
241
            error_report("invalid physical heads number");
242
            return NULL;
243
        }
244
        if (secs < 1 || (type == IF_IDE && secs > 63)) {
245
            error_report("invalid physical secs number");
246
            return NULL;
247
        }
248
    }
249

    
250
    if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
251
        if (!cyls) {
252
            error_report("'%s' trans must be used with cyls,heads and secs",
253
                         buf);
254
            return NULL;
255
        }
256
        if (!strcmp(buf, "none"))
257
            translation = BIOS_ATA_TRANSLATION_NONE;
258
        else if (!strcmp(buf, "lba"))
259
            translation = BIOS_ATA_TRANSLATION_LBA;
260
        else if (!strcmp(buf, "auto"))
261
            translation = BIOS_ATA_TRANSLATION_AUTO;
262
        else {
263
            error_report("'%s' invalid translation type", buf);
264
            return NULL;
265
        }
266
    }
267

    
268
    if ((buf = qemu_opt_get(opts, "media")) != NULL) {
269
        if (!strcmp(buf, "disk")) {
270
            media = MEDIA_DISK;
271
        } else if (!strcmp(buf, "cdrom")) {
272
            if (cyls || secs || heads) {
273
                error_report("'%s' invalid physical CHS format", buf);
274
                return NULL;
275
            }
276
            media = MEDIA_CDROM;
277
        } else {
278
            error_report("'%s' invalid media", buf);
279
            return NULL;
280
        }
281
    }
282

    
283
    if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
284
        if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
285
            bdrv_flags |= BDRV_O_NOCACHE;
286
        } else if (!strcmp(buf, "writeback")) {
287
            bdrv_flags |= BDRV_O_CACHE_WB;
288
        } else if (!strcmp(buf, "unsafe")) {
289
            bdrv_flags |= BDRV_O_CACHE_WB;
290
            bdrv_flags |= BDRV_O_NO_FLUSH;
291
        } else if (!strcmp(buf, "writethrough")) {
292
            /* this is the default */
293
        } else {
294
           error_report("invalid cache option");
295
           return NULL;
296
        }
297
    }
298

    
299
#ifdef CONFIG_LINUX_AIO
300
    if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
301
        if (!strcmp(buf, "native")) {
302
            bdrv_flags |= BDRV_O_NATIVE_AIO;
303
        } else if (!strcmp(buf, "threads")) {
304
            /* this is the default */
305
        } else {
306
           error_report("invalid aio option");
307
           return NULL;
308
        }
309
    }
310
#endif
311

    
312
    if ((buf = qemu_opt_get(opts, "format")) != NULL) {
313
       if (strcmp(buf, "?") == 0) {
314
           error_printf("Supported formats:");
315
           bdrv_iterate_format(bdrv_format_print, NULL);
316
           error_printf("\n");
317
           return NULL;
318
        }
319
        drv = bdrv_find_whitelisted_format(buf);
320
        if (!drv) {
321
            error_report("'%s' invalid format", buf);
322
            return NULL;
323
        }
324
    }
325

    
326
    on_write_error = BLOCK_ERR_STOP_ENOSPC;
327
    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
328
        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
329
            error_report("werror is not supported by this bus type");
330
            return NULL;
331
        }
332

    
333
        on_write_error = parse_block_error_action(buf, 0);
334
        if (on_write_error < 0) {
335
            return NULL;
336
        }
337
    }
338

    
339
    on_read_error = BLOCK_ERR_REPORT;
340
    if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
341
        if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
342
            error_report("rerror is not supported by this bus type");
343
            return NULL;
344
        }
345

    
346
        on_read_error = parse_block_error_action(buf, 1);
347
        if (on_read_error < 0) {
348
            return NULL;
349
        }
350
    }
351

    
352
    if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
353
        if (type != IF_VIRTIO) {
354
            error_report("addr is not supported by this bus type");
355
            return NULL;
356
        }
357
    }
358

    
359
    /* compute bus and unit according index */
360

    
361
    if (index != -1) {
362
        if (bus_id != 0 || unit_id != -1) {
363
            error_report("index cannot be used with bus and unit");
364
            return NULL;
365
        }
366
        if (max_devs == 0)
367
        {
368
            unit_id = index;
369
            bus_id = 0;
370
        } else {
371
            unit_id = index % max_devs;
372
            bus_id = index / max_devs;
373
        }
374
    }
375

    
376
    /* if user doesn't specify a unit_id,
377
     * try to find the first free
378
     */
379

    
380
    if (unit_id == -1) {
381
       unit_id = 0;
382
       while (drive_get(type, bus_id, unit_id) != NULL) {
383
           unit_id++;
384
           if (max_devs && unit_id >= max_devs) {
385
               unit_id -= max_devs;
386
               bus_id++;
387
           }
388
       }
389
    }
390

    
391
    /* check unit id */
392

    
393
    if (max_devs && unit_id >= max_devs) {
394
        error_report("unit %d too big (max is %d)",
395
                     unit_id, max_devs - 1);
396
        return NULL;
397
    }
398

    
399
    /*
400
     * ignore multiple definitions
401
     */
402

    
403
    if (drive_get(type, bus_id, unit_id) != NULL) {
404
        *fatal_error = 0;
405
        return NULL;
406
    }
407

    
408
    /* init */
409

    
410
    dinfo = qemu_mallocz(sizeof(*dinfo));
411
    if ((buf = qemu_opts_id(opts)) != NULL) {
412
        dinfo->id = qemu_strdup(buf);
413
    } else {
414
        /* no id supplied -> create one */
415
        dinfo->id = qemu_mallocz(32);
416
        if (type == IF_IDE || type == IF_SCSI)
417
            mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
418
        if (max_devs)
419
            snprintf(dinfo->id, 32, "%s%i%s%i",
420
                     devname, bus_id, mediastr, unit_id);
421
        else
422
            snprintf(dinfo->id, 32, "%s%s%i",
423
                     devname, mediastr, unit_id);
424
    }
425
    dinfo->bdrv = bdrv_new(dinfo->id);
426
    dinfo->devaddr = devaddr;
427
    dinfo->type = type;
428
    dinfo->bus = bus_id;
429
    dinfo->unit = unit_id;
430
    dinfo->opts = opts;
431
    if (serial)
432
        strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
433
    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
434

    
435
    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
436

    
437
    switch(type) {
438
    case IF_IDE:
439
    case IF_SCSI:
440
    case IF_XEN:
441
    case IF_NONE:
442
        switch(media) {
443
        case MEDIA_DISK:
444
            if (cyls != 0) {
445
                bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
446
                bdrv_set_translation_hint(dinfo->bdrv, translation);
447
            }
448
            break;
449
        case MEDIA_CDROM:
450
            bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
451
            break;
452
        }
453
        break;
454
    case IF_SD:
455
        /* FIXME: This isn't really a floppy, but it's a reasonable
456
           approximation.  */
457
    case IF_FLOPPY:
458
        bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
459
        break;
460
    case IF_PFLASH:
461
    case IF_MTD:
462
        break;
463
    case IF_VIRTIO:
464
        /* add virtio block device */
465
        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
466
        qemu_opt_set(opts, "driver", "virtio-blk-pci");
467
        qemu_opt_set(opts, "drive", dinfo->id);
468
        if (devaddr)
469
            qemu_opt_set(opts, "addr", devaddr);
470
        break;
471
    case IF_COUNT:
472
        abort();
473
    }
474
    if (!file || !*file) {
475
        *fatal_error = 0;
476
        return NULL;
477
    }
478
    if (snapshot) {
479
        /* always use cache=unsafe with snapshot */
480
        bdrv_flags &= ~BDRV_O_CACHE_MASK;
481
        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
482
    }
483

    
484
    if (media == MEDIA_CDROM) {
485
        /* CDROM is fine for any interface, don't check.  */
486
        ro = 1;
487
    } else if (ro == 1) {
488
        if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
489
            error_report("readonly not supported by this bus type");
490
            return NULL;
491
        }
492
    }
493

    
494
    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
495

    
496
    ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
497
    if (ret < 0) {
498
        error_report("could not open disk image %s: %s",
499
                     file, strerror(-ret));
500
        return NULL;
501
    }
502

    
503
    if (bdrv_key_required(dinfo->bdrv))
504
        autostart = 0;
505
    *fatal_error = 0;
506
    return dinfo;
507
}
508

    
509
void do_commit(Monitor *mon, const QDict *qdict)
510
{
511
    const char *device = qdict_get_str(qdict, "device");
512
    BlockDriverState *bs;
513

    
514
    if (!strcmp(device, "all")) {
515
        bdrv_commit_all();
516
    } else {
517
        bs = bdrv_find(device);
518
        if (!bs) {
519
            qerror_report(QERR_DEVICE_NOT_FOUND, device);
520
            return;
521
        }
522
        bdrv_commit(bs);
523
    }
524
}
525

    
526
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
527
{
528
    const char *device = qdict_get_str(qdict, "device");
529
    const char *filename = qdict_get_try_str(qdict, "snapshot_file");
530
    const char *format = qdict_get_try_str(qdict, "format");
531
    BlockDriverState *bs;
532
    BlockDriver *drv, *proto_drv;
533
    int ret = 0;
534
    int flags;
535

    
536
    if (!filename) {
537
        qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
538
        ret = -1;
539
        goto out;
540
    }
541

    
542
    bs = bdrv_find(device);
543
    if (!bs) {
544
        qerror_report(QERR_DEVICE_NOT_FOUND, device);
545
        ret = -1;
546
        goto out;
547
    }
548

    
549
    if (!format) {
550
        format = "qcow2";
551
    }
552

    
553
    drv = bdrv_find_format(format);
554
    if (!drv) {
555
        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
556
        ret = -1;
557
        goto out;
558
    }
559

    
560
    proto_drv = bdrv_find_protocol(filename);
561
    if (!proto_drv) {
562
        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
563
        ret = -1;
564
        goto out;
565
    }
566

    
567
    ret = bdrv_img_create(filename, format, bs->filename,
568
                          bs->drv->format_name, NULL, -1, bs->open_flags);
569
    if (ret) {
570
        goto out;
571
    }
572

    
573
    qemu_aio_flush();
574
    bdrv_flush(bs);
575

    
576
    flags = bs->open_flags;
577
    bdrv_close(bs);
578
    ret = bdrv_open(bs, filename, flags, drv);
579
    /*
580
     * If reopening the image file we just created fails, we really
581
     * are in trouble :(
582
     */
583
    if (ret != 0) {
584
        abort();
585
    }
586
out:
587
    if (ret) {
588
        ret = -1;
589
    }
590

    
591
    return ret;
592
}
593

    
594
static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
595
{
596
    if (!force) {
597
        if (!bdrv_is_removable(bs)) {
598
            qerror_report(QERR_DEVICE_NOT_REMOVABLE,
599
                           bdrv_get_device_name(bs));
600
            return -1;
601
        }
602
        if (bdrv_is_locked(bs)) {
603
            qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
604
            return -1;
605
        }
606
    }
607
    bdrv_close(bs);
608
    return 0;
609
}
610

    
611
int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
612
{
613
    BlockDriverState *bs;
614
    int force = qdict_get_try_bool(qdict, "force", 0);
615
    const char *filename = qdict_get_str(qdict, "device");
616

    
617
    bs = bdrv_find(filename);
618
    if (!bs) {
619
        qerror_report(QERR_DEVICE_NOT_FOUND, filename);
620
        return -1;
621
    }
622
    return eject_device(mon, bs, force);
623
}
624

    
625
int do_block_set_passwd(Monitor *mon, const QDict *qdict,
626
                        QObject **ret_data)
627
{
628
    BlockDriverState *bs;
629
    int err;
630

    
631
    bs = bdrv_find(qdict_get_str(qdict, "device"));
632
    if (!bs) {
633
        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
634
        return -1;
635
    }
636

    
637
    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
638
    if (err == -EINVAL) {
639
        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
640
        return -1;
641
    } else if (err < 0) {
642
        qerror_report(QERR_INVALID_PASSWORD);
643
        return -1;
644
    }
645

    
646
    return 0;
647
}
648

    
649
int do_change_block(Monitor *mon, const char *device,
650
                    const char *filename, const char *fmt)
651
{
652
    BlockDriverState *bs;
653
    BlockDriver *drv = NULL;
654
    int bdrv_flags;
655

    
656
    bs = bdrv_find(device);
657
    if (!bs) {
658
        qerror_report(QERR_DEVICE_NOT_FOUND, device);
659
        return -1;
660
    }
661
    if (fmt) {
662
        drv = bdrv_find_whitelisted_format(fmt);
663
        if (!drv) {
664
            qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
665
            return -1;
666
        }
667
    }
668
    if (eject_device(mon, bs, 0) < 0) {
669
        return -1;
670
    }
671
    bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
672
    bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
673
    if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
674
        qerror_report(QERR_OPEN_FILE_FAILED, filename);
675
        return -1;
676
    }
677
    return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
678
}
679

    
680
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
681
{
682
    const char *id = qdict_get_str(qdict, "id");
683
    BlockDriverState *bs;
684
    BlockDriverState **ptr;
685
    Property *prop;
686

    
687
    bs = bdrv_find(id);
688
    if (!bs) {
689
        qerror_report(QERR_DEVICE_NOT_FOUND, id);
690
        return -1;
691
    }
692

    
693
    /* quiesce block driver; prevent further io */
694
    qemu_aio_flush();
695
    bdrv_flush(bs);
696
    bdrv_close(bs);
697

    
698
    /* clean up guest state from pointing to host resource by
699
     * finding and removing DeviceState "drive" property */
700
    if (bs->peer) {
701
        for (prop = bs->peer->info->props; prop && prop->name; prop++) {
702
            if (prop->info->type == PROP_TYPE_DRIVE) {
703
                ptr = qdev_get_prop_ptr(bs->peer, prop);
704
                if (*ptr == bs) {
705
                    bdrv_detach(bs, bs->peer);
706
                    *ptr = NULL;
707
                    break;
708
                }
709
            }
710
        }
711
    }
712

    
713
    /* clean up host side */
714
    drive_uninit(drive_get_by_blockdev(bs));
715

    
716
    return 0;
717
}
718

    
719
/*
720
 * XXX: replace the QERR_UNDEFINED_ERROR errors with real values once the
721
 * existing QERR_ macro mess is cleaned up.  A good example for better
722
 * error reports can be found in the qemu-img resize code.
723
 */
724
int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
725
{
726
    const char *device = qdict_get_str(qdict, "device");
727
    int64_t size = qdict_get_int(qdict, "size");
728
    BlockDriverState *bs;
729

    
730
    bs = bdrv_find(device);
731
    if (!bs) {
732
        qerror_report(QERR_DEVICE_NOT_FOUND, device);
733
        return -1;
734
    }
735

    
736
    if (size < 0) {
737
        qerror_report(QERR_UNDEFINED_ERROR);
738
        return -1;
739
    }
740

    
741
    if (bdrv_truncate(bs, size)) {
742
        qerror_report(QERR_UNDEFINED_ERROR);
743
        return -1;
744
    }
745

    
746
    return 0;
747
}