Statistics
| Branch: | Revision:

root / block / vdi.c @ 7371d56f

History | View | Annotate | Download (24.3 kB)

1 9aebd98a Stefan Weil
/*
2 9aebd98a Stefan Weil
 * Block driver for the Virtual Disk Image (VDI) format
3 9aebd98a Stefan Weil
 *
4 641543b7 Stefan Weil
 * Copyright (c) 2009, 2012 Stefan Weil
5 9aebd98a Stefan Weil
 *
6 9aebd98a Stefan Weil
 * This program is free software: you can redistribute it and/or modify
7 9aebd98a Stefan Weil
 * it under the terms of the GNU General Public License as published by
8 9aebd98a Stefan Weil
 * the Free Software Foundation, either version 2 of the License, or
9 9aebd98a Stefan Weil
 * (at your option) version 3 or any later version.
10 9aebd98a Stefan Weil
 *
11 9aebd98a Stefan Weil
 * This program is distributed in the hope that it will be useful,
12 9aebd98a Stefan Weil
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 9aebd98a Stefan Weil
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 9aebd98a Stefan Weil
 * GNU General Public License for more details.
15 9aebd98a Stefan Weil
 *
16 9aebd98a Stefan Weil
 * You should have received a copy of the GNU General Public License
17 9aebd98a Stefan Weil
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 9aebd98a Stefan Weil
 *
19 9aebd98a Stefan Weil
 * Reference:
20 9aebd98a Stefan Weil
 * http://forums.virtualbox.org/viewtopic.php?t=8046
21 9aebd98a Stefan Weil
 *
22 9aebd98a Stefan Weil
 * This driver supports create / read / write operations on VDI images.
23 9aebd98a Stefan Weil
 *
24 9aebd98a Stefan Weil
 * Todo (see also TODO in code):
25 9aebd98a Stefan Weil
 *
26 9aebd98a Stefan Weil
 * Some features like snapshots are still missing.
27 9aebd98a Stefan Weil
 *
28 9aebd98a Stefan Weil
 * Deallocation of zero-filled blocks and shrinking images are missing, too
29 9aebd98a Stefan Weil
 * (might be added to common block layer).
30 9aebd98a Stefan Weil
 *
31 9aebd98a Stefan Weil
 * Allocation of blocks could be optimized (less writes to block map and
32 9aebd98a Stefan Weil
 * header).
33 9aebd98a Stefan Weil
 *
34 9aebd98a Stefan Weil
 * Read and write of adjacents blocks could be done in one operation
35 9aebd98a Stefan Weil
 * (current code uses one operation per block (1 MiB).
36 9aebd98a Stefan Weil
 *
37 9aebd98a Stefan Weil
 * The code is not thread safe (missing locks for changes in header and
38 9aebd98a Stefan Weil
 * block table, no problem with current QEMU).
39 9aebd98a Stefan Weil
 *
40 9aebd98a Stefan Weil
 * Hints:
41 9aebd98a Stefan Weil
 *
42 9aebd98a Stefan Weil
 * Blocks (VDI documentation) correspond to clusters (QEMU).
43 9aebd98a Stefan Weil
 * QEMU's backing files could be implemented using VDI snapshot files (TODO).
44 9aebd98a Stefan Weil
 * VDI snapshot files may also contain the complete machine state.
45 9aebd98a Stefan Weil
 * Maybe this machine state can be converted to QEMU PC machine snapshot data.
46 9aebd98a Stefan Weil
 *
47 9aebd98a Stefan Weil
 * The driver keeps a block cache (little endian entries) in memory.
48 9aebd98a Stefan Weil
 * For the standard block size (1 MiB), a 1 TiB disk will use 4 MiB RAM,
49 9aebd98a Stefan Weil
 * so this seems to be reasonable.
50 9aebd98a Stefan Weil
 */
51 9aebd98a Stefan Weil
52 9aebd98a Stefan Weil
#include "qemu-common.h"
53 737e150e Paolo Bonzini
#include "block/block_int.h"
54 1de7afc9 Paolo Bonzini
#include "qemu/module.h"
55 caf71f86 Paolo Bonzini
#include "migration/migration.h"
56 9aebd98a Stefan Weil
57 ee682d27 Stefan Weil
#if defined(CONFIG_UUID)
58 9aebd98a Stefan Weil
#include <uuid/uuid.h>
59 9aebd98a Stefan Weil
#else
60 9aebd98a Stefan Weil
/* TODO: move uuid emulation to some central place in QEMU. */
61 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"     /* UUID_FMT */
62 9aebd98a Stefan Weil
typedef unsigned char uuid_t[16];
63 9aebd98a Stefan Weil
#endif
64 9aebd98a Stefan Weil
65 9aebd98a Stefan Weil
/* Code configuration options. */
66 9aebd98a Stefan Weil
67 9aebd98a Stefan Weil
/* Enable debug messages. */
68 9aebd98a Stefan Weil
//~ #define CONFIG_VDI_DEBUG
69 9aebd98a Stefan Weil
70 9aebd98a Stefan Weil
/* Support write operations on VDI images. */
71 9aebd98a Stefan Weil
#define CONFIG_VDI_WRITE
72 9aebd98a Stefan Weil
73 9aebd98a Stefan Weil
/* Support non-standard block (cluster) size. This is untested.
74 9aebd98a Stefan Weil
 * Maybe it will be needed for very large images.
75 9aebd98a Stefan Weil
 */
