2 * Block driver for vmstate format
4 * Copyright (c) 2009 Nokia Corporation
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 #include "qemu-common.h"
25 #include "block_int.h"
27 #define VMSTATE_MAGIC 0x564D53544154451ALL
28 #define VMSTATE_VERSION 1
30 typedef struct VMStateHeader {
33 uint64_t state_offset;
37 typedef struct BDRVVmState {
39 uint64_t state_offset;
41 uint64_t write_offset;
44 static int vmstate_probe(const uint8_t *buf, int buf_size, const char *filename)
46 const VMStateHeader *header = (const VMStateHeader *)buf;
47 if (buf_size >= sizeof(VMStateHeader) &&
48 be64_to_cpu(header->magic) == VMSTATE_MAGIC &&
49 be32_to_cpu(header->version) == VMSTATE_VERSION)
54 static int vmstate_open(BlockDriverState *bs, const char *filename, int flags)
56 BDRVVMState *s = bs->opaque;
59 s->fd = open(filename, O_RDWR | O_BINARY);
62 if (read(s->fd, &header, sizeof(header)) == sizeof(header) &&
63 be64_to_cpu(header.magic) == VMSTATE_MAGIC &&
64 be32_to_cpu(header.version) == VMSTATE_VERSION) {
65 s->state_offset = be64_to_cpu(header.state_offset);
66 s->state_size = be64_to_cpu(header.state_size);
68 s->write_offset = s->state_offset;
75 static void vmstate_flush(BlockDriverState *bs)
79 static void vmstate_close(BlockDriverState *bs)
81 BDRVVMState *s = bs->opaque;
87 static int vmstate_create(const char *filename, int64_t total_size,
88 const char *backing_file, int flags)
91 int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
94 memset(&header, 0, sizeof(header));
95 header.magic = cpu_to_be64(VMSTATE_MAGIC);
96 header.version = cpu_to_be32(VMSTATE_VERSION);
97 header.state_offset = cpu_to_be64(sizeof(header));
98 write(fd, &header, sizeof(header));
103 static int vmstate_refresh_header(BDRVVMState *s)
105 VMStateHeader header;
107 if (!lseek(s->fd, 0, SEEK_SET) &&
108 read(s->fd, &header, sizeof(header)) == sizeof(header)) {
109 header.state_size = cpu_to_be64(s->state_size);
110 if (!lseek(s->fd, 0, SEEK_SET) &&
111 write(s->fd, &header, sizeof(header)) == sizeof(header))
117 static int vmstate_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
119 BDRVVMState *s = bs->opaque;
121 bdi->cluster_size = 0;//VMSTATE_BLOCK_SIZE;
122 bdi->vm_state_offset = s->state_offset;
126 static int vmstate_read(BlockDriverState *bs, int64_t sector_num,
127 uint8_t *buf, int nb_sectors)
129 BDRVVMState *s = bs->opaque;
131 if (lseek(s->fd, sector_num * 512, SEEK_SET) != sector_num * 512)
133 return read(s->fd, buf, nb_sectors * 512);
136 static int vmstate_write(BlockDriverState *bs, int64_t sector_num,
137 const uint8_t *buf, int nb_sectors)
139 BDRVVMState *s = bs->opaque;
141 if (lseek(s->fd, sector_num * 512, SEEK_SET) != sector_num * 512)
143 return write(s->fd, buf, nb_sectors * 512);
146 static int vmstate_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
148 BDRVVMState *s = bs->opaque;
150 return s->state_size ? 0 : -ENOENT;
153 static int vmstate_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
155 BDRVVMState *s = bs->opaque;
159 vmstate_refresh_header(s);
160 if (!lseek(s->fd, 0, SEEK_SET))
161 return ftruncate(s->fd, sizeof(VMStateHeader));
166 static int vmstate_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
168 BDRVVMState *s = bs->opaque;
171 vmstate_snapshot_delete(bs, NULL);
172 s->state_size = sn_info->vm_state_size;
173 s->write_offset = s->state_offset;
174 return vmstate_refresh_header(s);
177 static int vmstate_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
179 BDRVVMState *s = bs->opaque;
180 QEMUSnapshotInfo *sn_info;
182 sn_info = qemu_mallocz(sizeof(QEMUSnapshotInfo));
184 pstrcpy(sn_info->id_str, sizeof(sn_info->id_str), "vmstate");
185 pstrcpy(sn_info->name, sizeof(sn_info->name), "vmstate");
186 sn_info->vm_state_size = s->state_size;
189 return s->state_size ? 1 : 0;
192 static int64_t vmstate_getlength(BlockDriverState *bs)
194 return 1LL << 63; /* big enough? */
197 BlockDriver bdrv_vmstate = {
198 .format_name = "vmstate",
199 .instance_size = sizeof(BDRVVMState),
200 .bdrv_probe = vmstate_probe,
201 .bdrv_open = vmstate_open,
202 .bdrv_read = vmstate_read,
203 .bdrv_write = vmstate_write,
204 .bdrv_close = vmstate_close,
205 .bdrv_create = vmstate_create,
206 .bdrv_flush = vmstate_flush,
207 .bdrv_getlength = vmstate_getlength,
208 .bdrv_snapshot_create = vmstate_snapshot_create,
209 .bdrv_snapshot_goto = vmstate_snapshot_goto,
210 .bdrv_snapshot_delete = vmstate_snapshot_delete,
211 .bdrv_snapshot_list = vmstate_snapshot_list,
212 .bdrv_get_info = vmstate_get_info