1ced914d0SMaxim Levitsky /*
2ced914d0SMaxim Levitsky * Block layer code related to image options amend
3ced914d0SMaxim Levitsky *
4ced914d0SMaxim Levitsky * Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
5ced914d0SMaxim Levitsky * Copyright (c) 2020 Red Hat. Inc
6ced914d0SMaxim Levitsky *
7ced914d0SMaxim Levitsky * Heavily based on create.c
8ced914d0SMaxim Levitsky *
9ced914d0SMaxim Levitsky * Permission is hereby granted, free of charge, to any person obtaining a copy
10ced914d0SMaxim Levitsky * of this software and associated documentation files (the "Software"), to deal
11ced914d0SMaxim Levitsky * in the Software without restriction, including without limitation the rights
12ced914d0SMaxim Levitsky * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13ced914d0SMaxim Levitsky * copies of the Software, and to permit persons to whom the Software is
14ced914d0SMaxim Levitsky * furnished to do so, subject to the following conditions:
15ced914d0SMaxim Levitsky *
16ced914d0SMaxim Levitsky * The above copyright notice and this permission notice shall be included in
17ced914d0SMaxim Levitsky * all copies or substantial portions of the Software.
18ced914d0SMaxim Levitsky *
19ced914d0SMaxim Levitsky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20ced914d0SMaxim Levitsky * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21ced914d0SMaxim Levitsky * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22ced914d0SMaxim Levitsky * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23ced914d0SMaxim Levitsky * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24ced914d0SMaxim Levitsky * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25ced914d0SMaxim Levitsky * THE SOFTWARE.
26ced914d0SMaxim Levitsky */
27ced914d0SMaxim Levitsky
28ced914d0SMaxim Levitsky #include "qemu/osdep.h"
29e2c1c34fSMarkus Armbruster #include "block/block-io.h"
30ced914d0SMaxim Levitsky #include "block/block_int.h"
31ced914d0SMaxim Levitsky #include "qemu/job.h"
32ced914d0SMaxim Levitsky #include "qemu/main-loop.h"
33ced914d0SMaxim Levitsky #include "qapi/qapi-commands-block-core.h"
34ced914d0SMaxim Levitsky #include "qapi/qapi-visit-block-core.h"
35ced914d0SMaxim Levitsky #include "qapi/clone-visitor.h"
36ced914d0SMaxim Levitsky #include "qapi/error.h"
37ced914d0SMaxim Levitsky
38ced914d0SMaxim Levitsky typedef struct BlockdevAmendJob {
39ced914d0SMaxim Levitsky Job common;
40ced914d0SMaxim Levitsky BlockdevAmendOptions *opts;
41ced914d0SMaxim Levitsky BlockDriverState *bs;
42ced914d0SMaxim Levitsky bool force;
43ced914d0SMaxim Levitsky } BlockdevAmendJob;
44ced914d0SMaxim Levitsky
blockdev_amend_run(Job * job,Error ** errp)45ced914d0SMaxim Levitsky static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
46ced914d0SMaxim Levitsky {
47ced914d0SMaxim Levitsky BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
48ced914d0SMaxim Levitsky int ret;
49*840428a2SEmanuele Giuseppe Esposito GRAPH_RDLOCK_GUARD();
50ced914d0SMaxim Levitsky
51ced914d0SMaxim Levitsky job_progress_set_remaining(&s->common, 1);
52ced914d0SMaxim Levitsky ret = s->bs->drv->bdrv_co_amend(s->bs, s->opts, s->force, errp);
53ced914d0SMaxim Levitsky job_progress_update(&s->common, 1);
54ced914d0SMaxim Levitsky qapi_free_BlockdevAmendOptions(s->opts);
55ced914d0SMaxim Levitsky return ret;
56ced914d0SMaxim Levitsky }
57ced914d0SMaxim Levitsky
58*840428a2SEmanuele Giuseppe Esposito static int GRAPH_RDLOCK
blockdev_amend_pre_run(BlockdevAmendJob * s,Error ** errp)59*840428a2SEmanuele Giuseppe Esposito blockdev_amend_pre_run(BlockdevAmendJob *s, Error **errp)
60c1019d16SEmanuele Giuseppe Esposito {
61c1019d16SEmanuele Giuseppe Esposito if (s->bs->drv->bdrv_amend_pre_run) {
62c1019d16SEmanuele Giuseppe Esposito return s->bs->drv->bdrv_amend_pre_run(s->bs, errp);
63c1019d16SEmanuele Giuseppe Esposito }
64c1019d16SEmanuele Giuseppe Esposito
65c1019d16SEmanuele Giuseppe Esposito return 0;
66c1019d16SEmanuele Giuseppe Esposito }
67c1019d16SEmanuele Giuseppe Esposito
blockdev_amend_free(Job * job)68b8ba6006SHanna Reitz static void blockdev_amend_free(Job *job)
69c1019d16SEmanuele Giuseppe Esposito {
70c1019d16SEmanuele Giuseppe Esposito BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
71c1019d16SEmanuele Giuseppe Esposito
72*840428a2SEmanuele Giuseppe Esposito bdrv_graph_rdlock_main_loop();
73c1019d16SEmanuele Giuseppe Esposito if (s->bs->drv->bdrv_amend_clean) {
74c1019d16SEmanuele Giuseppe Esposito s->bs->drv->bdrv_amend_clean(s->bs);
75c1019d16SEmanuele Giuseppe Esposito }
76*840428a2SEmanuele Giuseppe Esposito bdrv_graph_rdunlock_main_loop();
7778fa41fcSHanna Reitz
7878fa41fcSHanna Reitz bdrv_unref(s->bs);
79c1019d16SEmanuele Giuseppe Esposito }
80c1019d16SEmanuele Giuseppe Esposito
81ced914d0SMaxim Levitsky static const JobDriver blockdev_amend_job_driver = {
82ced914d0SMaxim Levitsky .instance_size = sizeof(BlockdevAmendJob),
83ced914d0SMaxim Levitsky .job_type = JOB_TYPE_AMEND,
84ced914d0SMaxim Levitsky .run = blockdev_amend_run,
85b8ba6006SHanna Reitz .free = blockdev_amend_free,
86ced914d0SMaxim Levitsky };
87ced914d0SMaxim Levitsky
qmp_x_blockdev_amend(const char * job_id,const char * node_name,BlockdevAmendOptions * options,bool has_force,bool force,Error ** errp)88ced914d0SMaxim Levitsky void qmp_x_blockdev_amend(const char *job_id,
89ced914d0SMaxim Levitsky const char *node_name,
90ced914d0SMaxim Levitsky BlockdevAmendOptions *options,
91ced914d0SMaxim Levitsky bool has_force,
92ced914d0SMaxim Levitsky bool force,
93ced914d0SMaxim Levitsky Error **errp)
94ced914d0SMaxim Levitsky {
95ced914d0SMaxim Levitsky BlockdevAmendJob *s;
96ced914d0SMaxim Levitsky const char *fmt = BlockdevDriver_str(options->driver);
97ced914d0SMaxim Levitsky BlockDriver *drv = bdrv_find_format(fmt);
98984c3678SMax Reitz BlockDriverState *bs;
99ced914d0SMaxim Levitsky
100*840428a2SEmanuele Giuseppe Esposito GRAPH_RDLOCK_GUARD_MAINLOOP();
101*840428a2SEmanuele Giuseppe Esposito
102984c3678SMax Reitz bs = bdrv_lookup_bs(NULL, node_name, errp);
103984c3678SMax Reitz if (!bs) {
104984c3678SMax Reitz return;
105984c3678SMax Reitz }
106ced914d0SMaxim Levitsky
107ced914d0SMaxim Levitsky if (!drv) {
108ced914d0SMaxim Levitsky error_setg(errp, "Block driver '%s' not found or not supported", fmt);
109ced914d0SMaxim Levitsky return;
110ced914d0SMaxim Levitsky }
111ced914d0SMaxim Levitsky
112ced914d0SMaxim Levitsky /*
113ced914d0SMaxim Levitsky * If the driver is in the schema, we know that it exists. But it may not
114ced914d0SMaxim Levitsky * be whitelisted.
115ced914d0SMaxim Levitsky */
116ced914d0SMaxim Levitsky if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
117ced914d0SMaxim Levitsky error_setg(errp, "Driver is not whitelisted");
118ced914d0SMaxim Levitsky return;
119ced914d0SMaxim Levitsky }
120ced914d0SMaxim Levitsky
121ced914d0SMaxim Levitsky if (bs->drv != drv) {
122ced914d0SMaxim Levitsky error_setg(errp,
123ced914d0SMaxim Levitsky "x-blockdev-amend doesn't support changing the block driver");
124ced914d0SMaxim Levitsky return;
125ced914d0SMaxim Levitsky }
126ced914d0SMaxim Levitsky
127ced914d0SMaxim Levitsky /* Error out if the driver doesn't support .bdrv_co_amend */
128ced914d0SMaxim Levitsky if (!drv->bdrv_co_amend) {
129ced914d0SMaxim Levitsky error_setg(errp, "Driver does not support x-blockdev-amend");
130ced914d0SMaxim Levitsky return;
131ced914d0SMaxim Levitsky }
132ced914d0SMaxim Levitsky
133ced914d0SMaxim Levitsky /* Create the block job */
134ced914d0SMaxim Levitsky s = job_create(job_id, &blockdev_amend_job_driver, NULL,
135ced914d0SMaxim Levitsky bdrv_get_aio_context(bs), JOB_DEFAULT | JOB_MANUAL_DISMISS,
136ced914d0SMaxim Levitsky NULL, NULL, errp);
137ced914d0SMaxim Levitsky if (!s) {
138ced914d0SMaxim Levitsky return;
139ced914d0SMaxim Levitsky }
140ced914d0SMaxim Levitsky
14178fa41fcSHanna Reitz bdrv_ref(bs);
142ced914d0SMaxim Levitsky s->bs = bs,
143ced914d0SMaxim Levitsky s->opts = QAPI_CLONE(BlockdevAmendOptions, options),
144ced914d0SMaxim Levitsky s->force = has_force ? force : false;
145c1019d16SEmanuele Giuseppe Esposito
146c1019d16SEmanuele Giuseppe Esposito if (blockdev_amend_pre_run(s, errp)) {
147c1019d16SEmanuele Giuseppe Esposito job_early_fail(&s->common);
148c1019d16SEmanuele Giuseppe Esposito return;
149c1019d16SEmanuele Giuseppe Esposito }
150c1019d16SEmanuele Giuseppe Esposito
151ced914d0SMaxim Levitsky job_start(&s->common);
152ced914d0SMaxim Levitsky }
153