76 9aebd98a Stefan Weil
//~ #define CONFIG_VDI_BLOCK_SIZE
77 9aebd98a Stefan Weil
78 9aebd98a Stefan Weil
/* Support static (fixed, pre-allocated) images. */
79 9aebd98a Stefan Weil
#define CONFIG_VDI_STATIC_IMAGE
80 9aebd98a Stefan Weil
81 9aebd98a Stefan Weil
/* Command line option for static images. */
82 9aebd98a Stefan Weil
#define BLOCK_OPT_STATIC "static"
83 9aebd98a Stefan Weil
84 9aebd98a Stefan Weil
#define KiB     1024
85 9aebd98a Stefan Weil
#define MiB     (KiB * KiB)
86 9aebd98a Stefan Weil
87 9aebd98a Stefan Weil
#define SECTOR_SIZE 512
88 99cce9fa Kevin Wolf
#define DEFAULT_CLUSTER_SIZE (1 * MiB)
89 9aebd98a Stefan Weil
90 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_DEBUG)
91 9aebd98a Stefan Weil
#define logout(fmt, ...) \
92 9aebd98a Stefan Weil
                fprintf(stderr, "vdi\t%-24s" fmt, __func__, ##__VA_ARGS__)
93 9aebd98a Stefan Weil
#else
94 9aebd98a Stefan Weil
#define logout(fmt, ...) ((void)0)
95 9aebd98a Stefan Weil
#endif
96 9aebd98a Stefan Weil
97 9aebd98a Stefan Weil
/* Image signature. */
98 9aebd98a Stefan Weil
#define VDI_SIGNATURE 0xbeda107f
99 9aebd98a Stefan Weil
100 9aebd98a Stefan Weil
/* Image version. */
101 9aebd98a Stefan Weil
#define VDI_VERSION_1_1 0x00010001
102 9aebd98a Stefan Weil
103 9aebd98a Stefan Weil
/* Image type. */
104 9aebd98a Stefan Weil
#define VDI_TYPE_DYNAMIC 1
105 9aebd98a Stefan Weil
#define VDI_TYPE_STATIC  2
106 9aebd98a Stefan Weil
107 9aebd98a Stefan Weil
/* Innotek / SUN images use these strings in header.text:
108 9aebd98a Stefan Weil
 * "<<< innotek VirtualBox Disk Image >>>\n"
109 9aebd98a Stefan Weil
 * "<<< Sun xVM VirtualBox Disk Image >>>\n"
110 9aebd98a Stefan Weil
 * "<<< Sun VirtualBox Disk Image >>>\n"
111 9aebd98a Stefan Weil
 * The value does not matter, so QEMU created images use a different text.
112 9aebd98a Stefan Weil
 */
113 9aebd98a Stefan Weil
#define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
114 9aebd98a Stefan Weil
115 c794b4e0 Eric Sunshine
/* A never-allocated block; semantically arbitrary content. */
116 c794b4e0 Eric Sunshine
#define VDI_UNALLOCATED 0xffffffffU
117 c794b4e0 Eric Sunshine
118 c794b4e0 Eric Sunshine
/* A discarded (no longer allocated) block; semantically zero-filled. */
119 c794b4e0 Eric Sunshine
#define VDI_DISCARDED   0xfffffffeU
120 c794b4e0 Eric Sunshine
121 c794b4e0 Eric Sunshine
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
122 9aebd98a Stefan Weil
123 ee682d27 Stefan Weil
#if !defined(CONFIG_UUID)
124 8ba2aae3 Stefan Hajnoczi
static inline void uuid_generate(uuid_t out)
125 9aebd98a Stefan Weil
{
126 4f3669ea Stefan Weil
    memset(out, 0, sizeof(uuid_t));
127 9aebd98a Stefan Weil
}
128 9aebd98a Stefan Weil
129 8ba2aae3 Stefan Hajnoczi
static inline int uuid_is_null(const uuid_t uu)
130 9aebd98a Stefan Weil
{
131 9aebd98a Stefan Weil
    uuid_t null_uuid = { 0 };
132 4f3669ea Stefan Weil
    return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
133 9aebd98a Stefan Weil
}
134 9aebd98a Stefan Weil
135 8ba2aae3 Stefan Hajnoczi
static inline void uuid_unparse(const uuid_t uu, char *out)
136 9aebd98a Stefan Weil
{
137 9aebd98a Stefan Weil
    snprintf(out, 37, UUID_FMT,
138 9aebd98a Stefan Weil
            uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
139 9aebd98a Stefan Weil
            uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
140 9aebd98a Stefan Weil
}
141 9aebd98a Stefan Weil
#endif
142 9aebd98a Stefan Weil
143 9aebd98a Stefan Weil
typedef struct {
144 9aebd98a Stefan Weil
    char text[0x40];
145 9aebd98a Stefan Weil
    uint32_t signature;
146 9aebd98a Stefan Weil
    uint32_t version;
147 9aebd98a Stefan Weil
    uint32_t header_size;
148 9aebd98a Stefan Weil
    uint32_t image_type;
149 9aebd98a Stefan Weil
    uint32_t image_flags;
150 9aebd98a Stefan Weil
    char description[256];
151 9aebd98a Stefan Weil
    uint32_t offset_bmap;
152 9aebd98a Stefan Weil
    uint32_t offset_data;
153 9aebd98a Stefan Weil
    uint32_t cylinders;         /* disk geometry, unused here */
154 9aebd98a Stefan Weil
    uint32_t heads;             /* disk geometry, unused here */
155 9aebd98a Stefan Weil
    uint32_t sectors;           /* disk geometry, unused here */
156 9aebd98a Stefan Weil
    uint32_t sector_size;
157 9aebd98a Stefan Weil
    uint32_t unused1;
158 9aebd98a Stefan Weil
    uint64_t disk_size;
159 9aebd98a Stefan Weil
    uint32_t block_size;
160 9aebd98a Stefan Weil
    uint32_t block_extra;       /* unused here */
161 9aebd98a Stefan Weil
    uint32_t blocks_in_image;
162 9aebd98a Stefan Weil
    uint32_t blocks_allocated;
163 9aebd98a Stefan Weil
    uuid_t uuid_image;
164 9aebd98a Stefan Weil
    uuid_t uuid_last_snap;
165 9aebd98a Stefan Weil
    uuid_t uuid_link;
166 9aebd98a Stefan Weil
    uuid_t uuid_parent;
167 9aebd98a Stefan Weil
    uint64_t unused2[7];
168 9aebd98a Stefan Weil
} VdiHeader;
169 9aebd98a Stefan Weil
170 9aebd98a Stefan Weil
typedef struct {
171 9aebd98a Stefan Weil
    /* The block map entries are little endian (even in memory). */
172 9aebd98a Stefan Weil
    uint32_t *bmap;
173 9aebd98a Stefan Weil
    /* Size of block (bytes). */
174 9aebd98a Stefan Weil
    uint32_t block_size;
175 9aebd98a Stefan Weil
    /* Size of block (sectors). */
176 9aebd98a Stefan Weil
    uint32_t block_sectors;
177 9aebd98a Stefan Weil
    /* First sector of block map. */
178 9aebd98a Stefan Weil
    uint32_t bmap_sector;
179 4ff9786c Stefan Weil
    /* VDI header (converted to host endianness). */
180 9aebd98a Stefan Weil
    VdiHeader header;
181 fc9d106c Kevin Wolf
182 fc9d106c Kevin Wolf
    Error *migration_blocker;
183 9aebd98a Stefan Weil
} BDRVVdiState;
184 9aebd98a Stefan Weil
185 9aebd98a Stefan Weil
/* Change UUID from little endian (IPRT = VirtualBox format) to big endian
186 9aebd98a Stefan Weil
 * format (network byte order, standard, see RFC 4122) and vice versa.
187 9aebd98a Stefan Weil
 */
188 9aebd98a Stefan Weil
static void uuid_convert(uuid_t uuid)
189 9aebd98a Stefan Weil
{
190 9aebd98a Stefan Weil
    bswap32s((uint32_t *)&uuid[0]);
191 9aebd98a Stefan Weil
    bswap16s((uint16_t *)&uuid[4]);
192 9aebd98a Stefan Weil
    bswap16s((uint16_t *)&uuid[6]);
193 9aebd98a Stefan Weil
}
194 9aebd98a Stefan Weil
195 9aebd98a Stefan Weil
static void vdi_header_to_cpu(VdiHeader *header)
196 9aebd98a Stefan Weil
{
197 9aebd98a Stefan Weil
    le32_to_cpus(&header->signature);
198 9aebd98a Stefan Weil
    le32_to_cpus(&header->version);
199 9aebd98a Stefan Weil
    le32_to_cpus(&header->header_size);
200 9aebd98a Stefan Weil
    le32_to_cpus(&header->image_type);
201 9aebd98a Stefan Weil
    le32_to_cpus(&header->image_flags);
202 9aebd98a Stefan Weil
    le32_to_cpus(&header->offset_bmap);
203 9aebd98a Stefan Weil
    le32_to_cpus(&header->offset_data);
204 9aebd98a Stefan Weil
    le32_to_cpus(&header->cylinders);
205 9aebd98a Stefan Weil
    le32_to_cpus(&header->heads);
206 9aebd98a Stefan Weil
    le32_to_cpus(&header->sectors);
207 9aebd98a Stefan Weil
    le32_to_cpus(&header->sector_size);
208 9aebd98a Stefan Weil
    le64_to_cpus(&header->disk_size);
209 9aebd98a Stefan Weil
    le32_to_cpus(&header->block_size);
210 9aebd98a Stefan Weil
    le32_to_cpus(&header->block_extra);
211 9aebd98a Stefan Weil
    le32_to_cpus(&header->blocks_in_image);
212 9aebd98a Stefan Weil
    le32_to_cpus(&header->blocks_allocated);
213 9aebd98a Stefan Weil
    uuid_convert(header->uuid_image);
214 9aebd98a Stefan Weil
    uuid_convert(header->uuid_last_snap);
215 9aebd98a Stefan Weil
    uuid_convert(header->uuid_link);
216 9aebd98a Stefan Weil
    uuid_convert(header->uuid_parent);
217 9aebd98a Stefan Weil
}
218 9aebd98a Stefan Weil
219 9aebd98a Stefan Weil
static void vdi_header_to_le(VdiHeader *header)
220 9aebd98a Stefan Weil
{
221 9aebd98a Stefan Weil
    cpu_to_le32s(&header->signature);
222 9aebd98a Stefan Weil
    cpu_to_le32s(&header->version);
223 9aebd98a Stefan Weil
    cpu_to_le32s(&header->header_size);
224 9aebd98a Stefan Weil
    cpu_to_le32s(&header->image_type);
225 9aebd98a Stefan Weil
    cpu_to_le32s(&header->image_flags);
226 9aebd98a Stefan Weil
    cpu_to_le32s(&header->offset_bmap);
227 9aebd98a Stefan Weil
    cpu_to_le32s(&header->offset_data);
228 9aebd98a Stefan Weil
    cpu_to_le32s(&header->cylinders);
229 9aebd98a Stefan Weil
    cpu_to_le32s(&header->heads);
230 9aebd98a Stefan Weil
    cpu_to_le32s(&header->sectors);
231 9aebd98a Stefan Weil
    cpu_to_le32s(&header->sector_size);
232 9aebd98a Stefan Weil
    cpu_to_le64s(&header->disk_size);
233 9aebd98a Stefan Weil
    cpu_to_le32s(&header->block_size);
234 9aebd98a Stefan Weil
    cpu_to_le32s(&header->block_extra);
235 9aebd98a Stefan Weil
    cpu_to_le32s(&header->blocks_in_image);
236 9aebd98a Stefan Weil
    cpu_to_le32s(&header->blocks_allocated);
237 9aebd98a Stefan Weil
    cpu_to_le32s(&header->blocks_allocated);
238 9aebd98a Stefan Weil
    uuid_convert(header->uuid_image);
239 9aebd98a Stefan Weil
    uuid_convert(header->uuid_last_snap);
240 9aebd98a Stefan Weil
    uuid_convert(header->uuid_link);
241 9aebd98a Stefan Weil
    uuid_convert(header->uuid_parent);
242 9aebd98a Stefan Weil
}
243 9aebd98a Stefan Weil
244 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_DEBUG)
245 9aebd98a Stefan Weil
static void vdi_header_print(VdiHeader *header)
246 9aebd98a Stefan Weil
{
247 9aebd98a Stefan Weil
    char uuid[37];
248 9aebd98a Stefan Weil
    logout("text        %s", header->text);
249 9aebd98a Stefan Weil
    logout("signature   0x%04x\n", header->signature);
250 9aebd98a Stefan Weil
    logout("header size 0x%04x\n", header->header_size);
251 9aebd98a Stefan Weil
    logout("image type  0x%04x\n", header->image_type);
252 9aebd98a Stefan Weil
    logout("image flags 0x%04x\n", header->image_flags);
253 9aebd98a Stefan Weil
    logout("description %s\n", header->description);
254 9aebd98a Stefan Weil
    logout("offset bmap 0x%04x\n", header->offset_bmap);
255 9aebd98a Stefan Weil
    logout("offset data 0x%04x\n", header->offset_data);
256 9aebd98a Stefan Weil
    logout("cylinders   0x%04x\n", header->cylinders);
257 9aebd98a Stefan Weil
    logout("heads       0x%04x\n", header->heads);
258 9aebd98a Stefan Weil
    logout("sectors     0x%04x\n", header->sectors);
259 9aebd98a Stefan Weil
    logout("sector size 0x%04x\n", header->sector_size);
260 9aebd98a Stefan Weil
    logout("image size  0x%" PRIx64 " B (%" PRIu64 " MiB)\n",
261 9aebd98a Stefan Weil
           header->disk_size, header->disk_size / MiB);
262 9aebd98a Stefan Weil
    logout("block size  0x%04x\n", header->block_size);
263 9aebd98a Stefan Weil
    logout("block extra 0x%04x\n", header->block_extra);
264 9aebd98a Stefan Weil
    logout("blocks tot. 0x%04x\n", header->blocks_in_image);
265 9aebd98a Stefan Weil
    logout("blocks all. 0x%04x\n", header->blocks_allocated);
266 9aebd98a Stefan Weil
    uuid_unparse(header->uuid_image, uuid);
267 9aebd98a Stefan Weil
    logout("uuid image  %s\n", uuid);
268 9aebd98a Stefan Weil
    uuid_unparse(header->uuid_last_snap, uuid);
269 9aebd98a Stefan Weil
    logout("uuid snap   %s\n", uuid);
270 9aebd98a Stefan Weil
    uuid_unparse(header->uuid_link, uuid);
271 9aebd98a Stefan Weil
    logout("uuid link   %s\n", uuid);
272 9aebd98a Stefan Weil
    uuid_unparse(header->uuid_parent, uuid);
273 9aebd98a Stefan Weil
    logout("uuid parent %s\n", uuid);
274 9aebd98a Stefan Weil
}
275 9aebd98a Stefan Weil
#endif
276 9aebd98a Stefan Weil
277 4534ff54 Kevin Wolf
static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res,
278 4534ff54 Kevin Wolf
                     BdrvCheckMode fix)
