Statistics
| Branch: | Revision:

root / block / vdi.c @ c4d9d196

History | View | Annotate | Download (24.7 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 9f0470bb Stefan Weil
    logout("signature   0x%08x\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 1a86938f Kevin Wolf
static int vdi_open(BlockDriverState *bs, QDict *options, 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 8937f822 Stefan Weil
    int ret;
373 9aebd98a Stefan Weil
374 9aebd98a Stefan Weil
    logout("\n");
375 9aebd98a Stefan Weil
376 8937f822 Stefan Weil
    ret = bdrv_read(bs->file, 0, (uint8_t *)&header, 1);
377 8937f822 Stefan Weil
    if (ret < 0) {
378 9aebd98a Stefan Weil
        goto fail;
379 9aebd98a Stefan Weil
    }
380 9aebd98a Stefan Weil
381 9aebd98a Stefan Weil
    vdi_header_to_cpu(&header);
382 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_DEBUG)
383 9aebd98a Stefan Weil
    vdi_header_print(&header);
384 9aebd98a Stefan Weil
#endif
385 9aebd98a Stefan Weil
386 f21dc3a4 Stefan Weil
    if (header.disk_size % SECTOR_SIZE != 0) {
387 f21dc3a4 Stefan Weil
        /* 'VBoxManage convertfromraw' can create images with odd disk sizes.
388 f21dc3a4 Stefan Weil
           We accept them but round the disk size to the next multiple of
389 f21dc3a4 Stefan Weil
           SECTOR_SIZE. */
390 f21dc3a4 Stefan Weil
        logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);
391 f21dc3a4 Stefan Weil
        header.disk_size += SECTOR_SIZE - 1;
392 f21dc3a4 Stefan Weil
        header.disk_size &= ~(SECTOR_SIZE - 1);
393 f21dc3a4 Stefan Weil
    }
394 f21dc3a4 Stefan Weil
395 0e87ba2c Stefan Weil
    if (header.signature != VDI_SIGNATURE) {
396 0e87ba2c Stefan Weil
        logout("bad vdi signature %08x\n", header.signature);
397 0e87ba2c Stefan Weil
        ret = -EMEDIUMTYPE;
398 0e87ba2c Stefan Weil
        goto fail;
399 0e87ba2c Stefan Weil
    } else if (header.version != VDI_VERSION_1_1) {
400 9aebd98a Stefan Weil
        logout("unsupported version %u.%u\n",
401 9aebd98a Stefan Weil
               header.version >> 16, header.version & 0xffff);
402 8937f822 Stefan Weil
        ret = -ENOTSUP;
403 9aebd98a Stefan Weil
        goto fail;
404 9aebd98a Stefan Weil
    } else if (header.offset_bmap % SECTOR_SIZE != 0) {
405 9aebd98a Stefan Weil
        /* We only support block maps which start on a sector boundary. */
406 9aebd98a Stefan Weil
        logout("unsupported block map offset 0x%x B\n", header.offset_bmap);
407 8937f822 Stefan Weil
        ret = -ENOTSUP;
408 9aebd98a Stefan Weil
        goto fail;
409 9aebd98a Stefan Weil
    } else if (header.offset_data % SECTOR_SIZE != 0) {
410 9aebd98a Stefan Weil
        /* We only support data blocks which start on a sector boundary. */
411 9aebd98a Stefan Weil
        logout("unsupported data offset 0x%x B\n", header.offset_data);
412 8937f822 Stefan Weil
        ret = -ENOTSUP;
413 9aebd98a Stefan Weil
        goto fail;
414 9aebd98a Stefan Weil
    } else if (header.sector_size != SECTOR_SIZE) {
415 9aebd98a Stefan Weil
        logout("unsupported sector size %u B\n", header.sector_size);
416 8937f822 Stefan Weil
        ret = -ENOTSUP;
417 9aebd98a Stefan Weil
        goto fail;
418 9aebd98a Stefan Weil
    } else if (header.block_size != 1 * MiB) {
419 9aebd98a Stefan Weil
        logout("unsupported block size %u B\n", header.block_size);
420 8937f822 Stefan Weil
        ret = -ENOTSUP;
421 9aebd98a Stefan Weil
        goto fail;
422 f21dc3a4 Stefan Weil
    } else if (header.disk_size >
423 f21dc3a4 Stefan Weil
               (uint64_t)header.blocks_in_image * header.block_size) {
424 f21dc3a4 Stefan Weil
        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
425 8937f822 Stefan Weil
        ret = -ENOTSUP;
426 9aebd98a Stefan Weil
        goto fail;
427 9aebd98a Stefan Weil
    } else if (!uuid_is_null(header.uuid_link)) {
428 9aebd98a Stefan Weil
        logout("link uuid != 0, unsupported\n");
429 8937f822 Stefan Weil
        ret = -ENOTSUP;
430 9aebd98a Stefan Weil
        goto fail;
431 9aebd98a Stefan Weil
    } else if (!uuid_is_null(header.uuid_parent)) {
432 9aebd98a Stefan Weil
        logout("parent uuid != 0, unsupported\n");
433 8937f822 Stefan Weil
        ret = -ENOTSUP;
434 9aebd98a Stefan Weil
        goto fail;
435 9aebd98a Stefan Weil
    }
436 9aebd98a Stefan Weil
437 9aebd98a Stefan Weil
    bs->total_sectors = header.disk_size / SECTOR_SIZE;
438 9aebd98a Stefan Weil
439 9aebd98a Stefan Weil
    s->block_size = header.block_size;
440 9aebd98a Stefan Weil
    s->block_sectors = header.block_size / SECTOR_SIZE;
441 9aebd98a Stefan Weil
    s->bmap_sector = header.offset_bmap / SECTOR_SIZE;
442 9aebd98a Stefan Weil
    s->header = header;
443 9aebd98a Stefan Weil
444 9aebd98a Stefan Weil
    bmap_size = header.blocks_in_image * sizeof(uint32_t);
445 6eea90eb Stefan Weil
    bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
446 6528499f Markus Armbruster
    s->bmap = g_malloc(bmap_size * SECTOR_SIZE);
447 8937f822 Stefan Weil
    ret = bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size);
