[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH 3/4] qmp: Add "snapshot=" option to nbd-server-a
From: |
Fam Zheng |
Subject: |
[Qemu-devel] [RFC PATCH 3/4] qmp: Add "snapshot=" option to nbd-server-add |
Date: |
Mon, 29 Jul 2013 12:25:31 +0800 |
With drive-backup block job, we can have a point-in-time snapshot of a
device. With snapshot=on, a backup block job is started on the device to
do CoW to a temporary image and this image is exported to nbd. The image
is deleted after nbd server stops.
Signed-off-by: Fam Zheng <address@hidden>
---
blockdev-nbd.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
hmp.c | 5 ++--
qapi-schema.json | 3 ++-
qmp-commands.hx | 2 +-
4 files changed, 80 insertions(+), 6 deletions(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index c75df19..f12b57c 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -17,6 +17,8 @@
#include "qmp-commands.h"
#include "trace.h"
#include "block/nbd.h"
+#include "block/block_int.h"
+#include "block/block.h"
#include "qemu/sockets.h"
static int server_fd = -1;
@@ -78,8 +80,62 @@ static void nbd_server_put_ref(NBDExport *exp)
}
}
+static void snapshot_drive_backup_cb(void *opaque, int ret)
+{
+ BlockDriverState *bs = opaque;
+ bs->backing_hd = NULL;
+}
+
+/* create a point-in-time snapshot BDS from an existing BDS */
+static BlockDriverState *nbd_create_snapshot(BlockDriverState *orig_bs)
+{
+ int ret;
+ char filename[1024];
+ BlockDriver *drv;
+ BlockDriverState *bs;
+ QEMUOptionParameter *options;
+ Error *local_err = NULL;
+
+ bs = bdrv_new("");
+ ret = get_tmp_filename(filename, sizeof(filename));
+ if (ret < 0) {
+ goto err;
+ }
+ drv = bdrv_find_format("qcow2");
+ if (drv < 0) {
+ goto err;
+ }
+ options = parse_option_parameters("", drv->create_options, NULL);
+ set_option_parameter_int(options, BLOCK_OPT_SIZE, bdrv_getlength(orig_bs));
+
+ ret = bdrv_create(drv, filename, options);
+ if (ret < 0) {
+ goto err;
+ }
+ ret = bdrv_open(bs, filename, NULL, BDRV_O_RDWR, drv);
+ if (ret < 0) {
+ goto err;
+ }
+ bs->backing_hd = orig_bs;
+
+ backup_start(orig_bs, bs, 1,
+ MIRROR_SYNC_MODE_NONE,
+ BLOCKDEV_ON_ERROR_REPORT,
+ BLOCKDEV_ON_ERROR_REPORT,
+ snapshot_drive_backup_cb, bs, &local_err);
+ if (error_is_set(&local_err)) {
+ goto err;
+ }
+ return bs;
+
+err:
+ bdrv_delete(bs);
+ unlink(filename);
+ return NULL;
+}
+
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
- Error **errp)
+ bool has_snapshot, bool snapshot, Error **errp)
{
BlockDriverState *bs;
NBDExport *exp;
@@ -104,21 +160,37 @@ void qmp_nbd_server_add(const char *device, bool
has_writable, bool writable,
if (!has_writable) {
writable = false;
}
+
+ if (!has_snapshot) {
+ snapshot = false;
+ }
+
if (bdrv_is_read_only(bs)) {
writable = false;
}
+ if (snapshot) {
+ bs = nbd_create_snapshot(bs);
+ if (!bs) {
+ error_setg(errp, "Can't create snapshot for device");
+ return;
+ }
+ }
+
exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
nbd_server_put_ref);
nbd_export_set_name(exp, device);
- drive_get_ref(drive_get_by_blockdev(bs));
+ if (!snapshot) {
+ drive_get_ref(drive_get_by_blockdev(bs));
+ }
n = g_malloc0(sizeof(NBDCloseNotifier));
n->n.notify = nbd_close_notifier;
n->exp = exp;
bdrv_add_close_notifier(bs, &n->n);
QTAILQ_INSERT_TAIL(&close_notifiers, n, next);
+ return;
}
void qmp_nbd_server_stop(Error **errp)
diff --git a/hmp.c b/hmp.c
index c45514b..5cc97fe 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1440,7 +1440,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict
*qdict)
continue;
}
- qmp_nbd_server_add(info->value->device, true, writable, &local_err);
+ qmp_nbd_server_add(info->value->device, true, writable, false, false,
+ &local_err);
if (local_err != NULL) {
qmp_nbd_server_stop(NULL);
@@ -1460,7 +1461,7 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
int writable = qdict_get_try_bool(qdict, "writable", 0);
Error *local_err = NULL;
- qmp_nbd_server_add(device, true, writable, &local_err);
+ qmp_nbd_server_add(device, true, writable, false, false, &local_err);
if (local_err != NULL) {
hmp_handle_error(mon, &local_err);
diff --git a/qapi-schema.json b/qapi-schema.json
index f82d829..bfdbe33 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3225,7 +3225,8 @@
#
# Since: 1.3.0
##
-{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool'} }
+{ 'command': 'nbd-server-add', 'data': {'device': 'str', '*writable': 'bool',
+ '*snapshot': 'bool'} }
##
# @nbd-server-stop:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2e59b0d..e398d88 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2871,7 +2871,7 @@ EQMP
},
{
.name = "nbd-server-add",
- .args_type = "device:B,writable:b?",
+ .args_type = "device:B,writable:b?,snapshot:b?",
.mhandler.cmd_new = qmp_marshal_input_nbd_server_add,
},
{
--
1.8.3.4