279 9aebd98a Stefan Weil
{
280 9aebd98a Stefan Weil
    /* TODO: additional checks possible. */
281 9aebd98a Stefan Weil
    BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
282 9aebd98a Stefan Weil
    uint32_t blocks_allocated = 0;
283 9aebd98a Stefan Weil
    uint32_t block;
284 9aebd98a Stefan Weil
    uint32_t *bmap;
285 9aebd98a Stefan Weil
    logout("\n");
286 9aebd98a Stefan Weil
287 4534ff54 Kevin Wolf
    if (fix) {
288 4534ff54 Kevin Wolf
        return -ENOTSUP;
289 4534ff54 Kevin Wolf
    }
290 4534ff54 Kevin Wolf
291 7267c094 Anthony Liguori
    bmap = g_malloc(s->header.blocks_in_image * sizeof(uint32_t));
292 9aebd98a Stefan Weil
    memset(bmap, 0xff, s->header.blocks_in_image * sizeof(uint32_t));
293 9aebd98a Stefan Weil
294 9aebd98a Stefan Weil
    /* Check block map and value of blocks_allocated. */
295 9aebd98a Stefan Weil
    for (block = 0; block < s->header.blocks_in_image; block++) {
296 9aebd98a Stefan Weil
        uint32_t bmap_entry = le32_to_cpu(s->bmap[block]);
297 c794b4e0 Eric Sunshine
        if (VDI_IS_ALLOCATED(bmap_entry)) {
298 9aebd98a Stefan Weil
            if (bmap_entry < s->header.blocks_in_image) {
299 9aebd98a Stefan Weil
                blocks_allocated++;
300 c794b4e0 Eric Sunshine
                if (!VDI_IS_ALLOCATED(bmap[bmap_entry])) {
301 9aebd98a Stefan Weil
                    bmap[bmap_entry] = bmap_entry;
302 9aebd98a Stefan Weil
                } else {
303 9aebd98a Stefan Weil
                    fprintf(stderr, "ERROR: block index %" PRIu32
304 9aebd98a Stefan Weil
                            " also used by %" PRIu32 "\n", bmap[bmap_entry], bmap_entry);
305 9ac228e0 Kevin Wolf
                    res->corruptions++;
306 9aebd98a Stefan Weil
                }
307 9aebd98a Stefan Weil
            } else {
308 9aebd98a Stefan Weil
                fprintf(stderr, "ERROR: block index %" PRIu32
309 9aebd98a Stefan Weil
                        " too large, is %" PRIu32 "\n", block, bmap_entry);
310 9ac228e0 Kevin Wolf
                res->corruptions++;
311 9aebd98a Stefan Weil
            }
312 9aebd98a Stefan Weil
        }
313 9aebd98a Stefan Weil
    }
314 9aebd98a Stefan Weil
    if (blocks_allocated != s->header.blocks_allocated) {
315 9aebd98a Stefan Weil
        fprintf(stderr, "ERROR: allocated blocks mismatch, is %" PRIu32
316 9aebd98a Stefan Weil
               ", should be %" PRIu32 "\n",
317 9aebd98a Stefan Weil
               blocks_allocated, s->header.blocks_allocated);
318 9ac228e0 Kevin Wolf
        res->corruptions++;
319 9aebd98a Stefan Weil
    }
320 9aebd98a Stefan Weil
321 7267c094 Anthony Liguori
    g_free(bmap);
322 9aebd98a Stefan Weil
323 9ac228e0 Kevin Wolf
    return 0;
324 9aebd98a Stefan Weil
}
325 9aebd98a Stefan Weil
326 9aebd98a Stefan Weil
static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
327 9aebd98a Stefan Weil
{
328 9aebd98a Stefan Weil
    /* TODO: vdi_get_info would be needed for machine snapshots.
329 9aebd98a Stefan Weil
       vm_state_offset is still missing. */
330 9aebd98a Stefan Weil
    BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
331 9aebd98a Stefan Weil
    logout("\n");
332 9aebd98a Stefan Weil
    bdi->cluster_size = s->block_size;
333 9aebd98a Stefan Weil
    bdi->vm_state_offset = 0;
334 9aebd98a Stefan Weil
    return 0;
335 9aebd98a Stefan Weil
}
336 9aebd98a Stefan Weil
337 9aebd98a Stefan Weil
static int vdi_make_empty(BlockDriverState *bs)
338 9aebd98a Stefan Weil
{
339 9aebd98a Stefan Weil
    /* TODO: missing code. */
340 9aebd98a Stefan Weil
    logout("\n");
341 9aebd98a Stefan Weil
    /* The return value for missing code must be 0, see block.c. */
342 9aebd98a Stefan Weil
    return 0;
343 9aebd98a Stefan Weil
}
344 9aebd98a Stefan Weil
345 9aebd98a Stefan Weil
static int vdi_probe(const uint8_t *buf, int buf_size, const char *filename)
346 9aebd98a Stefan Weil
{
347 9aebd98a Stefan Weil
    const VdiHeader *header = (const VdiHeader *)buf;
348 9aebd98a Stefan Weil
    int result = 0;
349 9aebd98a Stefan Weil
350 9aebd98a Stefan Weil
    logout("\n");
351 9aebd98a Stefan Weil
352 9aebd98a Stefan Weil
    if (buf_size < sizeof(*header)) {
353 9aebd98a Stefan Weil
        /* Header too small, no VDI. */
354 9aebd98a Stefan Weil
    } else if (le32_to_cpu(header->signature) == VDI_SIGNATURE) {
355 9aebd98a Stefan Weil
        result = 100;
356 9aebd98a Stefan Weil
    }
357 9aebd98a Stefan Weil
358 9aebd98a Stefan Weil
    if (result == 0) {
359 9aebd98a Stefan Weil
        logout("no vdi image\n");
360 9aebd98a Stefan Weil
    } else {
361 9aebd98a Stefan Weil
        logout("%s", header->text);
362 9aebd98a Stefan Weil
    }
363 9aebd98a Stefan Weil
364 9aebd98a Stefan Weil
    return result;
365 9aebd98a Stefan Weil
}
366 9aebd98a Stefan Weil
367 66f82cee Kevin Wolf
static int vdi_open(BlockDriverState *bs, int flags)
368 9aebd98a Stefan Weil
{
369 9aebd98a Stefan Weil
    BDRVVdiState *s = bs->opaque;
370 9aebd98a Stefan Weil
    VdiHeader header;
371 9aebd98a Stefan Weil
    size_t bmap_size;
372 9aebd98a Stefan Weil
373 9aebd98a Stefan Weil
    logout("\n");
374 9aebd98a Stefan Weil
375 66f82cee Kevin Wolf
    if (bdrv_read(bs->file, 0, (uint8_t *)&header, 1) < 0) {
376 9aebd98a Stefan Weil
        goto fail;
377 9aebd98a Stefan Weil
    }
378 9aebd98a Stefan Weil
379 9aebd98a Stefan Weil
    vdi_header_to_cpu(&header);
380 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_DEBUG)
381 9aebd98a Stefan Weil
    vdi_header_print(&header);
