qemu

Форк
0
/
bitmap-qmp-cmds.c 
317 строк · 8.7 Кб
1
/*
2
 * QEMU block dirty bitmap QMP commands
3
 *
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 * This work is licensed under the terms of the GNU GPL, version 2 or
7
 * later.  See the COPYING file in the top-level directory.
8
 *
9
 * This file incorporates work covered by the following copyright and
10
 * permission notice:
11
 *
12
 * Copyright (c) 2003-2008 Fabrice Bellard
13
 *
14
 * Permission is hereby granted, free of charge, to any person obtaining a copy
15
 * of this software and associated documentation files (the "Software"), to deal
16
 * in the Software without restriction, including without limitation the rights
17
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
 * copies of the Software, and to permit persons to whom the Software is
19
 * furnished to do so, subject to the following conditions:
20
 *
21
 * The above copyright notice and this permission notice shall be included in
22
 * all copies or substantial portions of the Software.
23
 *
24
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30
 * THE SOFTWARE.
31
 */
32

33
#include "qemu/osdep.h"
34

35
#include "block/block-io.h"
36
#include "block/block_int.h"
37
#include "block/dirty-bitmap.h"
38
#include "qapi/qapi-commands-block.h"
39
#include "qapi/error.h"
40

41
/**
42
 * block_dirty_bitmap_lookup:
43
 * Return a dirty bitmap (if present), after validating
44
 * the node reference and bitmap names.
45
 *
46
 * @node: The name of the BDS node to search for bitmaps
47
 * @name: The name of the bitmap to search for
48
 * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
49
 * @errp: Output pointer for error information. Can be NULL.
50
 *
51
 * @return: A bitmap object on success, or NULL on failure.
52
 */
53
BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
54
                                           const char *name,
55
                                           BlockDriverState **pbs,
56
                                           Error **errp)
57
{
58
    BlockDriverState *bs;
59
    BdrvDirtyBitmap *bitmap;
60

61
    GLOBAL_STATE_CODE();
62

63
    if (!node) {
64
        error_setg(errp, "Node cannot be NULL");
65
        return NULL;
66
    }
67
    if (!name) {
68
        error_setg(errp, "Bitmap name cannot be NULL");
69
        return NULL;
70
    }
71
    bs = bdrv_lookup_bs(node, node, NULL);
72
    if (!bs) {
73
        error_setg(errp, "Node '%s' not found", node);
74
        return NULL;
75
    }
76

77
    bitmap = bdrv_find_dirty_bitmap(bs, name);
78
    if (!bitmap) {
79
        error_setg(errp, "Dirty bitmap '%s' not found", name);
80
        return NULL;
81
    }
82

83
    if (pbs) {
84
        *pbs = bs;
85
    }
86

87
    return bitmap;
88
}
89

90
void qmp_block_dirty_bitmap_add(const char *node, const char *name,
91
                                bool has_granularity, uint32_t granularity,
92
                                bool has_persistent, bool persistent,
93
                                bool has_disabled, bool disabled,
94
                                Error **errp)
95
{
96
    BlockDriverState *bs;
97
    BdrvDirtyBitmap *bitmap;
98

99
    if (!name || name[0] == '\0') {
100
        error_setg(errp, "Bitmap name cannot be empty");
101
        return;
102
    }
103

104
    bs = bdrv_lookup_bs(node, node, errp);
105
    if (!bs) {
106
        return;
107
    }
108

109
    if (has_granularity) {
110
        if (granularity < 512 || !is_power_of_2(granularity)) {
111
            error_setg(errp, "Granularity must be power of 2 "
112
                             "and at least 512");
113
            return;
114
        }
115
    } else {
116
        /* Default to cluster size, if available: */
117
        granularity = bdrv_get_default_bitmap_granularity(bs);
118
    }
119

120
    if (!has_persistent) {
121
        persistent = false;
122
    }
123

124
    if (!has_disabled) {
125
        disabled = false;
126
    }
127

128
    if (persistent &&
129
        !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
130
    {
131
        return;
132
    }
133

134
    bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
135
    if (bitmap == NULL) {
136
        return;
137
    }
138

139
    if (disabled) {
140
        bdrv_disable_dirty_bitmap(bitmap);
141
    }
142

143
    bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
144
}
145

146
BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
147
                                           bool release,
148
                                           BlockDriverState **bitmap_bs,
149
                                           Error **errp)