448 8937f822 Stefan Weil
    if (ret < 0) {
449 9aebd98a Stefan Weil
        goto fail_free_bmap;
450 9aebd98a Stefan Weil
    }
451 9aebd98a Stefan Weil
452 fc9d106c Kevin Wolf
    /* Disable migration when vdi images are used */
453 fc9d106c Kevin Wolf
    error_set(&s->migration_blocker,
454 fc9d106c Kevin Wolf
              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
455 fc9d106c Kevin Wolf
              "vdi", bs->device_name, "live migration");
456 fc9d106c Kevin Wolf
    migrate_add_blocker(s->migration_blocker);
457 fc9d106c Kevin Wolf
458 9aebd98a Stefan Weil
    return 0;
459 9aebd98a Stefan Weil
460 9aebd98a Stefan Weil
 fail_free_bmap:
461 7267c094 Anthony Liguori
    g_free(s->bmap);
462 9aebd98a Stefan Weil
463 9aebd98a Stefan Weil
 fail:
464 8937f822 Stefan Weil
    return ret;
465 9aebd98a Stefan Weil
}
466 9aebd98a Stefan Weil
467 ecfe2bba Jeff Cody
static int vdi_reopen_prepare(BDRVReopenState *state,
468 ecfe2bba Jeff Cody
                              BlockReopenQueue *queue, Error **errp)
469 ecfe2bba Jeff Cody
{
470 ecfe2bba Jeff Cody
    return 0;
471 ecfe2bba Jeff Cody
}
472 ecfe2bba Jeff Cody
473 e850b35a Stefan Hajnoczi
static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
474 e850b35a Stefan Hajnoczi
        int64_t sector_num, int nb_sectors, int *pnum)
