optimize omap3 dss packed 24bpp mode
[qemu] / block-vmstate.c
1 /*
2  * Block driver for vmstate format
3  *
4  * Copyright (c) 2009 Nokia Corporation
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 #include "qemu-common.h"
25 #include "block_int.h"
26
27 #define VMSTATE_MAGIC 0x564D53544154451ALL
28 #define VMSTATE_VERSION 1
29
30 typedef struct VMStateHeader {
31     uint64_t magic;
32     uint32_t version;
33     uint64_t state_offset;
34     uint64_t state_size;
35 } VMStateHeader;
36
37 typedef struct BDRVVmState {
38     int fd;
39     uint64_t state_offset;
40     uint64_t state_size;
41     uint64_t write_offset;
42 } BDRVVMState;
43
44 static int vmstate_probe(const uint8_t *buf, int buf_size, const char *filename)
45 {
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)
50         return 100;
51     return 0;
52 }
53
54 static int vmstate_open(BlockDriverState *bs, const char *filename, int flags)
55 {
56     BDRVVMState *s = bs->opaque;
57     VMStateHeader header;
58     
59     s->fd = open(filename, O_RDWR | O_BINARY);
60     if (s->fd < 0)
61         return -errno;
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);
67         
68         s->write_offset = s->state_offset;
69         return 0;
70     }
71     close(s->fd);
72     return -EIO;
73 }
74
75 static void vmstate_flush(BlockDriverState *bs)
76 {
77 }
78
79 static void vmstate_close(BlockDriverState *bs)
80 {
81     BDRVVMState *s = bs->opaque;
82     
83     vmstate_flush(bs);
84     close(s->fd);
85 }
86
87 static int vmstate_create(const char *filename, int64_t total_size,
88                           const char *backing_file, int flags)
89 {
90     VMStateHeader header;
91     int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
92     if (fd < 0)
93         return -EIO;
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));
99     close(fd);
100     return 0;
101 }
102
103 static int vmstate_refresh_header(BDRVVMState *s)
104 {
105     VMStateHeader header;
106     
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))
112             return 0;
113     }
114     return -EIO;
115 }
116
117 static int vmstate_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
118 {
119     BDRVVMState *s = bs->opaque;
120     
121     bdi->cluster_size = 0;//VMSTATE_BLOCK_SIZE;
122     bdi->vm_state_offset = s->state_offset;
123     return 0;
124 }
125
126 static int vmstate_read(BlockDriverState *bs, int64_t sector_num,
127                         uint8_t *buf, int nb_sectors)
128 {
129     BDRVVMState *s = bs->opaque;
130     
131     if (lseek(s->fd, sector_num * 512, SEEK_SET) != sector_num * 512)
132         return -EIO;
133     return read(s->fd, buf, nb_sectors * 512);
134 }
135
136 static int vmstate_write(BlockDriverState *bs, int64_t sector_num,
137                          const uint8_t *buf, int nb_sectors)
138 {
139     BDRVVMState *s = bs->opaque;
140     
141     if (lseek(s->fd, sector_num * 512, SEEK_SET) != sector_num * 512)
142         return -EIO;
143     return write(s->fd, buf, nb_sectors * 512);
144 }
145
146 static int vmstate_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
147 {
148     BDRVVMState *s = bs->opaque;
149
150     return s->state_size ? 0 : -ENOENT;
151 }
152
153 static int vmstate_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
154 {
155     BDRVVMState *s = bs->opaque;
156     
157     if (s->state_size) {
158         s->state_size = 0;
159         vmstate_refresh_header(s);
160         if (!lseek(s->fd, 0, SEEK_SET))
161             return ftruncate(s->fd, sizeof(VMStateHeader));
162     }
163     return -ENOENT;
164 }
165
166 static int vmstate_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
167 {
168     BDRVVMState *s = bs->opaque;
169     
170     if (s->state_size)
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);
175 }
176
177 static int vmstate_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
178 {
179     BDRVVMState *s = bs->opaque;
180     QEMUSnapshotInfo *sn_info;
181     
182     sn_info = qemu_mallocz(sizeof(QEMUSnapshotInfo));
183     if (s->state_size) {
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;
187     }
188     *psn_tab = sn_info;
189     return s->state_size ? 1 : 0;
190 }
191
192 static int64_t vmstate_getlength(BlockDriverState *bs)
193 {
194     return 1LL << 63; /* big enough? */
195 }
196
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
213 };