diff options
Diffstat (limited to 'block/rbd.c')
-rw-r--r-- | block/rbd.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/block/rbd.c b/block/rbd.c index 1ceeeb5a60..6471f4fd2b 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -94,7 +94,7 @@ typedef struct BDRVRBDState { rados_t cluster; rados_ioctx_t io_ctx; rbd_image_t image; - char *name; + char *image_name; char *snap; } BDRVRBDState; @@ -350,7 +350,7 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) int64_t bytes = 0; int64_t objsize; int obj_order = 0; - const char *pool, *name, *conf, *clientname, *keypairs; + const char *pool, *image_name, *conf, *user, *keypairs; const char *secretid; rados_t cluster; rados_ioctx_t io_ctx; @@ -393,11 +393,11 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) */ pool = qdict_get_try_str(options, "pool"); conf = qdict_get_try_str(options, "conf"); - clientname = qdict_get_try_str(options, "user"); - name = qdict_get_try_str(options, "image"); + user = qdict_get_try_str(options, "user"); + image_name = qdict_get_try_str(options, "image"); keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); - ret = rados_create(&cluster, clientname); + ret = rados_create(&cluster, user); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); goto exit; @@ -434,7 +434,7 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) goto shutdown; } - ret = rbd_create(io_ctx, name, bytes, &obj_order); + ret = rbd_create(io_ctx, image_name, bytes, &obj_order); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); } @@ -540,7 +540,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; - const char *pool, *snap, *conf, *clientname, *name, *keypairs; + const char *pool, *snap, *conf, *user, *image_name, *keypairs; const char *secretid; QemuOpts *opts; Error *local_err = NULL; @@ -567,24 +567,24 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, pool = qemu_opt_get(opts, "pool"); conf = qemu_opt_get(opts, "conf"); snap = qemu_opt_get(opts, "snapshot"); - clientname = qemu_opt_get(opts, "user"); - name = qemu_opt_get(opts, "image"); + user = qemu_opt_get(opts, "user"); + image_name = qemu_opt_get(opts, "image"); keypairs = qemu_opt_get(opts, "=keyvalue-pairs"); - if (!pool || !name) { + if (!pool || !image_name) { error_setg(errp, "Parameters 'pool' and 'image' are required"); r = -EINVAL; goto failed_opts; } - r = rados_create(&s->cluster, clientname); + r = rados_create(&s->cluster, user); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } s->snap = g_strdup(snap); - s->name = g_strdup(name); + s->image_name = g_strdup(image_name); /* try default location when conf=NULL, but ignore failure */ r = rados_conf_read_file(s->cluster, conf); @@ -635,13 +635,23 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, goto failed_shutdown; } - r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); + /* rbd_open is always r/w */ + r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap); if (r < 0) { - error_setg_errno(errp, -r, "error reading header from %s", s->name); + error_setg_errno(errp, -r, "error reading header from %s", + s->image_name); goto failed_open; } - bs->read_only = (s->snap != NULL); + /* If we are using an rbd snapshot, we must be r/o, otherwise + * leave as-is */ + if (s->snap != NULL) { + r = bdrv_set_read_only(bs, true, &local_err); + if (r < 0) { + error_propagate(errp, local_err); + goto failed_open; + } + } qemu_opts_del(opts); return 0; @@ -651,13 +661,33 @@ failed_open: failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); - g_free(s->name); + g_free(s->image_name); failed_opts: qemu_opts_del(opts); g_free(mon_host); return r; } + +/* Since RBD is currently always opened R/W via the API, + * we just need to check if we are using a snapshot or not, in + * order to determine if we will allow it to be R/W */ +static int qemu_rbd_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) +{ + BDRVRBDState *s = state->bs->opaque; + int ret = 0; + + if (s->snap && state->flags & BDRV_O_RDWR) { + error_setg(errp, + "Cannot change node '%s' to r/w when using RBD snapshot", + bdrv_get_device_or_node_name(state->bs)); + ret = -EINVAL; + } + + return ret; +} + static void qemu_rbd_close(BlockDriverState *bs) { BDRVRBDState *s = bs->opaque; @@ -665,7 +695,7 @@ static void qemu_rbd_close(BlockDriverState *bs) rbd_close(s->image); rados_ioctx_destroy(s->io_ctx); g_free(s->snap); - g_free(s->name); + g_free(s->image_name); rados_shutdown(s->cluster); } @@ -1064,6 +1094,7 @@ static BlockDriver bdrv_rbd = { .bdrv_parse_filename = qemu_rbd_parse_filename, .bdrv_file_open = qemu_rbd_open, .bdrv_close = qemu_rbd_close, + .bdrv_reopen_prepare = qemu_rbd_reopen_prepare, .bdrv_create = qemu_rbd_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_get_info = qemu_rbd_getinfo, |