382 9aebd98a Stefan Weil
#endif
383 9aebd98a Stefan Weil
384 f21dc3a4 Stefan Weil
    if (header.disk_size % SECTOR_SIZE != 0) {
385 f21dc3a4 Stefan Weil
        /* 'VBoxManage convertfromraw' can create images with odd disk sizes.
386 f21dc3a4 Stefan Weil
           We accept them but round the disk size to the next multiple of
387 f21dc3a4 Stefan Weil
           SECTOR_SIZE. */
388 f21dc3a4 Stefan Weil
        logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);
389 f21dc3a4 Stefan Weil
        header.disk_size += SECTOR_SIZE - 1;
390 f21dc3a4 Stefan Weil
        header.disk_size &= ~(SECTOR_SIZE - 1);
391 f21dc3a4 Stefan Weil
    }
392 f21dc3a4 Stefan Weil
393 9aebd98a Stefan Weil
    if (header.version != VDI_VERSION_1_1) {
394 9aebd98a Stefan Weil
        logout("unsupported version %u.%u\n",
395 9aebd98a Stefan Weil
               header.version >> 16, header.version & 0xffff);
396 9aebd98a Stefan Weil
        goto fail;
397 9aebd98a Stefan Weil
    } else if (header.offset_bmap % SECTOR_SIZE != 0) {
398 9aebd98a Stefan Weil
        /* We only support block maps which start on a sector boundary. */
399 9aebd98a Stefan Weil
        logout("unsupported block map offset 0x%x B\n", header.offset_bmap);
400 9aebd98a Stefan Weil
        goto fail;
401 9aebd98a Stefan Weil
    } else if (header.offset_data % SECTOR_SIZE != 0) {
402 9aebd98a Stefan Weil
        /* We only support data blocks which start on a sector boundary. */
403 9aebd98a Stefan Weil
        logout("unsupported data offset 0x%x B\n", header.offset_data);
404 9aebd98a Stefan Weil
        goto fail;
405 9aebd98a Stefan Weil
    } else if (header.sector_size != SECTOR_SIZE) {
406 9aebd98a Stefan Weil
        logout("unsupported sector size %u B\n", header.sector_size);
407 9aebd98a Stefan Weil
        goto fail;
408 9aebd98a Stefan Weil
    } else if (header.block_size != 1 * MiB) {
409 9aebd98a Stefan Weil
        logout("unsupported block size %u B\n", header.block_size);
410 9aebd98a Stefan Weil
        goto fail;
411 f21dc3a4 Stefan Weil
    } else if (header.disk_size >
412 f21dc3a4 Stefan Weil
               (uint64_t)header.blocks_in_image * header.block_size) {
413 f21dc3a4 Stefan Weil
        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
414 9aebd98a Stefan Weil
        goto fail;
415 9aebd98a Stefan Weil
    } else if (!uuid_is_null(header.uuid_link)) {
416 9aebd98a Stefan Weil
        logout("link uuid != 0, unsupported\n");
417 9aebd98a Stefan Weil
        goto fail;
418 9aebd98a Stefan Weil
    } else if (!uuid_is_null(header.uuid_parent)) {
419 9aebd98a Stefan Weil
        logout("parent uuid != 0, unsupported\n");
420 9aebd98a Stefan Weil
        goto fail;
421 9aebd98a Stefan Weil
    }