475 9aebd98a Stefan Weil
{
476 9aebd98a Stefan Weil
    /* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */
477 9aebd98a Stefan Weil
    BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
478 9aebd98a Stefan Weil
    size_t bmap_index = sector_num / s->block_sectors;
479 9aebd98a Stefan Weil
    size_t sector_in_block = sector_num % s->block_sectors;
480 9aebd98a Stefan Weil
    int n_sectors = s->block_sectors - sector_in_block;
481 9aebd98a Stefan Weil
    uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
482 9aebd98a Stefan Weil
    logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
483 9aebd98a Stefan Weil
    if (n_sectors > nb_sectors) {
484 9aebd98a Stefan Weil
        n_sectors = nb_sectors;
485 9aebd98a Stefan Weil
    }
486 9aebd98a Stefan Weil
    *pnum = n_sectors;
487 c794b4e0 Eric Sunshine
    return VDI_IS_ALLOCATED(bmap_entry);
488 9aebd98a Stefan Weil
}
489 9aebd98a Stefan Weil
490 a7a43aa1 Paolo Bonzini
static int vdi_co_read(BlockDriverState *bs,
491 a7a43aa1 Paolo Bonzini
        int64_t sector_num, uint8_t *buf, int nb_sectors)
492 9aebd98a Stefan Weil
{
493 9aebd98a Stefan Weil
    BDRVVdiState *s = bs->opaque;
494 9aebd98a Stefan Weil
    uint32_t bmap_entry;
495 9aebd98a Stefan Weil
    uint32_t block_index;
496 9aebd98a Stefan Weil
    uint32_t sector_in_block;
497 9aebd98a Stefan Weil
    uint32_t n_sectors;
498 eb9566d1 Paolo Bonzini
    int ret = 0;
499 4de659e8 Paolo Bonzini
500 4de659e8 Paolo Bonzini
    logout("\n");
501 9aebd98a Stefan Weil
502 eb9566d1 Paolo Bonzini
    while (ret >= 0 && nb_sectors > 0) {
503 eb9566d1 Paolo Bonzini
        block_index = sector_num / s->block_sectors;
504 eb9566d1 Paolo Bonzini
        sector_in_block = sector_num % s->block_sectors;
505 eb9566d1 Paolo Bonzini
        n_sectors = s->block_sectors - sector_in_block;
506 eb9566d1 Paolo Bonzini
        if (n_sectors > nb_sectors) {
507 eb9566d1 Paolo Bonzini
            n_sectors = nb_sectors;
508 eb9566d1 Paolo Bonzini
        }
509 0c7bfc32 Paolo Bonzini
510 eb9566d1 Paolo Bonzini
        logout("will read %u sectors starting at sector %" PRIu64 "\n",
511 eb9566d1 Paolo Bonzini
               n_sectors, sector_num);
512 eb9566d1 Paolo Bonzini
513 eb9566d1 Paolo Bonzini
        /* prepare next AIO request */
514 eb9566d1 Paolo Bonzini
        bmap_entry = le32_to_cpu(s->bmap[block_index]);
515 eb9566d1 Paolo Bonzini
        if (!VDI_IS_ALLOCATED(bmap_entry)) {
516 eb9566d1 Paolo Bonzini
            /* Block not allocated, return zeros, no need to wait. */
517 eb9566d1 Paolo Bonzini
            memset(buf, 0, n_sectors * SECTOR_SIZE);
518 eb9566d1 Paolo Bonzini
            ret = 0;
519 eb9566d1 Paolo Bonzini
        } else {
520 eb9566d1 Paolo Bonzini
            uint64_t offset = s->header.offset_data / SECTOR_SIZE +
521 eb9566d1 Paolo Bonzini
                              (uint64_t)bmap_entry * s->block_sectors +
522 eb9566d1 Paolo Bonzini
                              sector_in_block;
523 eb9566d1 Paolo Bonzini
            ret = bdrv_read(bs->file, offset, buf, n_sectors);
524 eb9566d1 Paolo Bonzini
        }
525 eb9566d1 Paolo Bonzini
        logout("%u sectors read\n", n_sectors);
526 0c7bfc32 Paolo Bonzini
527 eb9566d1 Paolo Bonzini
        nb_sectors -= n_sectors;
528 eb9566d1 Paolo Bonzini
        sector_num += n_sectors;
529 eb9566d1 Paolo Bonzini
        buf += n_sectors * SECTOR_SIZE;
530 9aebd98a Stefan Weil
    }
531 3d46a75a Paolo Bonzini
532 3d46a75a Paolo Bonzini
    return ret;
533 9aebd98a Stefan Weil
}
534 9aebd98a Stefan Weil
535 a7a43aa1 Paolo Bonzini
static int vdi_co_write(BlockDriverState *bs,
536 a7a43aa1 Paolo Bonzini
        int64_t sector_num, const uint8_t *buf, int nb_sectors)
