Add qemu 2.4.0
[kvmfornfv.git] / qemu / block / snapshot.c
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);
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, 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, snapshot_id);
192         open_ret = drv->bdrv_open(bs, NULL, bs->open_flags, NULL);
193         if (open_ret < 0) {
194             bdrv_unref(bs->file);
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     if (!drv) {
233         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
234         return -ENOMEDIUM;
235     }
236     if (!snapshot_id && !name) {
237         error_setg(errp, "snapshot_id and name are both NULL");
238         return -EINVAL;
239     }
240
241     /* drain all pending i/o before deleting snapshot */
242     bdrv_drain(bs);
243
244     if (drv->bdrv_snapshot_delete) {
245         return drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
246     }
247     if (bs->file) {
248         return bdrv_snapshot_delete(bs->file, snapshot_id, name, errp);
249     }
250     error_setg(errp, "Block format '%s' used by device '%s' "
251                "does not support internal snapshot deletion",
252                drv->format_name, bdrv_get_device_name(bs));
253     return -ENOTSUP;
254 }
255
256 void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
257                                         const char *id_or_name,
258                                         Error **errp)
259 {
260     int ret;
261     Error *local_err = NULL;
262
263     ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
264     if (ret == -ENOENT || ret == -EINVAL) {
265         error_free(local_err);
266         local_err = NULL;
267         ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
268     }
269
270     if (ret < 0) {
271         error_propagate(errp, local_err);
272     }
273 }
274
275 int bdrv_snapshot_list(BlockDriverState *bs,
276                        QEMUSnapshotInfo **psn_info)
277 {
278     BlockDriver *drv = bs->drv;
279     if (!drv) {
280         return -ENOMEDIUM;
281     }
282     if (drv->bdrv_snapshot_list) {
283         return drv->bdrv_snapshot_list(bs, psn_info);
284     }
285     if (bs->file) {
286         return bdrv_snapshot_list(bs->file, psn_info);
287     }
288     return -ENOTSUP;
289 }
290
291 /**
292  * Temporarily load an internal snapshot by @snapshot_id and @name.
293  * @bs: block device used in the operation
294  * @snapshot_id: unique snapshot ID, or NULL
295  * @name: snapshot name, or NULL
296  * @errp: location to store error
297  *
298  * If both @snapshot_id and @name are specified, load the first one with
299  * id @snapshot_id and name @name.
300  * If only @snapshot_id is specified, load the first one with id
301  * @snapshot_id.
302  * If only @name is specified, load the first one with name @name.
303  * if none is specified, return -EINVAL.
304  *
305  * Returns: 0 on success, -errno on fail. If @bs is not inserted, return
306  * -ENOMEDIUM. If @bs is not readonly, return -EINVAL. If @bs did not support
307  * internal snapshot, return -ENOTSUP. If qemu can't find a matching @id and
308  * @name, return -ENOENT. If @errp != NULL, it will always be filled on
309  * failure.
310  */
311 int bdrv_snapshot_load_tmp(BlockDriverState *bs,
312                            const char *snapshot_id,
313                            const char *name,
314                            Error **errp)
315 {
316     BlockDriver *drv = bs->drv;
317
318     if (!drv) {
319         error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
320         return -ENOMEDIUM;
321     }
322     if (!snapshot_id && !name) {
323         error_setg(errp, "snapshot_id and name are both NULL");
324         return -EINVAL;
325     }
326     if (!bs->read_only) {
327         error_setg(errp, "Device is not readonly");
328         return -EINVAL;
329     }
330     if (drv->bdrv_snapshot_load_tmp) {
331         return drv->bdrv_snapshot_load_tmp(bs, snapshot_id, name, errp);
332     }
333     error_setg(errp, "Block format '%s' used by device '%s' "
334                "does not support temporarily loading internal snapshots",
335                drv->format_name, bdrv_get_device_name(bs));
336     return -ENOTSUP;
337 }
338
339 int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
340                                          const char *id_or_name,
341                                          Error **errp)
342 {
343     int ret;
344     Error *local_err = NULL;
345
346     ret = bdrv_snapshot_load_tmp(bs, id_or_name, NULL, &local_err);
347     if (ret == -ENOENT || ret == -EINVAL) {
348         error_free(local_err);
349         local_err = NULL;
350         ret = bdrv_snapshot_load_tmp(bs, NULL, id_or_name, &local_err);
351     }
352
353     if (local_err) {
354         error_propagate(errp, local_err);
355     }
356
357     return ret;
358 }