422 9aebd98a Stefan Weil
423 9aebd98a Stefan Weil
    bs->total_sectors = header.disk_size / SECTOR_SIZE;
424 9aebd98a Stefan Weil
425 9aebd98a Stefan Weil
    s->block_size = header.block_size;
426 9aebd98a Stefan Weil
    s->block_sectors = header.block_size / SECTOR_SIZE;
427 9aebd98a Stefan Weil
    s->bmap_sector = header.offset_bmap / SECTOR_SIZE;
428 9aebd98a Stefan Weil
    s->header = header;
429 9aebd98a Stefan Weil
430 9aebd98a Stefan Weil
    bmap_size = header.blocks_in_image * sizeof(uint32_t);
431 6eea90eb Stefan Weil
    bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
432 b76b6e95 Stefan Weil
    if (bmap_size > 0) {
433 7267c094 Anthony Liguori
        s->bmap = g_malloc(bmap_size * SECTOR_SIZE);
434 b76b6e95 Stefan Weil
    }
435 66f82cee Kevin Wolf
    if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
436 9aebd98a Stefan Weil
        goto fail_free_bmap;
437 9aebd98a Stefan Weil
    }
438 9aebd98a Stefan Weil
439 fc9d106c Kevin Wolf
    /* Disable migration when vdi images are used */
440 fc9d106c Kevin Wolf
    error_set(&s->migration_blocker,
441 fc9d106c Kevin Wolf
              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
442 fc9d106c Kevin Wolf
              "vdi", bs->device_name, "live migration");
443 fc9d106c Kevin Wolf
    migrate_add_blocker(s->migration_blocker);
444 fc9d106c Kevin Wolf
445 9aebd98a Stefan Weil
    return 0;
446 9aebd98a Stefan Weil
447 9aebd98a Stefan Weil
 fail_free_bmap:
448 7267c094 Anthony Liguori
    g_free(s->bmap);
449 9aebd98a Stefan Weil
450 9aebd98a Stefan Weil
 fail:
451 9aebd98a Stefan Weil
    return -1;
452 9aebd98a Stefan Weil
}
453 9aebd98a Stefan Weil
454 ecfe2bba Jeff Cody
static int vdi_reopen_prepare(BDRVReopenState *state,
455 ecfe2bba Jeff Cody
                              BlockReopenQueue *queue, Error **errp)
456 ecfe2bba Jeff Cody
{
457 ecfe2bba Jeff Cody
    return 0;
458 ecfe2bba Jeff Cody
}
459 ecfe2bba Jeff Cody
460 e850b35a Stefan Hajnoczi
static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
461 e850b35a Stefan Hajnoczi
        int64_t sector_num, int nb_sectors, int *pnum)
462 9aebd98a Stefan Weil
{
463 9aebd98a Stefan Weil
    /* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */
464 9aebd98a Stefan Weil
    BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
465 9aebd98a Stefan Weil
    size_t bmap_index = sector_num / s->block_sectors;
466 9aebd98a Stefan Weil
    size_t sector_in_block = sector_num % s->block_sectors;
467 9aebd98a Stefan Weil
    int n_sectors = s->block_sectors - sector_in_block;
468 9aebd98a Stefan Weil
    uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
469 9aebd98a Stefan Weil
    logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
470 9aebd98a Stefan Weil
    if (n_sectors > nb_sectors) {
471 9aebd98a Stefan Weil
        n_sectors = nb_sectors;
472 9aebd98a Stefan Weil
    }
473 9aebd98a Stefan Weil
    *pnum = n_sectors;
474 c794b4e0 Eric Sunshine
    return VDI_IS_ALLOCATED(bmap_entry);
475 9aebd98a Stefan Weil
}
476 9aebd98a Stefan Weil
477 a7a43aa1 Paolo Bonzini
static int vdi_co_read(BlockDriverState *bs,
478 a7a43aa1 Paolo Bonzini
        int64_t sector_num, uint8_t *buf, int nb_sectors)