150
{
151
    BlockDriverState *bs;
152
    BdrvDirtyBitmap *bitmap;
153

154
    GLOBAL_STATE_CODE();
155

156
    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
157
    if (!bitmap || !bs) {
158
        return NULL;
159
    }
160

161
    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
162
                                errp)) {
163
        return NULL;
164
    }
165

166
    if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
167
        bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
168
    {
169
        return NULL;
170
    }
171

172
    if (release) {
173
        bdrv_release_dirty_bitmap(bitmap);
174
    }
175

176
    if (bitmap_bs) {
177
        *bitmap_bs = bs;
178
    }
179

180
    return release ? NULL : bitmap;
181
}
182

183
void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
184
                                   Error **errp)
185
{
186
    block_dirty_bitmap_remove(node, name, true, NULL, errp);
187
}
188

189
/**
190
 * Completely clear a bitmap, for the purposes of synchronizing a bitmap
191
 * immediately after a full backup operation.
192
 */
193
void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
194
                                  Error **errp)
195
{
196
    BdrvDirtyBitmap *bitmap;
197
    BlockDriverState *bs;
198

199
    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
200
    if (!bitmap || !bs) {
201
        return;
202
    }
203

204
    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
205
        return;
206
    }
207

208
    bdrv_clear_dirty_bitmap(bitmap, NULL);
209
}
210

211
void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
212
                                   Error **errp)
213
{
214
    BlockDriverState *bs;
215
    BdrvDirtyBitmap *bitmap;
216

217
    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
218
    if (!bitmap) {
219
        return;
220
    }
221

222
    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
223
        return;
224
    }
225

226
    bdrv_enable_dirty_bitmap(bitmap);
227
}
228

229
void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
230
                                    Error **errp)
231
{
232
    BlockDriverState *bs;
233
    BdrvDirtyBitmap *bitmap;
234

235
    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
236
    if (!bitmap) {
237
        return;
238
    }
239

240
    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
241
        return;
242
    }
243

244
    bdrv_disable_dirty_bitmap(bitmap);
245
}
246

247
BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node,
248
                                          const char *dst_bitmap,
249
                                          BlockDirtyBitmapOrStrList *bms,
250
                                          HBitmap **backup, Error **errp)
251
{
252
    BlockDriverState *bs;
253
    BdrvDirtyBitmap *dst, *src;
254
    BlockDirtyBitmapOrStrList *lst;
255
    const char *src_node, *src_bitmap;
256
    HBitmap *local_backup = NULL;
257

258
    GLOBAL_STATE_CODE();
259

260
    dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp);
261
    if (!dst) {
262
        return NULL;
263
    }
264

265
    for (lst = bms; lst; lst = lst->next) {
266
        switch (lst->value->type) {
267
        case QTYPE_QSTRING:
268
            src_bitmap = lst->value->u.local;
269
            src = bdrv_find_dirty_bitmap(bs, src_bitmap);
270
            if (!src) {
271
                error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap);
272
                goto fail;
273
            }
274
            break;
275
        case QTYPE_QDICT:
276
            src_node = lst->value->u.external.node;
277
            src_bitmap = lst->value->u.external.name;
278
            src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp);
279
            if (!src) {
280
                goto fail;
281
            }
282
            break;
283
        default:
284
            abort();
285
        }
286

287
        /* We do backup only for first merge operation */
288
        if (!bdrv_merge_dirty_bitmap(dst, src,
289
                                     local_backup ? NULL : &local_backup,
290
                                     errp))
291
        {
292
            goto fail;
293
        }
294
    }
295

296
    if (backup) {
297
        *backup = local_backup;
298
    } else {
299
        hbitmap_free(local_backup);
300
    }
301

302
    return dst;
303

304
fail:
305
    if (local_backup) {
306
        bdrv_restore_dirty_bitmap(dst, local_backup);
307
    }
308

309
    return NULL;
310
}
311

312
void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
313
                                  BlockDirtyBitmapOrStrList *bitmaps,
314
                                  Error **errp)
315
{
316
    block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
317
}
318

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.