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