479 9aebd98a Stefan Weil
{
480 9aebd98a Stefan Weil
    BDRVVdiState *s = bs->opaque;
481 9aebd98a Stefan Weil
    uint32_t bmap_entry;
482 9aebd98a Stefan Weil
    uint32_t block_index;
483 9aebd98a Stefan Weil
    uint32_t sector_in_block;
484 9aebd98a Stefan Weil
    uint32_t n_sectors;
485 eb9566d1 Paolo Bonzini
    int ret = 0;
486 4de659e8 Paolo Bonzini
487 4de659e8 Paolo Bonzini
    logout("\n");
488 9aebd98a Stefan Weil
489 eb9566d1 Paolo Bonzini
    while (ret >= 0 && nb_sectors > 0) {
490 eb9566d1 Paolo Bonzini
        block_index = sector_num / s->block_sectors;
491 eb9566d1 Paolo Bonzini
        sector_in_block = sector_num % s->block_sectors;
492 eb9566d1 Paolo Bonzini
        n_sectors = s->block_sectors - sector_in_block;
493 eb9566d1 Paolo Bonzini
        if (n_sectors > nb_sectors) {
494 eb9566d1 Paolo Bonzini
            n_sectors = nb_sectors;
495 eb9566d1 Paolo Bonzini
        }
496 0c7bfc32 Paolo Bonzini
497 eb9566d1 Paolo Bonzini
        logout("will read %u sectors starting at sector %" PRIu64 "\n",
498 eb9566d1 Paolo Bonzini
               n_sectors, sector_num);
499 eb9566d1 Paolo Bonzini
500 eb9566d1 Paolo Bonzini
        /* prepare next AIO request */
501 eb9566d1 Paolo Bonzini
        bmap_entry = le32_to_cpu(s->bmap[block_index]);
502 eb9566d1 Paolo Bonzini
        if (!VDI_IS_ALLOCATED(bmap_entry)) {
503 eb9566d1 Paolo Bonzini
            /* Block not allocated, return zeros, no need to wait. */
504 eb9566d1 Paolo Bonzini
            memset(buf, 0, n_sectors * SECTOR_SIZE);
505 eb9566d1 Paolo Bonzini
            ret = 0;
506 eb9566d1 Paolo Bonzini
        } else {
507 eb9566d1 Paolo Bonzini
            uint64_t offset = s->header.offset_data / SECTOR_SIZE +
508 eb9566d1 Paolo Bonzini
                              (uint64_t)bmap_entry * s->block_sectors +
509 eb9566d1 Paolo Bonzini
                              sector_in_block;
510 eb9566d1 Paolo Bonzini
            ret = bdrv_read(bs->file, offset, buf, n_sectors);
511 eb9566d1 Paolo Bonzini
        }
512 eb9566d1 Paolo Bonzini
        logout("%u sectors read\n", n_sectors);
513 0c7bfc32 Paolo Bonzini
514 eb9566d1 Paolo Bonzini
        nb_sectors -= n_sectors;
515 eb9566d1 Paolo Bonzini
        sector_num += n_sectors;
516 eb9566d1 Paolo Bonzini
        buf += n_sectors * SECTOR_SIZE;
517 9aebd98a Stefan Weil
    }
518 3d46a75a Paolo Bonzini
519 3d46a75a Paolo Bonzini
    return ret;
520 9aebd98a Stefan Weil
}
521 9aebd98a Stefan Weil
522 a7a43aa1 Paolo Bonzini
static int vdi_co_write(BlockDriverState *bs,
523 a7a43aa1 Paolo Bonzini
        int64_t sector_num, const uint8_t *buf, int nb_sectors)