537 9aebd98a Stefan Weil
{
538 9aebd98a Stefan Weil
    BDRVVdiState *s = bs->opaque;
539 9aebd98a Stefan Weil
    uint32_t bmap_entry;
540 9aebd98a Stefan Weil
    uint32_t block_index;
541 9aebd98a Stefan Weil
    uint32_t sector_in_block;
542 9aebd98a Stefan Weil
    uint32_t n_sectors;
543 bfc45fc1 Paolo Bonzini
    uint32_t bmap_first = VDI_UNALLOCATED;
544 bfc45fc1 Paolo Bonzini
    uint32_t bmap_last = VDI_UNALLOCATED;
545 bfc45fc1 Paolo Bonzini
    uint8_t *block = NULL;
546 eb9566d1 Paolo Bonzini
    int ret = 0;
547 4de659e8 Paolo Bonzini
548 4de659e8 Paolo Bonzini
    logout("\n");
549 9aebd98a Stefan Weil
550 eb9566d1 Paolo Bonzini
    while (ret >= 0 && nb_sectors > 0) {
551 eb9566d1 Paolo Bonzini
        block_index = sector_num / s->block_sectors;
552 eb9566d1 Paolo Bonzini
        sector_in_block = sector_num % s->block_sectors;
553 eb9566d1 Paolo Bonzini
        n_sectors = s->block_sectors - sector_in_block;
554 eb9566d1 Paolo Bonzini
        if (n_sectors > nb_sectors) {
555 eb9566d1 Paolo Bonzini
            n_sectors = nb_sectors;
556 eb9566d1 Paolo Bonzini
        }
557 9aebd98a Stefan Weil
558 eb9566d1 Paolo Bonzini
        logout("will write %u sectors starting at sector %" PRIu64 "\n",
559 eb9566d1 Paolo Bonzini
               n_sectors, sector_num);
560 eb9566d1 Paolo Bonzini
561 eb9566d1 Paolo Bonzini
        /* prepare next AIO request */
562 eb9566d1 Paolo Bonzini
        bmap_entry = le32_to_cpu(s->bmap[block_index]);
563 eb9566d1 Paolo Bonzini
        if (!VDI_IS_ALLOCATED(bmap_entry)) {
564 eb9566d1 Paolo Bonzini
            /* Allocate new block and write to it. */
565 eb9566d1 Paolo Bonzini
            uint64_t offset;
566 eb9566d1 Paolo Bonzini
            bmap_entry = s->header.blocks_allocated;
567 eb9566d1 Paolo Bonzini
            s->bmap[block_index] = cpu_to_le32(bmap_entry);
568 eb9566d1 Paolo Bonzini
            s->header.blocks_allocated++;
569 eb9566d1 Paolo Bonzini
            offset = s->header.offset_data / SECTOR_SIZE +
570 eb9566d1 Paolo Bonzini
                     (uint64_t)bmap_entry * s->block_sectors;
571 eb9566d1 Paolo Bonzini
            if (block == NULL) {
572 eb9566d1 Paolo Bonzini
                block = g_malloc(s->block_size);
573 eb9566d1 Paolo Bonzini
                bmap_first = block_index;
574 eb9566d1 Paolo Bonzini
            }
575 eb9566d1 Paolo Bonzini
            bmap_last = block_index;
576 eb9566d1 Paolo Bonzini
            /* Copy data to be written to new block and zero unused parts. */
577 eb9566d1 Paolo Bonzini
            memset(block, 0, sector_in_block * SECTOR_SIZE);
578 eb9566d1 Paolo Bonzini
            memcpy(block + sector_in_block * SECTOR_SIZE,
579 eb9566d1 Paolo Bonzini
                   buf, n_sectors * SECTOR_SIZE);
580 eb9566d1 Paolo Bonzini
            memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
581 eb9566d1 Paolo Bonzini
                   (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
582 eb9566d1 Paolo Bonzini
            ret = bdrv_write(bs->file, offset, block, s->block_sectors);
583 eb9566d1 Paolo Bonzini
        } else {
584 eb9566d1 Paolo Bonzini
            uint64_t offset = s->header.offset_data / SECTOR_SIZE +
585 eb9566d1 Paolo Bonzini
                              (uint64_t)bmap_entry * s->block_sectors +
586 eb9566d1 Paolo Bonzini
                              sector_in_block;
587 eb9566d1 Paolo Bonzini
            ret = bdrv_write(bs->file, offset, buf, n_sectors);
588 9aebd98a Stefan Weil
        }
589 0c7bfc32 Paolo Bonzini
590 eb9566d1 Paolo Bonzini
        nb_sectors -= n_sectors;
591 eb9566d1 Paolo Bonzini
        sector_num += n_sectors;
592 eb9566d1 Paolo Bonzini
        buf += n_sectors * SECTOR_SIZE;
593 0c7bfc32 Paolo Bonzini
594 eb9566d1 Paolo Bonzini
        logout("%u sectors written\n", n_sectors);
595 9aebd98a Stefan Weil
    }
596 9aebd98a Stefan Weil
597 0c7bfc32 Paolo Bonzini
    logout("finished data write\n");
598 4eea78e6 Paolo Bonzini
    if (ret < 0) {
599 4eea78e6 Paolo Bonzini
        return ret;
600 4eea78e6 Paolo Bonzini
    }
601 4eea78e6 Paolo Bonzini
602 4eea78e6 Paolo Bonzini
    if (block) {
603 4eea78e6 Paolo Bonzini
        /* One or more new blocks were allocated. */
604 4eea78e6 Paolo Bonzini
        VdiHeader *header = (VdiHeader *) block;
605 4eea78e6 Paolo Bonzini
        uint8_t *base;
606 4eea78e6 Paolo Bonzini
        uint64_t offset;
607 4eea78e6 Paolo Bonzini
608 4eea78e6 Paolo Bonzini
        logout("now writing modified header\n");
609 4eea78e6 Paolo Bonzini
        assert(VDI_IS_ALLOCATED(bmap_first));
610 4eea78e6 Paolo Bonzini
        *header = s->header;
611 4eea78e6 Paolo Bonzini
        vdi_header_to_le(header);
612 4eea78e6 Paolo Bonzini
        ret = bdrv_write(bs->file, 0, block, 1);
613 bfc45fc1 Paolo Bonzini
        g_free(block);
614 bfc45fc1 Paolo Bonzini
        block = NULL;
615 4eea78e6 Paolo Bonzini
616 4eea78e6 Paolo Bonzini
        if (ret < 0) {
617 4eea78e6 Paolo Bonzini
            return ret;
618 0c7bfc32 Paolo Bonzini
        }
619 4eea78e6 Paolo Bonzini
620 4eea78e6 Paolo Bonzini
        logout("now writing modified block map entry %u...%u\n",
621 4eea78e6 Paolo Bonzini
               bmap_first, bmap_last);
622 4eea78e6 Paolo Bonzini
        /* Write modified sectors from block map. */
623 4eea78e6 Paolo Bonzini
        bmap_first /= (SECTOR_SIZE / sizeof(uint32_t));
624 4eea78e6 Paolo Bonzini
        bmap_last /= (SECTOR_SIZE / sizeof(uint32_t));
625 4eea78e6 Paolo Bonzini
        n_sectors = bmap_last - bmap_first + 1;
626 4eea78e6 Paolo Bonzini
        offset = s->bmap_sector + bmap_first;
627 4eea78e6 Paolo Bonzini
        base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
628 4eea78e6 Paolo Bonzini
        logout("will write %u block map sectors starting from entry %u\n",
629 4eea78e6 Paolo Bonzini
               n_sectors, bmap_first);
630 4eea78e6 Paolo Bonzini
        ret = bdrv_write(bs->file, offset, base, n_sectors);
631 0c7bfc32 Paolo Bonzini
    }
632 0c7bfc32 Paolo Bonzini
633 3d46a75a Paolo Bonzini
    return ret;
634 9aebd98a Stefan Weil
}
635 9aebd98a Stefan Weil
636 9aebd98a Stefan Weil
static int vdi_create(const char *filename, QEMUOptionParameter *options)
637 9aebd98a Stefan Weil
{
638 9aebd98a Stefan Weil
    int fd;
639 9aebd98a Stefan Weil
    int result = 0;
640 9aebd98a Stefan Weil
    uint64_t bytes = 0;
641 9aebd98a Stefan Weil
    uint32_t blocks;
642 99cce9fa Kevin Wolf
    size_t block_size = DEFAULT_CLUSTER_SIZE;
643 9aebd98a Stefan Weil
    uint32_t image_type = VDI_TYPE_DYNAMIC;
644 9aebd98a Stefan Weil
    VdiHeader header;
645 9aebd98a Stefan Weil
    size_t i;
646 9aebd98a Stefan Weil
    size_t bmap_size;
647 9aebd98a Stefan Weil
648 9aebd98a Stefan Weil
    logout("\n");
649 9aebd98a Stefan Weil
650 9aebd98a Stefan Weil
    /* Read out options. */
651 9aebd98a Stefan Weil
    while (options && options->name) {
652 9aebd98a Stefan Weil
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
653 9aebd98a Stefan Weil
            bytes = options->value.n;
654 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_BLOCK_SIZE)
655 9aebd98a Stefan Weil
        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
656 9aebd98a Stefan Weil
            if (options->value.n) {
657 9aebd98a Stefan Weil
                /* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
658 9aebd98a Stefan Weil
                block_size = options->value.n;
659 9aebd98a Stefan Weil
            }
660 9aebd98a Stefan Weil
#endif
661 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_STATIC_IMAGE)
662 9aebd98a Stefan Weil
        } else if (!strcmp(options->name, BLOCK_OPT_STATIC)) {
663 6eea90eb Stefan Weil
            if (options->value.n) {
664 6eea90eb Stefan Weil
                image_type = VDI_TYPE_STATIC;
665 6eea90eb Stefan Weil
            }
666 9aebd98a Stefan Weil
#endif
667 9aebd98a Stefan Weil
        }
668 9aebd98a Stefan Weil
        options++;
669 9aebd98a Stefan Weil
    }
670 9aebd98a Stefan Weil
671 6165f4d8 Corey Bryant
    fd = qemu_open(filename,
672 6165f4d8 Corey Bryant
                   O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
673 6165f4d8 Corey Bryant
                   0644);
674 9aebd98a Stefan Weil
    if (fd < 0) {
675 9aebd98a Stefan Weil
        return -errno;
676 9aebd98a Stefan Weil
    }
677 9aebd98a Stefan Weil
678 f21dc3a4 Stefan Weil
    /* We need enough blocks to store the given disk size,
679 f21dc3a4 Stefan Weil
       so always round up. */
680 f21dc3a4 Stefan Weil
    blocks = (bytes + block_size - 1) / block_size;
681 f21dc3a4 Stefan Weil
682 9aebd98a Stefan Weil
    bmap_size = blocks * sizeof(uint32_t);
683 9aebd98a Stefan Weil
    bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1));
684 9aebd98a Stefan Weil
685 9aebd98a Stefan Weil
    memset(&header, 0, sizeof(header));
686 1786dc15 Blue Swirl
    pstrcpy(header.text, sizeof(header.text), VDI_TEXT);
687 9aebd98a Stefan Weil
    header.signature = VDI_SIGNATURE;
688 9aebd98a Stefan Weil
    header.version = VDI_VERSION_1_1;
689 9aebd98a Stefan Weil
    header.header_size = 0x180;
690 9aebd98a Stefan Weil
    header.image_type = image_type;
691 9aebd98a Stefan Weil
    header.offset_bmap = 0x200;
692 9aebd98a Stefan Weil
    header.offset_data = 0x200 + bmap_size;
693 9aebd98a Stefan Weil
    header.sector_size = SECTOR_SIZE;
694 9aebd98a Stefan Weil
    header.disk_size = bytes;
695 9aebd98a Stefan Weil
    header.block_size = block_size;
696 9aebd98a Stefan Weil
    header.blocks_in_image = blocks;
697 6eea90eb Stefan Weil
    if (image_type == VDI_TYPE_STATIC) {
698 6eea90eb Stefan Weil
        header.blocks_allocated = blocks;
699 6eea90eb Stefan Weil
    }
700 9aebd98a Stefan Weil
    uuid_generate(header.uuid_image);
701 9aebd98a Stefan Weil
    uuid_generate(header.uuid_last_snap);
702 9aebd98a Stefan Weil
    /* There is no need to set header.uuid_link or header.uuid_parent here. */
703 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_DEBUG)
704 9aebd98a Stefan Weil
    vdi_header_print(&header);
