Revision 6cc2a415

b/blockdev.c
649 649
    }
650 650
}
651 651

  
652
static void blockdev_do_action(int kind, void *data, Error **errp)
653
{
654
    BlockdevAction action;
655
    BlockdevActionList list;
656

  
657
    action.kind = kind;
658
    action.data = data;
659
    list.value = &action;
660
    list.next = NULL;
661
    qmp_transaction(&list, errp);
662
}
663

  
652 664
void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
653 665
                                bool has_format, const char *format,
666
                                bool has_mode, enum NewImageMode mode,
654 667
                                Error **errp)
655 668
{
656
    BlockDriverState *bs;
657
    BlockDriver *drv, *old_drv, *proto_drv;
658
    int ret = 0;
659
    int flags;
660
    char old_filename[1024];
661

  
662
    bs = bdrv_find(device);
663
    if (!bs) {
664
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
665
        return;
666
    }
667
    if (bdrv_in_use(bs)) {
668
        error_set(errp, QERR_DEVICE_IN_USE, device);
669
        return;
670
    }
671

  
672
    pstrcpy(old_filename, sizeof(old_filename), bs->filename);
673

  
674
    old_drv = bs->drv;
675
    flags = bs->open_flags;
676

  
677
    if (!has_format) {
678
        format = "qcow2";
679
    }
680

  
681
    drv = bdrv_find_format(format);
682
    if (!drv) {
683
        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
684
        return;
685
    }
686

  
687
    proto_drv = bdrv_find_protocol(snapshot_file);
688
    if (!proto_drv) {
689
        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
690
        return;
691
    }
692

  
693
    ret = bdrv_img_create(snapshot_file, format, bs->filename,
694
                          bs->drv->format_name, NULL, -1, flags);
695
    if (ret) {
696
        error_set(errp, QERR_UNDEFINED_ERROR);
697
        return;
698
    }
699

  
700
    bdrv_drain_all();
701
    bdrv_flush(bs);
702

  
703
    bdrv_close(bs);
704
    ret = bdrv_open(bs, snapshot_file, flags, drv);
705
    /*
706
     * If reopening the image file we just created fails, fall back
707
     * and try to re-open the original image. If that fails too, we
708
     * are in serious trouble.
709
     */
710
    if (ret != 0) {
711
        ret = bdrv_open(bs, old_filename, flags, old_drv);
712
        if (ret != 0) {
713
            error_set(errp, QERR_OPEN_FILE_FAILED, old_filename);
714
        } else {
715
            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
716
        }
717
    }
669
    BlockdevSnapshot snapshot = {
670
        .device = (char *) device,
671
        .snapshot_file = (char *) snapshot_file,
672
        .has_format = has_format,
673
        .format = (char *) format,
674
        .has_mode = has_mode,
675
        .mode = mode,
676
    };
677
    blockdev_do_action(BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, &snapshot,
678
                       errp);
718 679
}
719 680

  
720 681

  
b/hmp-commands.hx
882 882

  
883 883
    {
884 884
        .name       = "snapshot_blkdev",
885
        .args_type  = "device:B,snapshot-file:s?,format:s?",
886
        .params     = "device [new-image-file] [format]",
885
        .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
886
        .params     = "[-n] device [new-image-file] [format]",
887 887
        .help       = "initiates a live snapshot\n\t\t\t"
888 888
                      "of device. If a new image file is specified, the\n\t\t\t"
889 889
                      "new image file will become the new root image.\n\t\t\t"
890 890
                      "If format is specified, the snapshot file will\n\t\t\t"
891 891
                      "be created in that format. Otherwise the\n\t\t\t"
892
                      "snapshot will be internal! (currently unsupported)",
892
                      "snapshot will be internal! (currently unsupported).\n\t\t\t"
893
                      "The default format is qcow2.  The -n flag requests QEMU\n\t\t\t"
894
                      "to reuse the image found in new-image-file, instead of\n\t\t\t"
895
                      "recreating it from scratch.",
893 896
        .mhandler.cmd = hmp_snapshot_blkdev,
894 897
    },
895 898

  
b/hmp.c
692 692
    const char *device = qdict_get_str(qdict, "device");
693 693
    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
694 694
    const char *format = qdict_get_try_str(qdict, "format");
695
    int reuse = qdict_get_try_bool(qdict, "reuse", 0);
696
    enum NewImageMode mode;
695 697
    Error *errp = NULL;
696 698

  
697 699
    if (!filename) {
......
702 704
        return;
703 705
    }
704 706

  
705
    qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
707
    mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
708
    qmp_blockdev_snapshot_sync(device, filename, !!format, format,
709
                               true, mode, &errp);
706 710
    hmp_handle_error(mon, &errp);
707 711
}
708 712

  
b/qapi-schema.json
1141 1141
# @snapshot-file: the target of the new image. A new file will be created.
1142 1142
#
1143 1143
# @format: #optional the format of the snapshot image, default is 'qcow2'.
1144
#
1145
# @mode: #optional whether and how QEMU should create a new image, default is
1146
# 'absolute-paths'.
1144 1147
##
1145 1148
{ 'type': 'BlockdevSnapshot',
1146 1149
  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
......
1197 1200
#
1198 1201
# @format: #optional the format of the snapshot image, default is 'qcow2'.
1199 1202
#
1203
# @mode: #optional whether and how QEMU should create a new image, default is
1204
# 'absolute-paths'.
1205
#
1200 1206
# Returns: nothing on success
1201 1207
#          If @device is not a valid block device, DeviceNotFound
1202 1208
#          If @snapshot-file can't be opened, OpenFileFailed
1203 1209
#          If @format is invalid, InvalidBlockFormat
1204 1210
#
1205
# Notes: One of the last steps taken by this command is to close the current
1206
#        image being used by @device and open the @snapshot-file one. If that
1207
#        fails, the command will try to reopen the original image file. If
1208
#        that also fails OpenFileFailed will be returned and the guest may get
1209
#        unexpected errors.
1210
#
1211 1211
# Since 0.14.0
1212 1212
##
1213 1213
{ 'command': 'blockdev-snapshot-sync',
1214
  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
1214
  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
1215
            '*mode': 'NewImageMode'} }
1215 1216

  
1216 1217
##
1217 1218
# @human-monitor-command:
b/qmp-commands.hx
760 760

  
761 761
- "device": device name to snapshot (json-string)
762 762
- "snapshot-file": name of new image file (json-string)
763
- "mode": whether and how QEMU should create the snapshot file
764
  (NewImageMode, optional, default "absolute-paths")
763 765
- "format": format of new image (json-string, optional)
764 766

  
765 767
Example:

Also available in: Unified diff