524 9aebd98a Stefan Weil
{
525 9aebd98a Stefan Weil
    BDRVVdiState *s = bs->opaque;
526 9aebd98a Stefan Weil
    uint32_t bmap_entry;
527 9aebd98a Stefan Weil
    uint32_t block_index;
528 9aebd98a Stefan Weil
    uint32_t sector_in_block;
529 9aebd98a Stefan Weil
    uint32_t n_sectors;
530 bfc45fc1 Paolo Bonzini
    uint32_t bmap_first = VDI_UNALLOCATED;
531 bfc45fc1 Paolo Bonzini
    uint32_t bmap_last = VDI_UNALLOCATED;
532 bfc45fc1 Paolo Bonzini
    uint8_t *block = NULL;
533 eb9566d1 Paolo Bonzini
    int ret = 0;
534 4de659e8 Paolo Bonzini
535 4de659e8 Paolo Bonzini
    logout("\n");
536 9aebd98a Stefan Weil
537 eb9566d1 Paolo Bonzini
    while (ret >= 0 && nb_sectors > 0) {
538 eb9566d1 Paolo Bonzini
        block_index = sector_num / s->block_sectors;
539 eb9566d1 Paolo Bonzini
        sector_in_block = sector_num % s->block_sectors;
540 eb9566d1 Paolo Bonzini
        n_sectors = s->block_sectors - sector_in_block;
541 eb9566d1 Paolo Bonzini
        if (n_sectors > nb_sectors) {
542 eb9566d1 Paolo Bonzini
            n_sectors = nb_sectors;
543 eb9566d1 Paolo Bonzini
        }
544 9aebd98a Stefan Weil
545 eb9566d1 Paolo Bonzini
        logout("will write %u sectors starting at sector %" PRIu64 "\n",
546 eb9566d1 Paolo Bonzini
               n_sectors, sector_num);
547 eb9566d1 Paolo Bonzini
548 eb9566d1 Paolo Bonzini
        /* prepare next AIO request */
549 eb9566d1 Paolo Bonzini
        bmap_entry = le32_to_cpu(s->bmap[block_index]);
550 eb9566d1 Paolo Bonzini
        if (!VDI_IS_ALLOCATED(bmap_entry)) {
551 eb9566d1 Paolo Bonzini
            /* Allocate new block and write to it. */
552 eb9566d1 Paolo Bonzini
            uint64_t offset;
553 eb9566d1 Paolo Bonzini
            bmap_entry = s->header.blocks_allocated;
554 eb9566d1 Paolo Bonzini
            s->bmap[block_index] = cpu_to_le32(bmap_entry);
555 eb9566d1 Paolo Bonzini
            s->header.blocks_allocated++;
556 eb9566d1 Paolo Bonzini
            offset = s->header.offset_data / SECTOR_SIZE +
557 eb9566d1 Paolo Bonzini
                     (uint64_t)bmap_entry * s->block_sectors;
558 eb9566d1 Paolo Bonzini
            if (block == NULL) {
559 eb9566d1 Paolo Bonzini
                block = g_malloc(s->block_size);
560 eb9566d1 Paolo Bonzini
                bmap_first = block_index;
561 eb9566d1 Paolo Bonzini
            }
562 eb9566d1 Paolo Bonzini
            bmap_last = block_index;
563 eb9566d1 Paolo Bonzini
            /* Copy data to be written to new block and zero unused parts. */
564 eb9566d1 Paolo Bonzini
            memset(block, 0, sector_in_block * SECTOR_SIZE);
565 eb9566d1 Paolo Bonzini
            memcpy(block + sector_in_block * SECTOR_SIZE,
566 eb9566d1 Paolo Bonzini
                   buf, n_sectors * SECTOR_SIZE);
567 eb9566d1 Paolo Bonzini
            memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
568 eb9566d1 Paolo Bonzini
                   (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
569 eb9566d1 Paolo Bonzini
            ret = bdrv_write(bs->file, offset, block, s->block_sectors);
570 eb9566d1 Paolo Bonzini
        } else {
571 eb9566d1 Paolo Bonzini
            uint64_t offset = s->header.offset_data / SECTOR_SIZE +
572 eb9566d1 Paolo Bonzini
                              (uint64_t)bmap_entry * s->block_sectors +
573 eb9566d1 Paolo Bonzini
                              sector_in_block;
574 eb9566d1 Paolo Bonzini
            ret = bdrv_write(bs->file, offset, buf, n_sectors);
575 9aebd98a Stefan Weil
        }
576 0c7bfc32 Paolo Bonzini
577 eb9566d1 Paolo Bonzini
        nb_sectors -= n_sectors;
578 eb9566d1 Paolo Bonzini
        sector_num += n_sectors;
579 eb9566d1 Paolo Bonzini
        buf += n_sectors * SECTOR_SIZE;
580 0c7bfc32 Paolo Bonzini
581 eb9566d1 Paolo Bonzini
        logout("%u sectors written\n", n_sectors);
582 9aebd98a Stefan Weil
    }
583 9aebd98a Stefan Weil
584 0c7bfc32 Paolo Bonzini
    logout("finished data write\n");
585 4eea78e6 Paolo Bonzini
    if (ret < 0) {
586 4eea78e6 Paolo Bonzini
        return ret;
587 4eea78e6 Paolo Bonzini
    }
588 4eea78e6 Paolo Bonzini
589 4eea78e6 Paolo Bonzini
    if (block) {
590 4eea78e6 Paolo Bonzini
        /* One or more new blocks were allocated. */
591 4eea78e6 Paolo Bonzini
        VdiHeader *header = (VdiHeader *) block;
592 4eea78e6 Paolo Bonzini
        uint8_t *base;
593 4eea78e6 Paolo Bonzini
        uint64_t offset;
594 4eea78e6 Paolo Bonzini
595 4eea78e6 Paolo Bonzini
        logout("now writing modified header\n");
596 4eea78e6 Paolo Bonzini
        assert(VDI_IS_ALLOCATED(bmap_first));
597 4eea78e6 Paolo Bonzini
        *header = s->header;
598 4eea78e6 Paolo Bonzini
        vdi_header_to_le(header);
599 4eea78e6 Paolo Bonzini
        ret = bdrv_write(bs->file, 0, block, 1);
600 bfc45fc1 Paolo Bonzini
        g_free(block);
601 bfc45fc1 Paolo Bonzini
        block = NULL;
602 4eea78e6 Paolo Bonzini
603 4eea78e6 Paolo Bonzini
        if (ret < 0) {
604 4eea78e6 Paolo Bonzini
            return ret;
605 0c7bfc32 Paolo Bonzini
        }
606 4eea78e6 Paolo Bonzini
607 4eea78e6 Paolo Bonzini
        logout("now writing modified block map entry %u...%u\n",
608 4eea78e6 Paolo Bonzini
               bmap_first, bmap_last);
609 4eea78e6 Paolo Bonzini
        /* Write modified sectors from block map. */
610 4eea78e6 Paolo Bonzini
        bmap_first /= (SECTOR_SIZE / sizeof(uint32_t));
611 4eea78e6 Paolo Bonzini
        bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
612 4eea78e6 Paolo Bonzini
        n_sectors = bmap_last - bmap_first + 1;
613 4eea78e6 Paolo Bonzini
        offset = s->bmap_sector + bmap_first;
614 4eea78e6 Paolo Bonzini
        base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
615 4eea78e6 Paolo Bonzini
        logout("will write %u block map sectors starting from entry %u\n",
616 4eea78e6 Paolo Bonzini
               n_sectors, bmap_first);
617 4eea78e6 Paolo Bonzini
        ret = bdrv_write(bs->file, offset, base, n_sectors);
618 0c7bfc32 Paolo Bonzini
    }
619 0c7bfc32 Paolo Bonzini
620 3d46a75a Paolo Bonzini
    return ret;
621 9aebd98a Stefan Weil
}
622 9aebd98a Stefan Weil
623 9aebd98a Stefan Weil
static int vdi_create(const char *filename, QEMUOptionParameter *options)
624 9aebd98a Stefan Weil
{
625 9aebd98a Stefan Weil
    int fd;
626 9aebd98a Stefan Weil
    int result = 0;
627 9aebd98a Stefan Weil
    uint64_t bytes = 0;
628 9aebd98a Stefan Weil
    uint32_t blocks;
629 99cce9fa Kevin Wolf
    size_t block_size = DEFAULT_CLUSTER_SIZE;
630 9aebd98a Stefan Weil
    uint32_t image_type = VDI_TYPE_DYNAMIC;
631 9aebd98a Stefan Weil
    VdiHeader header;
632 9aebd98a Stefan Weil
    size_t i;
633 9aebd98a Stefan Weil
    size_t bmap_size;
634 9aebd98a Stefan Weil
635 9aebd98a Stefan Weil
    logout("\n");
636 9aebd98a Stefan Weil
637 9aebd98a Stefan Weil
    /* Read out options. */
638 9aebd98a Stefan Weil
    while (options && options->name) {
639 9aebd98a Stefan Weil
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
640 9aebd98a Stefan Weil
            bytes = options->value.n;
641 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_BLOCK_SIZE)
642 9aebd98a Stefan Weil
        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
643 9aebd98a Stefan Weil
            if (options->value.n) {
644 9aebd98a Stefan Weil
                /* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
645 9aebd98a Stefan Weil
                block_size = options->value.n;
646 9aebd98a Stefan Weil
            }
647 9aebd98a Stefan Weil
#endif
648 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_STATIC_IMAGE)
649 9aebd98a Stefan Weil
        } else if (!strcmp(options->name, BLOCK_OPT_STATIC)) {
650 6eea90eb Stefan Weil
            if (options->value.n) {
651 6eea90eb Stefan Weil
                image_type = VDI_TYPE_STATIC;
652 6eea90eb Stefan Weil
            }
653 9aebd98a Stefan Weil
#endif
654 9aebd98a Stefan Weil
        }
655 9aebd98a Stefan Weil
        options++;
656 9aebd98a Stefan Weil
    }
657 9aebd98a Stefan Weil
658 6165f4d8 Corey Bryant
    fd = qemu_open(filename,
659 6165f4d8 Corey Bryant
                   O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
660 6165f4d8 Corey Bryant
                   0644);
661 9aebd98a Stefan Weil
    if (fd < 0) {
662 9aebd98a Stefan Weil
        return -errno;
663 9aebd98a Stefan Weil
    }
664 9aebd98a Stefan Weil
665 f21dc3a4 Stefan Weil
    /* We need enough blocks to store the given disk size,
666 f21dc3a4 Stefan Weil
       so always round up. */
667 f21dc3a4 Stefan Weil
    blocks = (bytes + block_size - 1) / block_size;
668 f21dc3a4 Stefan Weil
669 9aebd98a Stefan Weil
    bmap_size = blocks * sizeof(uint32_t);
670 9aebd98a Stefan Weil
    bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1));
671 9aebd98a Stefan Weil
672 9aebd98a Stefan Weil
    memset(&header, 0, sizeof(header));
673 1786dc15 Blue Swirl
    pstrcpy(header.text, sizeof(header.text), VDI_TEXT);
674 9aebd98a Stefan Weil
    header.signature = VDI_SIGNATURE;
675 9aebd98a Stefan Weil
    header.version = VDI_VERSION_1_1;
676 9aebd98a Stefan Weil
    header.header_size = 0x180;
677 9aebd98a Stefan Weil
    header.image_type = image_type;
678 9aebd98a Stefan Weil
    header.offset_bmap = 0x200;
679 9aebd98a Stefan Weil
    header.offset_data = 0x200 + bmap_size;
680 9aebd98a Stefan Weil
    header.sector_size = SECTOR_SIZE;
681 9aebd98a Stefan Weil
    header.disk_size = bytes;
682 9aebd98a Stefan Weil
    header.block_size = block_size;
683 9aebd98a Stefan Weil
    header.blocks_in_image = blocks;
684 6eea90eb Stefan Weil
    if (image_type == VDI_TYPE_STATIC) {
685 6eea90eb Stefan Weil
        header.blocks_allocated = blocks;
686 6eea90eb Stefan Weil
    }
687 9aebd98a Stefan Weil
    uuid_generate(header.uuid_image);
688 9aebd98a Stefan Weil
    uuid_generate(header.uuid_last_snap);
689 9aebd98a Stefan Weil
    /* There is no need to set header.uuid_link or header.uuid_parent here. */
690 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_DEBUG)
691 9aebd98a Stefan Weil
    vdi_header_print(&header);
