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 28 int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, 29 const char *name) 30 { 31 QEMUSnapshotInfo *sn_tab, *sn; 32 int nb_sns, i, ret; 33 34 ret = -ENOENT; 35 nb_sns = bdrv_snapshot_list(bs, &sn_tab); 36 if (nb_sns < 0) { 37 return ret; 38 } 39 for (i = 0; i < nb_sns; i++) { 40 sn = &sn_tab[i]; 41 if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) { 42 *sn_info = *sn; 43 ret = 0; 44 break; 45 } 46 } 47 g_free(sn_tab); 48 return ret; 49 } 50 51 int bdrv_can_snapshot(BlockDriverState *bs) 52 { 53 BlockDriver *drv = bs->drv; 54 if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { 55 return 0; 56 } 57 58 if (!drv->bdrv_snapshot_create) { 59 if (bs->file != NULL) { 60 return bdrv_can_snapshot(bs->file); 61 } 62 return 0; 63 } 64 65 return 1; 66 } 67 68 int bdrv_snapshot_create(BlockDriverState *bs, 69 QEMUSnapshotInfo *sn_info) 70 { 71 BlockDriver *drv = bs->drv; 72 if (!drv) { 73 return -ENOMEDIUM; 74 } 75 if (drv->bdrv_snapshot_create) { 76 return drv->bdrv_snapshot_create(bs, sn_info); 77 } 78 if (bs->file) { 79 return bdrv_snapshot_create(bs->file, sn_info); 80 } 81 return -ENOTSUP; 82 } 83 84 int bdrv_snapshot_goto(BlockDriverState *bs, 85 const char *snapshot_id) 86 { 87 BlockDriver *drv = bs->drv; 88 int ret, open_ret; 89 90 if (!drv) { 91 return -ENOMEDIUM; 92 } 93 if (drv->bdrv_snapshot_goto) { 94 return drv->bdrv_snapshot_goto(bs, snapshot_id); 95 } 96 97 if (bs->file) { 98 drv->bdrv_close(bs); 99 ret = bdrv_snapshot_goto(bs->file, snapshot_id); 100 open_ret = drv->bdrv_open(bs, NULL, bs->open_flags); 101 if (open_ret < 0) { 102 bdrv_delete(bs->file); 103 bs->drv = NULL; 104 return open_ret; 105 } 106 return ret; 107 } 108 109 return -ENOTSUP; 110 } 111 112 int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) 113 { 114 BlockDriver *drv = bs->drv; 115 if (!drv) { 116 return -ENOMEDIUM; 117 } 118 if (drv->bdrv_snapshot_delete) { 119 return drv->bdrv_snapshot_delete(bs, snapshot_id); 120 } 121 if (bs->file) { 122 return bdrv_snapshot_delete(bs->file, snapshot_id); 123 } 124 return -ENOTSUP; 125 } 126 127 int bdrv_snapshot_list(BlockDriverState *bs, 128 QEMUSnapshotInfo **psn_info) 129 { 130 BlockDriver *drv = bs->drv; 131 if (!drv) { 132 return -ENOMEDIUM; 133 } 134 if (drv->bdrv_snapshot_list) { 135 return drv->bdrv_snapshot_list(bs, psn_info); 136 } 137 if (bs->file) { 138 return bdrv_snapshot_list(bs->file, psn_info); 139 } 140 return -ENOTSUP; 141 } 142 143 int bdrv_snapshot_load_tmp(BlockDriverState *bs, 144 const char *snapshot_name) 145 { 146 BlockDriver *drv = bs->drv; 147 if (!drv) { 148 return -ENOMEDIUM; 149 } 150 if (!bs->read_only) { 151 return -EINVAL; 152 } 153 if (drv->bdrv_snapshot_load_tmp) { 154 return drv->bdrv_snapshot_load_tmp(bs, snapshot_name); 155 } 156 return -ENOTSUP; 157 } 158