705 9aebd98a Stefan Weil
#endif
706 9aebd98a Stefan Weil
    vdi_header_to_le(&header);
707 9aebd98a Stefan Weil
    if (write(fd, &header, sizeof(header)) < 0) {
708 9aebd98a Stefan Weil
        result = -errno;
709 9aebd98a Stefan Weil
    }
710 9aebd98a Stefan Weil
711 b76b6e95 Stefan Weil
    if (bmap_size > 0) {
712 514f21a5 Stefan Weil
        uint32_t *bmap = g_malloc0(bmap_size);
713 514f21a5 Stefan Weil
        for (i = 0; i < blocks; i++) {
714 514f21a5 Stefan Weil
            if (image_type == VDI_TYPE_STATIC) {
715 514f21a5 Stefan Weil
                bmap[i] = i;
716 514f21a5 Stefan Weil
            } else {
717 514f21a5 Stefan Weil
                bmap[i] = VDI_UNALLOCATED;
718 514f21a5 Stefan Weil
            }
719 9aebd98a Stefan Weil
        }
720 514f21a5 Stefan Weil
        if (write(fd, bmap, bmap_size) < 0) {
721 514f21a5 Stefan Weil
            result = -errno;
722 514f21a5 Stefan Weil
        }
723 514f21a5 Stefan Weil
        g_free(bmap);
724 9aebd98a Stefan Weil
    }