692 9aebd98a Stefan Weil
#endif
693 9aebd98a Stefan Weil
    vdi_header_to_le(&header);
694 9aebd98a Stefan Weil
    if (write(fd, &header, sizeof(header)) < 0) {
695 9aebd98a Stefan Weil
        result = -errno;
696 9aebd98a Stefan Weil
    }
697 9aebd98a Stefan Weil
698 b76b6e95 Stefan Weil
    if (bmap_size > 0) {
699 514f21a5 Stefan Weil
        uint32_t *bmap = g_malloc0(bmap_size);
700 514f21a5 Stefan Weil
        for (i = 0; i < blocks; i++) {
701 514f21a5 Stefan Weil
            if (image_type == VDI_TYPE_STATIC) {
702 514f21a5 Stefan Weil
                bmap[i] = i;
703 514f21a5 Stefan Weil
            } else {
704 514f21a5 Stefan Weil
                bmap[i] = VDI_UNALLOCATED;
705 514f21a5 Stefan Weil
            }
706 9aebd98a Stefan Weil
        }
707 514f21a5 Stefan Weil
        if (write(fd, bmap, bmap_size) < 0) {
708 514f21a5 Stefan Weil
            result = -errno;
709 514f21a5 Stefan Weil
        }
710 514f21a5 Stefan Weil
        g_free(bmap);
711 9aebd98a Stefan Weil
    }
712 514f21a5 Stefan Weil
713 9aebd98a Stefan Weil
    if (image_type == VDI_TYPE_STATIC) {
714 9aebd98a Stefan Weil
        if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
715 9aebd98a Stefan Weil
            result = -errno;
716 9aebd98a Stefan Weil
        }
717 9aebd98a Stefan Weil
    }
718 9aebd98a Stefan Weil
719 9aebd98a Stefan Weil
    if (close(fd) < 0) {
720 9aebd98a Stefan Weil
        result = -errno;
721 9aebd98a Stefan Weil
    }
722 9aebd98a Stefan Weil
723 9aebd98a Stefan Weil
    return result;
724 9aebd98a Stefan Weil
}
725 9aebd98a Stefan Weil
726 9aebd98a Stefan Weil
static void vdi_close(BlockDriverState *bs)
727 9aebd98a Stefan Weil
{
728 fc9d106c Kevin Wolf
    BDRVVdiState *s = bs->opaque;
729 6ac5f388 Kevin Wolf
730 6ac5f388 Kevin Wolf
    g_free(s->bmap);
731 6ac5f388 Kevin Wolf
732 fc9d106c Kevin Wolf
    migrate_del_blocker(s->migration_blocker);
733 fc9d106c Kevin Wolf
    error_free(s->migration_blocker);
734 9aebd98a Stefan Weil
}
735 9aebd98a Stefan Weil
736 9aebd98a Stefan Weil
static QEMUOptionParameter vdi_create_options[] = {
737 9aebd98a Stefan Weil
    {
738 9aebd98a Stefan Weil
        .name = BLOCK_OPT_SIZE,
739 9aebd98a Stefan Weil
        .type = OPT_SIZE,
740 9aebd98a Stefan Weil
        .help = "Virtual disk size"
741 9aebd98a Stefan Weil
    },
742 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_BLOCK_SIZE)
743 9aebd98a Stefan Weil
    {
744 9aebd98a Stefan Weil
        .name = BLOCK_OPT_CLUSTER_SIZE,
745 9aebd98a Stefan Weil
        .type = OPT_SIZE,
746 99cce9fa Kevin Wolf
        .help = "VDI cluster (block) size",
747 99cce9fa Kevin Wolf
        .value = { .n = DEFAULT_CLUSTER_SIZE },
748 9aebd98a Stefan Weil
    },
749 9aebd98a Stefan Weil
#endif
750 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_STATIC_IMAGE)
751 9aebd98a Stefan Weil
    {
752 9aebd98a Stefan Weil
        .name = BLOCK_OPT_STATIC,
753 9aebd98a Stefan Weil
        .type = OPT_FLAG,
754 9aebd98a Stefan Weil
        .help = "VDI static (pre-allocated) image"
755 9aebd98a Stefan Weil
    },
756 9aebd98a Stefan Weil
#endif
757 9aebd98a Stefan Weil
    /* TODO: An additional option to set UUID values might be useful. */
758 9aebd98a Stefan Weil
    { NULL }
759 9aebd98a Stefan Weil
};
760 9aebd98a Stefan Weil
761 9aebd98a Stefan Weil
static BlockDriver bdrv_vdi = {
762 9aebd98a Stefan Weil
    .format_name = "vdi",
763 9aebd98a Stefan Weil
    .instance_size = sizeof(BDRVVdiState),
764 9aebd98a Stefan Weil
    .bdrv_probe = vdi_probe,
765 9aebd98a Stefan Weil
    .bdrv_open = vdi_open,
766 9aebd98a Stefan Weil
    .bdrv_close = vdi_close,
767 ecfe2bba Jeff Cody
    .bdrv_reopen_prepare = vdi_reopen_prepare,
768 9aebd98a Stefan Weil
    .bdrv_create = vdi_create,
769 e850b35a Stefan Hajnoczi
    .bdrv_co_is_allocated = vdi_co_is_allocated,
770 9aebd98a Stefan Weil
    .bdrv_make_empty = vdi_make_empty,
771 9aebd98a Stefan Weil
772 a7a43aa1 Paolo Bonzini
    .bdrv_read = vdi_co_read,
773 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_WRITE)
774 a7a43aa1 Paolo Bonzini
    .bdrv_write = vdi_co_write,
775 9aebd98a Stefan Weil
#endif
776 9aebd98a Stefan Weil
777 9aebd98a Stefan Weil
    .bdrv_get_info = vdi_get_info,
778 9aebd98a Stefan Weil
779 9aebd98a Stefan Weil
    .create_options = vdi_create_options,
780 9aebd98a Stefan Weil
    .bdrv_check = vdi_check,
781 9aebd98a Stefan Weil
};
782 9aebd98a Stefan Weil
783 9aebd98a Stefan Weil
static void bdrv_vdi_init(void)
784 9aebd98a Stefan Weil
{
785 9aebd98a Stefan Weil
    logout("\n");
786 9aebd98a Stefan Weil
    bdrv_register(&bdrv_vdi);
787 9aebd98a Stefan Weil
}
788 9aebd98a Stefan Weil
789 9aebd98a Stefan Weil
block_init(bdrv_vdi_init);