xref: /openbmc/qemu/block/snapshot.c (revision d341d9f3)
1 /*
2  * Block layer snapshot related functions
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "block/snapshot.h"
27 #include "block/block_int.h"
28 #include "qapi/qmp/qerror.h"
29 
30 QemuOptsList internal_snapshot_opts = {
31     .name = "snapshot",
32     .head = QTAILQ_HEAD_INITIALIZER(internal_snapshot_opts.head),
33     .desc = {
34         {
35             .name = SNAPSHOT_OPT_ID,
36             .type = QEMU_OPT_STRING,
37             .help = "snapshot id"
38         },{
39             .name = SNAPSHOT_OPT_NAME,
40             .type = QEMU_OPT_STRING,
41             .help = "snapshot name"
42         },{
43             /* end of list */
44         }
45     },
46 };
47 
48 int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
49                        const char *name)
50 {
51     QEMUSnapshotInfo *sn_tab, *sn;
52     int nb_sns, i, ret;
53 
54     ret = -ENOENT;
55     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
56     if (nb_sns < 0) {
57         return ret;
58     }
59     for (i = 0; i < nb_sns; i++) {
60         sn = &sn_tab[i];
61         if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
62             *sn_info = *sn;
63             ret = 0;
64             break;
65         }
66     }
67     g_free(sn_tab);
68     return ret;
69 }
70 
71 /**
72  * Look up an internal snapshot by @id and @name.
73  * @bs: block device to search
74  * @id: unique snapshot ID, or NULL
75  * @name: snapshot name, or NULL
76  * @sn_info: location to store information on the snapshot found
77  * @errp: location to store error, will be set only for exception
78  *
79  * This function will traverse snapshot list in @bs to search the matching
80  * one, @id and @name are the matching condition:
81  * If both @id and @name are specified, find the first one with id @id and
82  * name @name.
83  * If only @id is specified, find the first one with id @id.
84  * If only @name is specified, find the first one with name @name.
85  * if none is specified, abort().
86  *
87  * Returns: true when a snapshot is found and @sn_info will be filled, false
88  * when error or not found. If all operation succeed but no matching one is
89  * found, @errp will NOT be set.
90  */
91 bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
92                                        const char *id,
93                                        const char *name,
94                                        QEMUSnapshotInfo *sn_info,
95                                        Error **errp)
96 {
97     QEMUSnapshotInfo *sn_tab, *sn;
98     int nb_sns, i;
99     bool ret = false;
100 
101     assert(id || name);
102 
103     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
104     if (nb_sns < 0) {
105         error_setg_errno(errp, -nb_sns, "Failed to get a snapshot list");
106         return false;
107     } else if (nb_sns == 0) {
108         return false;
109     }
110 
111     if (id && name) {
112         for (i = 0; i < nb_sns; i++) {
113             sn = &sn_tab[i];
114             if (!strcmp(sn->id_str, id) && !strcmp(sn->name, name)) {
115                 *sn_info = *sn;
116                 ret = true;
117                 break;
118             }
119         }
120     } else if (id) {
121         for (i = 0; i < nb_sns; i++) {
122             sn = &sn_tab[i];
123             if (!strcmp(sn->id_str, id)) {
124                 *sn_info = *sn;
125                 ret = true;
126                 break;
127             }
128         }
129     } else if (name) {
130         for (i = 0; i < nb_sns; i++) {
131             sn = &sn_tab[i];
132             if (!strcmp(sn->name, name)) {
133                 *sn_info = *sn;
134                 ret = true;
135                 break;
136             }
137         }
138     }
139 
140     g_free(sn_tab);
141     return ret;
142 }
143 
144 int bdrv_can_snapshot(BlockDriverState *bs)
145 {
146     BlockDriver *drv = bs->drv;
147     if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
148         return 0;
149     }
150 
151     if (!drv->bdrv_snapshot_create) {
152         if (bs->file != NULL) {
153             return bdrv_can_snapshot(bs->file->bs);
154         }
155         return 0;
156     }
157 
158     return 1;
159 }
160 
161 int bdrv_snapshot_create(BlockDriverState *bs,
162                          QEMUSnapshotInfo *sn_info)
163 {
164     BlockDriver *drv = bs->drv;
165     if (!drv) {
166         return -ENOMEDIUM;
167     }
168     if (drv->bdrv_snapshot_create) {
169         return drv->bdrv_snapshot_create(bs, sn_info);
170     }
171     if (bs->file) {
172         return bdrv_snapshot_create(bs->file->bs, sn_info);
173     }
174     return -ENOTSUP;
175 }
176 
177 int bdrv_snapshot_goto(BlockDriverState *bs,
178                        const char *snapshot_id)
179 {
180     BlockDriver *drv = bs->drv;
181     int ret, open_ret;
182 
183     if (!drv) {
184         return -ENOMEDIUM;
185     }
186     if (drv->bdrv_snapshot_goto) {
187         return drv->bdrv_snapshot_goto(bs, snapshot_id);
188     }
189 
190     if (bs->file) {
191         drv->bdrv_close(bs);
192         ret = bdrv_snapshot_goto(bs->file->bs, snapshot_id);
193         open_ret = drv->bdrv_open(bs, NULL, bs->open_flags, NULL);
194         if (open_ret < 0) {
195             bdrv_unref(bs->file->bs);
196             bs->drv = NULL;
197             return open_ret;
198         }
199         return ret;
200     }
201 
202     return -ENOTSUP;
203 }
204 
205 /**
206  * Delete an internal snapshot by @snapshot_id and @name.
207  * @bs: block device used in the operation
208  * @snapshot_id: unique snapshot ID, or NULL
209  * @name: snapshot name, or NULL
210  * @errp: location to store error
211  *
212  * If both @snapshot_id and @name are specified, delete the first one with
213  * id @snapshot_id and name @name.
214  * If only @snapshot_id is specified, delete the first one with id
215  * @snapshot_id.
216  * If only @name is specified, delete the first one with name @name.
217  * if none is specified, return -EINVAL.
218  *
219  * Returns: 0 on success, -errno on failure. If @bs is not inserted, return
220  * -ENOMEDIUM. If @snapshot_id and @name are both NULL, return -EINVAL. If @bs
221  * does not support internal snapshot deletion, return -ENOTSUP. If @bs does
222  * not support parameter @snapshot_id or @name, or one of them is not correctly
223  * specified, return -EINVAL. If @bs can't find one matching @id and @name,
224  * return -ENOENT. If @errp != NULL, it will always be filled with error
225  * message on failure.
226  */
227 int bdrv_snapshot_delete(BlockDriverState *bs,
228                          const char *snapshot_id,
229                          const char *name,
230                          Error **errp)
231 {
232     BlockDriver *drv = bs->drv;
233     int ret;
234 
235     if (!drv) {
236         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
237         return -ENOMEDIUM;
238     }
239     if (!snapshot_id && !name) {
240         error_setg(errp, "snapshot_id and name are both NULL");
241         return -EINVAL;
242     }
243 
244     /* drain all pending i/o before deleting snapshot */
245     bdrv_drained_begin(bs);
246 
247     if (drv->bdrv_snapshot_delete) {
248         ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
249     } else if (bs->file) {
250         ret = bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp);
251     } else {
252         error_setg(errp, "Block format '%s' used by device '%s' "
253                    "does not support internal snapshot deletion",
254                    drv->format_name, bdrv_get_device_name(bs));
255         ret = -ENOTSUP;
256     }
257 
258     bdrv_drained_end(bs);
259     return ret;
260 }
261 
262 int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
263                                        const char *id_or_name,
264                                        Error **errp)
265 {
266     int ret;
267     Error *local_err = NULL;
268 
269     ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
270     if (ret == -ENOENT || ret == -EINVAL) {
271         error_free(local_err);
272         local_err = NULL;
273         ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
274     }
275 
276     if (ret < 0) {
277         error_propagate(errp, local_err);
278     }
279     return ret;
280 }
281 
282 int bdrv_snapshot_list(BlockDriverState *bs,
283                        QEMUSnapshotInfo **psn_info)
284 {
285     BlockDriver *drv = bs->drv;
286     if (!drv) {
287         return -ENOMEDIUM;
288     }
289     if (drv->bdrv_snapshot_list) {
290         return drv->bdrv_snapshot_list(bs, psn_info);
291     }
292     if (bs->file) {
293         return bdrv_snapshot_list(bs->file->bs, psn_info);
294     }
295     return -ENOTSUP;
296 }
297 
298 /**
299  * Temporarily load an internal snapshot by @snapshot_id and @name.
300  * @bs: block device used in the operation
301  * @snapshot_id: unique snapshot ID, or NULL
302  * @name: snapshot name, or NULL
303  * @errp: location to store error
304  *
305  * If both @snapshot_id and @name are specified, load the first one with
306  * id @snapshot_id and name @name.
307  * If only @snapshot_id is specified, load the first one with id
308  * @snapshot_id.
309  * If only @name is specified, load the first one with name @name.
310  * if none is specified, return -EINVAL.
311  *
312  * Returns: 0 on success, -errno on fail. If @bs is not inserted, return
313  * -ENOMEDIUM. If @bs is not readonly, return -EINVAL. If @bs did not support
314  * internal snapshot, return -ENOTSUP. If qemu can't find a matching @id and
315  * @name, return -ENOENT. If @errp != NULL, it will always be filled on
316  * failure.
317  */
318 int bdrv_snapshot_load_tmp(BlockDriverState *bs,
319                            const char *snapshot_id,
320                            const char *name,
321                            Error **errp)
322 {
323     BlockDriver *drv = bs->drv;
324 
325     if (!drv) {
326         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
327         return -ENOMEDIUM;
328     }
329     if (!snapshot_id && !name) {
330         error_setg(errp, "snapshot_id and name are both NULL");
331         return -EINVAL;
332     }
333     if (!bs->read_only) {
334         error_setg(errp, "Device is not readonly");
335         return -EINVAL;
336     }
337     if (drv->bdrv_snapshot_load_tmp) {
338         return drv->bdrv_snapshot_load_tmp(bs, snapshot_id, name, errp);
339     }
340     error_setg(errp, "Block format '%s' used by device '%s' "
341                "does not support temporarily loading internal snapshots",
342                drv->format_name, bdrv_get_device_name(bs));
343     return -ENOTSUP;
344 }
345 
346 int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
347                                          const char *id_or_name,
348                                          Error **errp)
349 {
350     int ret;
351     Error *local_err = NULL;
352 
353     ret = bdrv_snapshot_load_tmp(bs, id_or_name, NULL, &local_err);
354     if (ret == -ENOENT || ret == -EINVAL) {
355         error_free(local_err);
356         local_err = NULL;
357         ret = bdrv_snapshot_load_tmp(bs, NULL, id_or_name, &local_err);
358     }
359 
360     if (local_err) {
361         error_propagate(errp, local_err);
362     }
363 
364     return ret;
365 }
366 
367 
368 /* Group operations. All block drivers are involved.
369  * These functions will properly handle dataplane (take aio_context_acquire
370  * when appropriate for appropriate block drivers) */
371 
372 bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs)
373 {
374     bool ok = true;
375     BlockDriverState *bs = NULL;
376 
377     while (ok && (bs = bdrv_next(bs))) {
378         AioContext *ctx = bdrv_get_aio_context(bs);
379 
380         aio_context_acquire(ctx);
381         if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) {
382             ok = bdrv_can_snapshot(bs);
383         }
384         aio_context_release(ctx);
385     }
386 
387     *first_bad_bs = bs;
388     return ok;
389 }
390 
391 int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
392                              Error **err)
393 {
394     int ret = 0;
395     BlockDriverState *bs = NULL;
396     QEMUSnapshotInfo sn1, *snapshot = &sn1;
397 
398     while (ret == 0 && (bs = bdrv_next(bs))) {
399         AioContext *ctx = bdrv_get_aio_context(bs);
400 
401         aio_context_acquire(ctx);
402         if (bdrv_can_snapshot(bs) &&
403                 bdrv_snapshot_find(bs, snapshot, name) >= 0) {
404             ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
405         }
406         aio_context_release(ctx);
407     }
408 
409     *first_bad_bs = bs;
410     return ret;
411 }
412 
413 
414 int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs)
415 {
416     int err = 0;
417     BlockDriverState *bs = NULL;
418 
419     while (err == 0 && (bs = bdrv_next(bs))) {
420         AioContext *ctx = bdrv_get_aio_context(bs);
421 
422         aio_context_acquire(ctx);
423         if (bdrv_can_snapshot(bs)) {
424             err = bdrv_snapshot_goto(bs, name);
425         }
426         aio_context_release(ctx);
427     }
428 
429     *first_bad_bs = bs;
430     return err;
431 }
432 
433 int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs)
434 {
435     QEMUSnapshotInfo sn;
436     int err = 0;
437     BlockDriverState *bs = NULL;
438 
439     while (err == 0 && (bs = bdrv_next(bs))) {
440         AioContext *ctx = bdrv_get_aio_context(bs);
441 
442         aio_context_acquire(ctx);
443         if (bdrv_can_snapshot(bs)) {
444             err = bdrv_snapshot_find(bs, &sn, name);
445         }
446         aio_context_release(ctx);
447     }
448 
449     *first_bad_bs = bs;
450     return err;
451 }
452 
453 int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
454                              BlockDriverState *vm_state_bs,
455                              uint64_t vm_state_size,
456                              BlockDriverState **first_bad_bs)
457 {
458     int err = 0;
459     BlockDriverState *bs = NULL;
460 
461     while (err == 0 && (bs = bdrv_next(bs))) {
462         AioContext *ctx = bdrv_get_aio_context(bs);
463 
464         aio_context_acquire(ctx);
465         if (bs == vm_state_bs) {
466             sn->vm_state_size = vm_state_size;
467             err = bdrv_snapshot_create(bs, sn);
468         } else if (bdrv_can_snapshot(bs)) {
469             sn->vm_state_size = 0;
470             err = bdrv_snapshot_create(bs, sn);
471         }
472         aio_context_release(ctx);
473     }
474 
475     *first_bad_bs = bs;
476     return err;
477 }
478 
479 BlockDriverState *bdrv_all_find_vmstate_bs(void)
480 {
481     bool not_found = true;
482     BlockDriverState *bs = NULL;
483 
484     while (not_found && (bs = bdrv_next(bs))) {
485         AioContext *ctx = bdrv_get_aio_context(bs);
486 
487         aio_context_acquire(ctx);
488         not_found = !bdrv_can_snapshot(bs);
489         aio_context_release(ctx);
490     }
491     return bs;
492 }
493