725 514f21a5 Stefan Weil
726 9aebd98a Stefan Weil
    if (image_type == VDI_TYPE_STATIC) {
727 9aebd98a Stefan Weil
        if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
728 9aebd98a Stefan Weil
            result = -errno;
729 9aebd98a Stefan Weil
        }
730 9aebd98a Stefan Weil
    }
731 9aebd98a Stefan Weil
732 9aebd98a Stefan Weil
    if (close(fd) < 0) {
733 9aebd98a Stefan Weil
        result = -errno;
734 9aebd98a Stefan Weil
    }
735 9aebd98a Stefan Weil
736 9aebd98a Stefan Weil
    return result;
737 9aebd98a Stefan Weil
}
738 9aebd98a Stefan Weil
739 9aebd98a Stefan Weil
static void vdi_close(BlockDriverState *bs)
740 9aebd98a Stefan Weil
{
741 fc9d106c Kevin Wolf
    BDRVVdiState *s = bs->opaque;
742 6ac5f388 Kevin Wolf
743 6ac5f388 Kevin Wolf
    g_free(s->bmap);
744 6ac5f388 Kevin Wolf
745 fc9d106c Kevin Wolf
    migrate_del_blocker(s->migration_blocker);
746 fc9d106c Kevin Wolf
    error_free(s->migration_blocker);
747 9aebd98a Stefan Weil
}
748 9aebd98a Stefan Weil
749 9aebd98a Stefan Weil
static QEMUOptionParameter vdi_create_options[] = {
750 9aebd98a Stefan Weil
    {
751 9aebd98a Stefan Weil
        .name = BLOCK_OPT_SIZE,
752 9aebd98a Stefan Weil
        .type = OPT_SIZE,
753 9aebd98a Stefan Weil
        .help = "Virtual disk size"
754 9aebd98a Stefan Weil
    },
755 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_BLOCK_SIZE)
756 9aebd98a Stefan Weil
    {
757 9aebd98a Stefan Weil
        .name = BLOCK_OPT_CLUSTER_SIZE,
758 9aebd98a Stefan Weil
        .type = OPT_SIZE,
759 99cce9fa Kevin Wolf
        .help = "VDI cluster (block) size",
760 99cce9fa Kevin Wolf
        .value = { .n = DEFAULT_CLUSTER_SIZE },
761 9aebd98a Stefan Weil
    },
762 9aebd98a Stefan Weil
#endif
763 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_STATIC_IMAGE)
764 9aebd98a Stefan Weil
    {
765 9aebd98a Stefan Weil
        .name = BLOCK_OPT_STATIC,
766 9aebd98a Stefan Weil
        .type = OPT_FLAG,
767 9aebd98a Stefan Weil
        .help = "VDI static (pre-allocated) image"
768 9aebd98a Stefan Weil
    },
769 9aebd98a Stefan Weil
#endif
770 9aebd98a Stefan Weil
    /* TODO: An additional option to set UUID values might be useful. */
771 9aebd98a Stefan Weil
    { NULL }
772 9aebd98a Stefan Weil
};
773 9aebd98a Stefan Weil
774 9aebd98a Stefan Weil
static BlockDriver bdrv_vdi = {
775 9aebd98a Stefan Weil
    .format_name = "vdi",
776 9aebd98a Stefan Weil
    .instance_size = sizeof(BDRVVdiState),
777 9aebd98a Stefan Weil
    .bdrv_probe = vdi_probe,
778 9aebd98a Stefan Weil
    .bdrv_open = vdi_open,
779 9aebd98a Stefan Weil
    .bdrv_close = vdi_close,
780 ecfe2bba Jeff Cody
    .bdrv_reopen_prepare = vdi_reopen_prepare,
781 9aebd98a Stefan Weil
    .bdrv_create = vdi_create,
782 e850b35a Stefan Hajnoczi
    .bdrv_co_is_allocated = vdi_co_is_allocated,
783 9aebd98a Stefan Weil
    .bdrv_make_empty = vdi_make_empty,
784 9aebd98a Stefan Weil
785 a7a43aa1 Paolo Bonzini
    .bdrv_read = vdi_co_read,
786 9aebd98a Stefan Weil
#if defined(CONFIG_VDI_WRITE)
787 a7a43aa1 Paolo Bonzini
    .bdrv_write = vdi_co_write,
788 9aebd98a Stefan Weil
#endif
789 9aebd98a Stefan Weil
790 9aebd98a Stefan Weil
    .bdrv_get_info = vdi_get_info,
791 9aebd98a Stefan Weil
792 9aebd98a Stefan Weil
    .create_options = vdi_create_options,
793 9aebd98a Stefan Weil
    .bdrv_check = vdi_check,
794 9aebd98a Stefan Weil
};
795 9aebd98a Stefan Weil
796 9aebd98a Stefan Weil
static void bdrv_vdi_init(void)
797 9aebd98a Stefan Weil
{
798 9aebd98a Stefan Weil
    logout("\n");
799 9aebd98a Stefan Weil
    bdrv_register(&bdrv_vdi);
800 9aebd98a Stefan Weil
}
801 9aebd98a Stefan Weil
802 9aebd98a Stefan Weil
block_init(bdrv_vdi_init);