Statistics
| Branch: | Revision:

root / block / vmdk.c @ 3178e275

History | View | Annotate | Download (48.2 kB)

1 ea2384d3 bellard
/*
2 ea2384d3 bellard
 * Block driver for the VMDK format
3 5fafdf24 ths
 *
4 ea2384d3 bellard
 * Copyright (c) 2004 Fabrice Bellard
5 ff1afc72 bellard
 * Copyright (c) 2005 Filip Navara
6 5fafdf24 ths
 *
7 ea2384d3 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 ea2384d3 bellard
 * of this software and associated documentation files (the "Software"), to deal
9 ea2384d3 bellard
 * in the Software without restriction, including without limitation the rights
10 ea2384d3 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 ea2384d3 bellard
 * copies of the Software, and to permit persons to whom the Software is
12 ea2384d3 bellard
 * furnished to do so, subject to the following conditions:
13 ea2384d3 bellard
 *
14 ea2384d3 bellard
 * The above copyright notice and this permission notice shall be included in
15 ea2384d3 bellard
 * all copies or substantial portions of the Software.
16 ea2384d3 bellard
 *
17 ea2384d3 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 ea2384d3 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 ea2384d3 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 ea2384d3 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 ea2384d3 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 ea2384d3 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 ea2384d3 bellard
 * THE SOFTWARE.
24 ea2384d3 bellard
 */
25 5f4da8c0 ths
26 faf07963 pbrook
#include "qemu-common.h"
27 ea2384d3 bellard
#include "block_int.h"
28 5efa9d5a Anthony Liguori
#include "module.h"
29 2bc3166c Kevin Wolf
#include "migration.h"
30 2923d34f Stefan Weil
#include <zlib.h>
31 ea2384d3 bellard
32 ea2384d3 bellard
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
33 ea2384d3 bellard
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
34 432bb170 Fam Zheng
#define VMDK4_COMPRESSION_DEFLATE 1
35 bb45ded9 Fam Zheng
#define VMDK4_FLAG_RGD (1 << 1)
36 432bb170 Fam Zheng
#define VMDK4_FLAG_COMPRESS (1 << 16)
37 432bb170 Fam Zheng
#define VMDK4_FLAG_MARKER (1 << 17)
38 65bd155c Kevin Wolf
#define VMDK4_GD_AT_END 0xffffffffffffffffULL
39 ea2384d3 bellard
40 ea2384d3 bellard
typedef struct {
41 ea2384d3 bellard
    uint32_t version;
42 ea2384d3 bellard
    uint32_t flags;
43 ea2384d3 bellard
    uint32_t disk_sectors;
44 ea2384d3 bellard
    uint32_t granularity;
45 ea2384d3 bellard
    uint32_t l1dir_offset;
46 ea2384d3 bellard
    uint32_t l1dir_size;
47 ea2384d3 bellard
    uint32_t file_sectors;
48 ea2384d3 bellard
    uint32_t cylinders;
49 ea2384d3 bellard
    uint32_t heads;
50 ea2384d3 bellard
    uint32_t sectors_per_track;
51 ea2384d3 bellard
} VMDK3Header;
52 ea2384d3 bellard
53 ea2384d3 bellard
typedef struct {
54 ea2384d3 bellard
    uint32_t version;
55 ea2384d3 bellard
    uint32_t flags;
56 ea2384d3 bellard
    int64_t capacity;
57 ea2384d3 bellard
    int64_t granularity;
58 ea2384d3 bellard
    int64_t desc_offset;
59 ea2384d3 bellard
    int64_t desc_size;
60 ea2384d3 bellard
    int32_t num_gtes_per_gte;
61 bb45ded9 Fam Zheng
    int64_t rgd_offset;
62 7a736bfa Kevin Wolf
    int64_t gd_offset;
63 ea2384d3 bellard
    int64_t grain_offset;
64 ea2384d3 bellard
    char filler[1];
65 ea2384d3 bellard
    char check_bytes[4];
66 432bb170 Fam Zheng
    uint16_t compressAlgorithm;
67 541dc0d4 Stefan Weil
} QEMU_PACKED VMDK4Header;
68 ea2384d3 bellard
69 ea2384d3 bellard
#define L2_CACHE_SIZE 16
70 ea2384d3 bellard
71 b3976d3c Fam Zheng
typedef struct VmdkExtent {
72 b3976d3c Fam Zheng
    BlockDriverState *file;
73 b3976d3c Fam Zheng
    bool flat;
74 432bb170 Fam Zheng
    bool compressed;
75 432bb170 Fam Zheng
    bool has_marker;
76 b3976d3c Fam Zheng
    int64_t sectors;
77 b3976d3c Fam Zheng
    int64_t end_sector;
78 7fa60fa3 Fam Zheng
    int64_t flat_start_offset;
79 ea2384d3 bellard
    int64_t l1_table_offset;
80 ff1afc72 bellard
    int64_t l1_backup_table_offset;
81 ea2384d3 bellard
    uint32_t *l1_table;
82 ff1afc72 bellard
    uint32_t *l1_backup_table;
83 ea2384d3 bellard
    unsigned int l1_size;
84 ea2384d3 bellard
    uint32_t l1_entry_sectors;
85 ea2384d3 bellard
86 ea2384d3 bellard
    unsigned int l2_size;
87 ea2384d3 bellard
    uint32_t *l2_cache;
88 ea2384d3 bellard
    uint32_t l2_cache_offsets[L2_CACHE_SIZE];
89 ea2384d3 bellard
    uint32_t l2_cache_counts[L2_CACHE_SIZE];
90 ea2384d3 bellard
91 ea2384d3 bellard
    unsigned int cluster_sectors;
92 b3976d3c Fam Zheng
} VmdkExtent;
93 b3976d3c Fam Zheng
94 b3976d3c Fam Zheng
typedef struct BDRVVmdkState {
95 848c66e8 Paolo Bonzini
    CoMutex lock;
96 e1da9b24 Fam Zheng
    int desc_offset;
97 69b4d86d Fam Zheng
    bool cid_updated;
98 5f4da8c0 ths
    uint32_t parent_cid;
99 b3976d3c Fam Zheng
    int num_extents;
100 b3976d3c Fam Zheng
    /* Extent array with num_extents entries, ascend ordered by address */
101 b3976d3c Fam Zheng
    VmdkExtent *extents;
102 2bc3166c Kevin Wolf
    Error *migration_blocker;
103 ea2384d3 bellard
} BDRVVmdkState;
104 ea2384d3 bellard
105 630530a6 ths
typedef struct VmdkMetaData {
106 630530a6 ths
    uint32_t offset;
107 630530a6 ths
    unsigned int l1_index;
108 630530a6 ths
    unsigned int l2_index;
109 630530a6 ths
    unsigned int l2_offset;
110 630530a6 ths
    int valid;
111 630530a6 ths
} VmdkMetaData;
112 630530a6 ths
113 432bb170 Fam Zheng
typedef struct VmdkGrainMarker {
114 432bb170 Fam Zheng
    uint64_t lba;
115 432bb170 Fam Zheng
    uint32_t size;
116 432bb170 Fam Zheng
    uint8_t  data[0];
117 432bb170 Fam Zheng
} VmdkGrainMarker;
118 432bb170 Fam Zheng
119 65bd155c Kevin Wolf
enum {
120 65bd155c Kevin Wolf
    MARKER_END_OF_STREAM    = 0,
121 65bd155c Kevin Wolf
    MARKER_GRAIN_TABLE      = 1,
122 65bd155c Kevin Wolf
    MARKER_GRAIN_DIRECTORY  = 2,
123 65bd155c Kevin Wolf
    MARKER_FOOTER           = 3,
124 65bd155c Kevin Wolf
};
125 65bd155c Kevin Wolf
126 ea2384d3 bellard
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
127 ea2384d3 bellard
{
128 ea2384d3 bellard
    uint32_t magic;
129 ea2384d3 bellard
130 ae261c86 Fam Zheng
    if (buf_size < 4) {
131 ea2384d3 bellard
        return 0;
132 ae261c86 Fam Zheng
    }
133 ea2384d3 bellard
    magic = be32_to_cpu(*(uint32_t *)buf);
134 ea2384d3 bellard
    if (magic == VMDK3_MAGIC ||
135 01fc99d6 Fam Zheng
        magic == VMDK4_MAGIC) {
136 ea2384d3 bellard
        return 100;
137 01fc99d6 Fam Zheng
    } else {
138 01fc99d6 Fam Zheng
        const char *p = (const char *)buf;
139 01fc99d6 Fam Zheng
        const char *end = p + buf_size;
140 01fc99d6 Fam Zheng
        while (p < end) {
141 01fc99d6 Fam Zheng
            if (*p == '#') {
142 01fc99d6 Fam Zheng
                /* skip comment line */
143 01fc99d6 Fam Zheng
                while (p < end && *p != '\n') {
144 01fc99d6 Fam Zheng
                    p++;
145 01fc99d6 Fam Zheng
                }
146 01fc99d6 Fam Zheng
                p++;
147 01fc99d6 Fam Zheng
                continue;
148 01fc99d6 Fam Zheng
            }
149 01fc99d6 Fam Zheng
            if (*p == ' ') {
150 01fc99d6 Fam Zheng
                while (p < end && *p == ' ') {
151 01fc99d6 Fam Zheng
                    p++;
152 01fc99d6 Fam Zheng
                }
153 01fc99d6 Fam Zheng
                /* skip '\r' if windows line endings used. */
154 01fc99d6 Fam Zheng
                if (p < end && *p == '\r') {
155 01fc99d6 Fam Zheng
                    p++;
156 01fc99d6 Fam Zheng
                }
157 01fc99d6 Fam Zheng
                /* only accept blank lines before 'version=' line */
158 01fc99d6 Fam Zheng
                if (p == end || *p != '\n') {
159 01fc99d6 Fam Zheng
                    return 0;
160 01fc99d6 Fam Zheng
                }
161 01fc99d6 Fam Zheng
                p++;
162 01fc99d6 Fam Zheng
                continue;
163 01fc99d6 Fam Zheng
            }
164 01fc99d6 Fam Zheng
            if (end - p >= strlen("version=X\n")) {
165 01fc99d6 Fam Zheng
                if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
166 01fc99d6 Fam Zheng
                    strncmp("version=2\n", p, strlen("version=2\n")) == 0) {
167 01fc99d6 Fam Zheng
                    return 100;
168 01fc99d6 Fam Zheng
                }
169 01fc99d6 Fam Zheng
            }
170 01fc99d6 Fam Zheng
            if (end - p >= strlen("version=X\r\n")) {
171 01fc99d6 Fam Zheng
                if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
172 01fc99d6 Fam Zheng
                    strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) {
173 01fc99d6 Fam Zheng
                    return 100;
174 01fc99d6 Fam Zheng
                }
175 01fc99d6 Fam Zheng
            }
176 01fc99d6 Fam Zheng
            return 0;
177 01fc99d6 Fam Zheng
        }
178 ea2384d3 bellard
        return 0;
179 01fc99d6 Fam Zheng
    }
180 ea2384d3 bellard
}
181 ea2384d3 bellard
182 5f4da8c0 ths
#define CHECK_CID 1
183 5f4da8c0 ths
184 3b46e624 ths
#define SECTOR_SIZE 512
185 f66fd6c3 Fam Zheng
#define DESC_SIZE (20 * SECTOR_SIZE)    /* 20 sectors of 512 bytes each */
186 f66fd6c3 Fam Zheng
#define BUF_SIZE 4096
187 f66fd6c3 Fam Zheng
#define HEADER_SIZE 512                 /* first sector of 512 bytes */
188 5f4da8c0 ths
189 b3976d3c Fam Zheng
static void vmdk_free_extents(BlockDriverState *bs)
190 b3976d3c Fam Zheng
{
191 b3976d3c Fam Zheng
    int i;
192 b3976d3c Fam Zheng
    BDRVVmdkState *s = bs->opaque;
193 b3c0bfb6 Fam Zheng
    VmdkExtent *e;
194 b3976d3c Fam Zheng
195 b3976d3c Fam Zheng
    for (i = 0; i < s->num_extents; i++) {
196 b3c0bfb6 Fam Zheng
        e = &s->extents[i];
197 b3c0bfb6 Fam Zheng
        g_free(e->l1_table);
198 b3c0bfb6 Fam Zheng
        g_free(e->l2_cache);
199 b3c0bfb6 Fam Zheng
        g_free(e->l1_backup_table);
200 b3c0bfb6 Fam Zheng
        if (e->file != bs->file) {
201 b3c0bfb6 Fam Zheng
            bdrv_delete(e->file);
202 b3c0bfb6 Fam Zheng
        }
203 b3976d3c Fam Zheng
    }
204 7267c094 Anthony Liguori
    g_free(s->extents);
205 b3976d3c Fam Zheng
}
206 b3976d3c Fam Zheng
207 86c6b429 Fam Zheng
static void vmdk_free_last_extent(BlockDriverState *bs)
208 86c6b429 Fam Zheng
{
209 86c6b429 Fam Zheng
    BDRVVmdkState *s = bs->opaque;
210 86c6b429 Fam Zheng
211 86c6b429 Fam Zheng
    if (s->num_extents == 0) {
212 86c6b429 Fam Zheng
        return;
213 86c6b429 Fam Zheng
    }
214 86c6b429 Fam Zheng
    s->num_extents--;
215 86c6b429 Fam Zheng
    s->extents = g_realloc(s->extents, s->num_extents * sizeof(VmdkExtent));
216 86c6b429 Fam Zheng
}
217 86c6b429 Fam Zheng
218 5f4da8c0 ths
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
219 ea2384d3 bellard
{
220 5f4da8c0 ths
    char desc[DESC_SIZE];
221 8379e46d Pavel Borzenkov
    uint32_t cid = 0xffffffff;
222 7ccfb2eb blueswir1
    const char *p_name, *cid_str;
223 5f4da8c0 ths
    size_t cid_str_size;
224 e1da9b24 Fam Zheng
    BDRVVmdkState *s = bs->opaque;
225 99f1835d Kevin Wolf
    int ret;
226 5f4da8c0 ths
227 99f1835d Kevin Wolf
    ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
228 99f1835d Kevin Wolf
    if (ret < 0) {
229 5f4da8c0 ths
        return 0;
230 e1da9b24 Fam Zheng
    }
231 5f4da8c0 ths
232 5f4da8c0 ths
    if (parent) {
233 5f4da8c0 ths
        cid_str = "parentCID";
234 5f4da8c0 ths
        cid_str_size = sizeof("parentCID");
235 5f4da8c0 ths
    } else {
236 5f4da8c0 ths
        cid_str = "CID";
237 5f4da8c0 ths
        cid_str_size = sizeof("CID");
238 5f4da8c0 ths
    }
239 5f4da8c0 ths
240 93897b9f Kevin Wolf
    desc[DESC_SIZE - 1] = '\0';
241 ae261c86 Fam Zheng
    p_name = strstr(desc, cid_str);
242 ae261c86 Fam Zheng
    if (p_name != NULL) {
243 5f4da8c0 ths
        p_name += cid_str_size;
244 ae261c86 Fam Zheng
        sscanf(p_name, "%x", &cid);
245 5f4da8c0 ths
    }
246 5f4da8c0 ths
247 5f4da8c0 ths
    return cid;
248 5f4da8c0 ths
}
249 5f4da8c0 ths
250 5f4da8c0 ths
static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
251 5f4da8c0 ths
{
252 5f4da8c0 ths
    char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
253 5f4da8c0 ths
    char *p_name, *tmp_str;
254 e1da9b24 Fam Zheng
    BDRVVmdkState *s = bs->opaque;
255 99f1835d Kevin Wolf
    int ret;
256 5f4da8c0 ths
257 99f1835d Kevin Wolf
    ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
258 99f1835d Kevin Wolf
    if (ret < 0) {
259 99f1835d Kevin Wolf
        return ret;
260 e1da9b24 Fam Zheng
    }
261 5f4da8c0 ths
262 93897b9f Kevin Wolf
    desc[DESC_SIZE - 1] = '\0';
263 ae261c86 Fam Zheng
    tmp_str = strstr(desc, "parentCID");
264 93897b9f Kevin Wolf
    if (tmp_str == NULL) {
265 93897b9f Kevin Wolf
        return -EINVAL;
266 93897b9f Kevin Wolf
    }
267 93897b9f Kevin Wolf
268 363a37d5 blueswir1
    pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str);
269 ae261c86 Fam Zheng
    p_name = strstr(desc, "CID");
270 ae261c86 Fam Zheng
    if (p_name != NULL) {
271 5f4da8c0 ths
        p_name += sizeof("CID");
272 363a37d5 blueswir1
        snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
273 363a37d5 blueswir1
        pstrcat(desc, sizeof(desc), tmp_desc);
274 5f4da8c0 ths
    }
275 5f4da8c0 ths
276 99f1835d Kevin Wolf
    ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE);
277 99f1835d Kevin Wolf
    if (ret < 0) {
278 99f1835d Kevin Wolf
        return ret;
279 e1da9b24 Fam Zheng
    }
280 99f1835d Kevin Wolf
281 5f4da8c0 ths
    return 0;
282 5f4da8c0 ths
}
283 5f4da8c0 ths
284 5f4da8c0 ths
static int vmdk_is_cid_valid(BlockDriverState *bs)
285 5f4da8c0 ths
{
286 5f4da8c0 ths
#ifdef CHECK_CID
287 5f4da8c0 ths
    BDRVVmdkState *s = bs->opaque;
288 b171271a Kevin Wolf
    BlockDriverState *p_bs = bs->backing_hd;
289 5f4da8c0 ths
    uint32_t cur_pcid;
290 5f4da8c0 ths
291 5f4da8c0 ths
    if (p_bs) {
292 ae261c86 Fam Zheng
        cur_pcid = vmdk_read_cid(p_bs, 0);
293 ae261c86 Fam Zheng
        if (s->parent_cid != cur_pcid) {
294 ae261c86 Fam Zheng
            /* CID not valid */
295 5f4da8c0 ths
            return 0;
296 ae261c86 Fam Zheng
        }
297 5f4da8c0 ths
    }
298 5f4da8c0 ths
#endif
299 ae261c86 Fam Zheng
    /* CID valid */
300 5f4da8c0 ths
    return 1;
301 5f4da8c0 ths
}
302 5f4da8c0 ths
303 3897575f Jeff Cody
/* Queue extents, if any, for reopen() */
304 3897575f Jeff Cody
static int vmdk_reopen_prepare(BDRVReopenState *state,
305 3897575f Jeff Cody
                               BlockReopenQueue *queue, Error **errp)
306 3897575f Jeff Cody
{
307 3897575f Jeff Cody
    BDRVVmdkState *s;
308 3897575f Jeff Cody
    int ret = -1;
309 3897575f Jeff Cody
    int i;
310 3897575f Jeff Cody
    VmdkExtent *e;
311 3897575f Jeff Cody
312 3897575f Jeff Cody
    assert(state != NULL);
313 3897575f Jeff Cody
    assert(state->bs != NULL);
314 3897575f Jeff Cody
315 3897575f Jeff Cody
    if (queue == NULL) {
316 3897575f Jeff Cody
        error_set(errp, ERROR_CLASS_GENERIC_ERROR,
317 3897575f Jeff Cody
                 "No reopen queue for VMDK extents");
318 3897575f Jeff Cody
        goto exit;
319 3897575f Jeff Cody
    }
320 3897575f Jeff Cody
321 3897575f Jeff Cody
    s = state->bs->opaque;
322 3897575f Jeff Cody
323 3897575f Jeff Cody
    assert(s != NULL);
324 3897575f Jeff Cody
325 3897575f Jeff Cody
    for (i = 0; i < s->num_extents; i++) {
326 3897575f Jeff Cody
        e = &s->extents[i];
327 3897575f Jeff Cody
        if (e->file != state->bs->file) {
328 3897575f Jeff Cody
            bdrv_reopen_queue(queue, e->file, state->flags);
329 3897575f Jeff Cody
        }
330 3897575f Jeff Cody
    }
331 3897575f Jeff Cody
    ret = 0;
332 3897575f Jeff Cody
333 3897575f Jeff Cody
exit:
334 3897575f Jeff Cody
    return ret;
335 3897575f Jeff Cody
}
336 3897575f Jeff Cody
337 9949f97e Kevin Wolf
static int vmdk_parent_open(BlockDriverState *bs)
338 5f4da8c0 ths
{
339 5fafdf24 ths
    char *p_name;
340 7fa60fa3 Fam Zheng
    char desc[DESC_SIZE + 1];
341 e1da9b24 Fam Zheng
    BDRVVmdkState *s = bs->opaque;
342 588b65a3 Paolo Bonzini
    int ret;
343 5f4da8c0 ths
344 7fa60fa3 Fam Zheng
    desc[DESC_SIZE] = '\0';
345 588b65a3 Paolo Bonzini
    ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
346 588b65a3 Paolo Bonzini
    if (ret < 0) {
347 588b65a3 Paolo Bonzini
        return ret;
348 e1da9b24 Fam Zheng
    }
349 5f4da8c0 ths
350 ae261c86 Fam Zheng
    p_name = strstr(desc, "parentFileNameHint");
351 ae261c86 Fam Zheng
    if (p_name != NULL) {
352 5f4da8c0 ths
        char *end_name;
353 5f4da8c0 ths
354 5f4da8c0 ths
        p_name += sizeof("parentFileNameHint") + 1;
355 ae261c86 Fam Zheng
        end_name = strchr(p_name, '\"');
356 ae261c86 Fam Zheng
        if (end_name == NULL) {
357 588b65a3 Paolo Bonzini
            return -EINVAL;
358 ae261c86 Fam Zheng
        }
359 ae261c86 Fam Zheng
        if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
360 588b65a3 Paolo Bonzini
            return -EINVAL;
361 ae261c86 Fam Zheng
        }
362 3b46e624 ths
363 b171271a Kevin Wolf
        pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
364 ff1afc72 bellard
    }
365 5f4da8c0 ths
366 5f4da8c0 ths
    return 0;
367 5f4da8c0 ths
}
368 5f4da8c0 ths
369 b3976d3c Fam Zheng
/* Create and append extent to the extent array. Return the added VmdkExtent
370 b3976d3c Fam Zheng
 * address. return NULL if allocation failed. */
371 b3976d3c Fam Zheng
static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
372 b3976d3c Fam Zheng
                           BlockDriverState *file, bool flat, int64_t sectors,
373 b3976d3c Fam Zheng
                           int64_t l1_offset, int64_t l1_backup_offset,
374 b3976d3c Fam Zheng
                           uint32_t l1_size,
375 b3976d3c Fam Zheng
                           int l2_size, unsigned int cluster_sectors)
376 b3976d3c Fam Zheng
{
377 b3976d3c Fam Zheng
    VmdkExtent *extent;
378 b3976d3c Fam Zheng
    BDRVVmdkState *s = bs->opaque;
379 b3976d3c Fam Zheng
380 7267c094 Anthony Liguori
    s->extents = g_realloc(s->extents,
381 b3976d3c Fam Zheng
                              (s->num_extents + 1) * sizeof(VmdkExtent));
382 b3976d3c Fam Zheng
    extent = &s->extents[s->num_extents];
383 b3976d3c Fam Zheng
    s->num_extents++;
384 b3976d3c Fam Zheng
385 b3976d3c Fam Zheng
    memset(extent, 0, sizeof(VmdkExtent));
386 b3976d3c Fam Zheng
    extent->file = file;
387 b3976d3c Fam Zheng
    extent->flat = flat;
388 b3976d3c Fam Zheng
    extent->sectors = sectors;
389 b3976d3c Fam Zheng
    extent->l1_table_offset = l1_offset;
390 b3976d3c Fam Zheng
    extent->l1_backup_table_offset = l1_backup_offset;
391 b3976d3c Fam Zheng
    extent->l1_size = l1_size;
392 b3976d3c Fam Zheng
    extent->l1_entry_sectors = l2_size * cluster_sectors;
393 b3976d3c Fam Zheng
    extent->l2_size = l2_size;
394 b3976d3c Fam Zheng
    extent->cluster_sectors = cluster_sectors;
395 b3976d3c Fam Zheng
396 b3976d3c Fam Zheng
    if (s->num_extents > 1) {
397 b3976d3c Fam Zheng
        extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
398 b3976d3c Fam Zheng
    } else {
399 b3976d3c Fam Zheng
        extent->end_sector = extent->sectors;
400 b3976d3c Fam Zheng
    }
401 b3976d3c Fam Zheng
    bs->total_sectors = extent->end_sector;
402 b3976d3c Fam Zheng
    return extent;
403 b3976d3c Fam Zheng
}
404 b3976d3c Fam Zheng
405 b4b3ab14 Fam Zheng
static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
406 5f4da8c0 ths
{
407 b4b3ab14 Fam Zheng
    int ret;
408 b4b3ab14 Fam Zheng
    int l1_size, i;
409 5f4da8c0 ths
410 ea2384d3 bellard
    /* read the L1 table */
411 b3976d3c Fam Zheng
    l1_size = extent->l1_size * sizeof(uint32_t);
412 7267c094 Anthony Liguori
    extent->l1_table = g_malloc(l1_size);
413 b4b3ab14 Fam Zheng
    ret = bdrv_pread(extent->file,
414 b4b3ab14 Fam Zheng
                    extent->l1_table_offset,
415 b4b3ab14 Fam Zheng
                    extent->l1_table,
416 b4b3ab14 Fam Zheng
                    l1_size);
417 b4b3ab14 Fam Zheng
    if (ret < 0) {
418 b4b3ab14 Fam Zheng
        goto fail_l1;
419 b3976d3c Fam Zheng
    }
420 b3976d3c Fam Zheng
    for (i = 0; i < extent->l1_size; i++) {
421 b3976d3c Fam Zheng
        le32_to_cpus(&extent->l1_table[i]);
422 ea2384d3 bellard
    }
423 ea2384d3 bellard
424 b3976d3c Fam Zheng
    if (extent->l1_backup_table_offset) {
425 7267c094 Anthony Liguori
        extent->l1_backup_table = g_malloc(l1_size);
426 b4b3ab14 Fam Zheng
        ret = bdrv_pread(extent->file,
427 b4b3ab14 Fam Zheng
                        extent->l1_backup_table_offset,
428 b4b3ab14 Fam Zheng
                        extent->l1_backup_table,
429 b4b3ab14 Fam Zheng
                        l1_size);
430 b4b3ab14 Fam Zheng
        if (ret < 0) {
431 b4b3ab14 Fam Zheng
            goto fail_l1b;
432 b3976d3c Fam Zheng
        }
433 b3976d3c Fam Zheng
        for (i = 0; i < extent->l1_size; i++) {
434 b3976d3c Fam Zheng
            le32_to_cpus(&extent->l1_backup_table[i]);
435 ff1afc72 bellard
        }
436 ff1afc72 bellard
    }
437 ff1afc72 bellard
438 b3976d3c Fam Zheng
    extent->l2_cache =
439 7267c094 Anthony Liguori
        g_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
440 ea2384d3 bellard
    return 0;
441 b4b3ab14 Fam Zheng
 fail_l1b:
442 7267c094 Anthony Liguori
    g_free(extent->l1_backup_table);
443 b4b3ab14 Fam Zheng
 fail_l1:
444 7267c094 Anthony Liguori
    g_free(extent->l1_table);
445 b4b3ab14 Fam Zheng
    return ret;
446 b4b3ab14 Fam Zheng
}
447 b4b3ab14 Fam Zheng
448 86c6b429 Fam Zheng
static int vmdk_open_vmdk3(BlockDriverState *bs,
449 86c6b429 Fam Zheng
                           BlockDriverState *file,
450 86c6b429 Fam Zheng
                           int flags)
451 b4b3ab14 Fam Zheng
{
452 b4b3ab14 Fam Zheng
    int ret;
453 b4b3ab14 Fam Zheng
    uint32_t magic;
454 b4b3ab14 Fam Zheng
    VMDK3Header header;
455 b4b3ab14 Fam Zheng
    VmdkExtent *extent;
456 b4b3ab14 Fam Zheng
457 86c6b429 Fam Zheng
    ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
458 b4b3ab14 Fam Zheng
    if (ret < 0) {
459 86c6b429 Fam Zheng
        return ret;
460 b4b3ab14 Fam Zheng
    }
461 b4b3ab14 Fam Zheng
    extent = vmdk_add_extent(bs,
462 b4b3ab14 Fam Zheng
                             bs->file, false,
463 b4b3ab14 Fam Zheng
                             le32_to_cpu(header.disk_sectors),
464 b4b3ab14 Fam Zheng
                             le32_to_cpu(header.l1dir_offset) << 9,
465 b4b3ab14 Fam Zheng
                             0, 1 << 6, 1 << 9,
466 b4b3ab14 Fam Zheng
                             le32_to_cpu(header.granularity));
467 b4b3ab14 Fam Zheng
    ret = vmdk_init_tables(bs, extent);
468 b4b3ab14 Fam Zheng
    if (ret) {
469 86c6b429 Fam Zheng
        /* free extent allocated by vmdk_add_extent */
470 86c6b429 Fam Zheng
        vmdk_free_last_extent(bs);
471 b4b3ab14 Fam Zheng
    }
472 b4b3ab14 Fam Zheng
    return ret;
473 b4b3ab14 Fam Zheng
}
474 b4b3ab14 Fam Zheng
475 f16f509d Fam Zheng
static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
476 f16f509d Fam Zheng
                               int64_t desc_offset);
477 f16f509d Fam Zheng
478 86c6b429 Fam Zheng
static int vmdk_open_vmdk4(BlockDriverState *bs,
479 86c6b429 Fam Zheng
                           BlockDriverState *file,
480 86c6b429 Fam Zheng
                           int flags)
481 b4b3ab14 Fam Zheng
{
482 b4b3ab14 Fam Zheng
    int ret;
483 b4b3ab14 Fam Zheng
    uint32_t magic;
484 b4b3ab14 Fam Zheng
    uint32_t l1_size, l1_entry_sectors;
485 b4b3ab14 Fam Zheng
    VMDK4Header header;
486 b4b3ab14 Fam Zheng
    VmdkExtent *extent;
487 bb45ded9 Fam Zheng
    int64_t l1_backup_offset = 0;
488 b4b3ab14 Fam Zheng
489 86c6b429 Fam Zheng
    ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
490 b4b3ab14 Fam Zheng
    if (ret < 0) {
491 86c6b429 Fam Zheng
        return ret;
492 b4b3ab14 Fam Zheng
    }
493 f16f509d Fam Zheng
    if (header.capacity == 0 && header.desc_offset) {
494 f16f509d Fam Zheng
        return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
495 f16f509d Fam Zheng
    }
496 65bd155c Kevin Wolf
497 65bd155c Kevin Wolf
    if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
498 65bd155c Kevin Wolf
        /*
499 65bd155c Kevin Wolf
         * The footer takes precedence over the header, so read it in. The
500 65bd155c Kevin Wolf
         * footer starts at offset -1024 from the end: One sector for the
501 65bd155c Kevin Wolf
         * footer, and another one for the end-of-stream marker.
502 65bd155c Kevin Wolf
         */
503 65bd155c Kevin Wolf
        struct {
504 65bd155c Kevin Wolf
            struct {
505 65bd155c Kevin Wolf
                uint64_t val;
506 65bd155c Kevin Wolf
                uint32_t size;
507 65bd155c Kevin Wolf
                uint32_t type;
508 65bd155c Kevin Wolf
                uint8_t pad[512 - 16];
509 65bd155c Kevin Wolf
            } QEMU_PACKED footer_marker;
510 65bd155c Kevin Wolf
511 65bd155c Kevin Wolf
            uint32_t magic;
512 65bd155c Kevin Wolf
            VMDK4Header header;
513 65bd155c Kevin Wolf
            uint8_t pad[512 - 4 - sizeof(VMDK4Header)];
514 65bd155c Kevin Wolf
515 65bd155c Kevin Wolf
            struct {
516 65bd155c Kevin Wolf
                uint64_t val;
517 65bd155c Kevin Wolf
                uint32_t size;
518 65bd155c Kevin Wolf
                uint32_t type;
519 65bd155c Kevin Wolf
                uint8_t pad[512 - 16];
520 65bd155c Kevin Wolf
            } QEMU_PACKED eos_marker;
521 65bd155c Kevin Wolf
        } QEMU_PACKED footer;
522 65bd155c Kevin Wolf
523 65bd155c Kevin Wolf
        ret = bdrv_pread(file,
524 65bd155c Kevin Wolf
            bs->file->total_sectors * 512 - 1536,
525 65bd155c Kevin Wolf
            &footer, sizeof(footer));
526 65bd155c Kevin Wolf
        if (ret < 0) {
527 65bd155c Kevin Wolf
            return ret;
528 65bd155c Kevin Wolf
        }
529 65bd155c Kevin Wolf
530 65bd155c Kevin Wolf
        /* Some sanity checks for the footer */
531 65bd155c Kevin Wolf
        if (be32_to_cpu(footer.magic) != VMDK4_MAGIC ||
532 65bd155c Kevin Wolf
            le32_to_cpu(footer.footer_marker.size) != 0  ||
533 65bd155c Kevin Wolf
            le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER ||
534 65bd155c Kevin Wolf
            le64_to_cpu(footer.eos_marker.val) != 0  ||
535 65bd155c Kevin Wolf
            le32_to_cpu(footer.eos_marker.size) != 0  ||
536 65bd155c Kevin Wolf
            le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM)
537 65bd155c Kevin Wolf
        {
538 65bd155c Kevin Wolf
            return -EINVAL;
539 65bd155c Kevin Wolf
        }
540 65bd155c Kevin Wolf
541 65bd155c Kevin Wolf
        header = footer.header;
542 65bd155c Kevin Wolf
    }
543 65bd155c Kevin Wolf
544 b4b3ab14 Fam Zheng
    l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
545 b4b3ab14 Fam Zheng
                        * le64_to_cpu(header.granularity);
546 75d12341 Stefan Weil
    if (l1_entry_sectors == 0) {
547 86c6b429 Fam Zheng
        return -EINVAL;
548 86c6b429 Fam Zheng
    }
549 b4b3ab14 Fam Zheng
    l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
550 b4b3ab14 Fam Zheng
                / l1_entry_sectors;
551 bb45ded9 Fam Zheng
    if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
552 bb45ded9 Fam Zheng
        l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
553 bb45ded9 Fam Zheng
    }
554 86c6b429 Fam Zheng
    extent = vmdk_add_extent(bs, file, false,
555 b4b3ab14 Fam Zheng
                          le64_to_cpu(header.capacity),
556 b4b3ab14 Fam Zheng
                          le64_to_cpu(header.gd_offset) << 9,
557 bb45ded9 Fam Zheng
                          l1_backup_offset,
558 b4b3ab14 Fam Zheng
                          l1_size,
559 b4b3ab14 Fam Zheng
                          le32_to_cpu(header.num_gtes_per_gte),
560 b4b3ab14 Fam Zheng
                          le64_to_cpu(header.granularity));
561 432bb170 Fam Zheng
    extent->compressed =
562 432bb170 Fam Zheng
        le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
563 432bb170 Fam Zheng
    extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
564 b4b3ab14 Fam Zheng
    ret = vmdk_init_tables(bs, extent);
565 b4b3ab14 Fam Zheng
    if (ret) {
566 86c6b429 Fam Zheng
        /* free extent allocated by vmdk_add_extent */
567 86c6b429 Fam Zheng
        vmdk_free_last_extent(bs);
568 b4b3ab14 Fam Zheng
    }
569 b4b3ab14 Fam Zheng
    return ret;
570 b4b3ab14 Fam Zheng
}
571 b4b3ab14 Fam Zheng
572 7fa60fa3 Fam Zheng
/* find an option value out of descriptor file */
573 7fa60fa3 Fam Zheng
static int vmdk_parse_description(const char *desc, const char *opt_name,
574 7fa60fa3 Fam Zheng
        char *buf, int buf_size)
575 7fa60fa3 Fam Zheng
{
576 7fa60fa3 Fam Zheng
    char *opt_pos, *opt_end;
577 7fa60fa3 Fam Zheng
    const char *end = desc + strlen(desc);
578 7fa60fa3 Fam Zheng
579 7fa60fa3 Fam Zheng
    opt_pos = strstr(desc, opt_name);
580 7fa60fa3 Fam Zheng
    if (!opt_pos) {
581 7fa60fa3 Fam Zheng
        return -1;
582 7fa60fa3 Fam Zheng
    }
583 7fa60fa3 Fam Zheng
    /* Skip "=\"" following opt_name */
584 7fa60fa3 Fam Zheng
    opt_pos += strlen(opt_name) + 2;
585 7fa60fa3 Fam Zheng
    if (opt_pos >= end) {
586 7fa60fa3 Fam Zheng
        return -1;
587 7fa60fa3 Fam Zheng
    }
588 7fa60fa3 Fam Zheng
    opt_end = opt_pos;
589 7fa60fa3 Fam Zheng
    while (opt_end < end && *opt_end != '"') {
590 7fa60fa3 Fam Zheng
        opt_end++;
591 7fa60fa3 Fam Zheng
    }
592 7fa60fa3 Fam Zheng
    if (opt_end == end || buf_size < opt_end - opt_pos + 1) {
593 7fa60fa3 Fam Zheng
        return -1;
594 7fa60fa3 Fam Zheng
    }
595 7fa60fa3 Fam Zheng
    pstrcpy(buf, opt_end - opt_pos + 1, opt_pos);
596 7fa60fa3 Fam Zheng
    return 0;
597 7fa60fa3 Fam Zheng
}
598 7fa60fa3 Fam Zheng
599 86c6b429 Fam Zheng
/* Open an extent file and append to bs array */
600 86c6b429 Fam Zheng
static int vmdk_open_sparse(BlockDriverState *bs,
601 86c6b429 Fam Zheng
                            BlockDriverState *file,
602 86c6b429 Fam Zheng
                            int flags)
603 86c6b429 Fam Zheng
{
604 86c6b429 Fam Zheng
    uint32_t magic;
605 86c6b429 Fam Zheng
606 86c6b429 Fam Zheng
    if (bdrv_pread(file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
607 86c6b429 Fam Zheng
        return -EIO;
608 86c6b429 Fam Zheng
    }
609 86c6b429 Fam Zheng
610 86c6b429 Fam Zheng
    magic = be32_to_cpu(magic);
611 86c6b429 Fam Zheng
    switch (magic) {
612 86c6b429 Fam Zheng
        case VMDK3_MAGIC:
613 86c6b429 Fam Zheng
            return vmdk_open_vmdk3(bs, file, flags);
614 86c6b429 Fam Zheng
            break;
615 86c6b429 Fam Zheng
        case VMDK4_MAGIC:
616 86c6b429 Fam Zheng
            return vmdk_open_vmdk4(bs, file, flags);
617 86c6b429 Fam Zheng
            break;
618 86c6b429 Fam Zheng
        default:
619 86c6b429 Fam Zheng
            return -EINVAL;
620 86c6b429 Fam Zheng
            break;
621 86c6b429 Fam Zheng
    }
622 86c6b429 Fam Zheng
}
623 86c6b429 Fam Zheng
624 7fa60fa3 Fam Zheng
static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
625 7fa60fa3 Fam Zheng
        const char *desc_file_path)
626 7fa60fa3 Fam Zheng
{
627 7fa60fa3 Fam Zheng
    int ret;
628 7fa60fa3 Fam Zheng
    char access[11];
629 7fa60fa3 Fam Zheng
    char type[11];
630 7fa60fa3 Fam Zheng
    char fname[512];
631 7fa60fa3 Fam Zheng
    const char *p = desc;
632 7fa60fa3 Fam Zheng
    int64_t sectors = 0;
633 7fa60fa3 Fam Zheng
    int64_t flat_offset;
634 86c6b429 Fam Zheng
    char extent_path[PATH_MAX];
635 86c6b429 Fam Zheng
    BlockDriverState *extent_file;
636 7fa60fa3 Fam Zheng
637 7fa60fa3 Fam Zheng
    while (*p) {
638 7fa60fa3 Fam Zheng
        /* parse extent line:
639 7fa60fa3 Fam Zheng
         * RW [size in sectors] FLAT "file-name.vmdk" OFFSET
640 7fa60fa3 Fam Zheng
         * or
641 7fa60fa3 Fam Zheng
         * RW [size in sectors] SPARSE "file-name.vmdk"
642 7fa60fa3 Fam Zheng
         */
643 7fa60fa3 Fam Zheng
        flat_offset = -1;
644 7fa60fa3 Fam Zheng
        ret = sscanf(p, "%10s %" SCNd64 " %10s %511s %" SCNd64,
645 7fa60fa3 Fam Zheng
                access, &sectors, type, fname, &flat_offset);
646 7fa60fa3 Fam Zheng
        if (ret < 4 || strcmp(access, "RW")) {
647 7fa60fa3 Fam Zheng
            goto next_line;
648 7fa60fa3 Fam Zheng
        } else if (!strcmp(type, "FLAT")) {
649 7fa60fa3 Fam Zheng
            if (ret != 5 || flat_offset < 0) {
650 7fa60fa3 Fam Zheng
                return -EINVAL;
651 7fa60fa3 Fam Zheng
            }
652 7fa60fa3 Fam Zheng
        } else if (ret != 4) {
653 7fa60fa3 Fam Zheng
            return -EINVAL;
654 7fa60fa3 Fam Zheng
        }
655 7fa60fa3 Fam Zheng
656 7fa60fa3 Fam Zheng
        /* trim the quotation marks around */
657 7fa60fa3 Fam Zheng
        if (fname[0] == '"') {
658 7fa60fa3 Fam Zheng
            memmove(fname, fname + 1, strlen(fname));
659 7fa60fa3 Fam Zheng
            if (strlen(fname) <= 1 || fname[strlen(fname) - 1] != '"') {
660 7fa60fa3 Fam Zheng
                return -EINVAL;
661 7fa60fa3 Fam Zheng
            }
662 7fa60fa3 Fam Zheng
            fname[strlen(fname) - 1] = '\0';
663 7fa60fa3 Fam Zheng
        }
664 7fa60fa3 Fam Zheng
        if (sectors <= 0 ||
665 7fa60fa3 Fam Zheng
            (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) ||
666 7fa60fa3 Fam Zheng
            (strcmp(access, "RW"))) {
667 7fa60fa3 Fam Zheng
            goto next_line;
668 7fa60fa3 Fam Zheng
        }
669 7fa60fa3 Fam Zheng
670 86c6b429 Fam Zheng
        path_combine(extent_path, sizeof(extent_path),
671 86c6b429 Fam Zheng
                desc_file_path, fname);
672 86c6b429 Fam Zheng
        ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
673 86c6b429 Fam Zheng
        if (ret) {
674 86c6b429 Fam Zheng
            return ret;
675 86c6b429 Fam Zheng
        }
676 86c6b429 Fam Zheng
677 7fa60fa3 Fam Zheng
        /* save to extents array */
678 7fa60fa3 Fam Zheng
        if (!strcmp(type, "FLAT")) {
679 7fa60fa3 Fam Zheng
            /* FLAT extent */
680 7fa60fa3 Fam Zheng
            VmdkExtent *extent;
681 7fa60fa3 Fam Zheng
682 7fa60fa3 Fam Zheng
            extent = vmdk_add_extent(bs, extent_file, true, sectors,
683 7fa60fa3 Fam Zheng
                            0, 0, 0, 0, sectors);
684 f16f509d Fam Zheng
            extent->flat_start_offset = flat_offset << 9;
685 86c6b429 Fam Zheng
        } else if (!strcmp(type, "SPARSE")) {
686 86c6b429 Fam Zheng
            /* SPARSE extent */
687 86c6b429 Fam Zheng
            ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
688 86c6b429 Fam Zheng
            if (ret) {
689 86c6b429 Fam Zheng
                bdrv_delete(extent_file);
690 86c6b429 Fam Zheng
                return ret;
691 86c6b429 Fam Zheng
            }
692 7fa60fa3 Fam Zheng
        } else {
693 7fa60fa3 Fam Zheng
            fprintf(stderr,
694 7fa60fa3 Fam Zheng
                "VMDK: Not supported extent type \"%s\""".\n", type);
695 7fa60fa3 Fam Zheng
            return -ENOTSUP;
696 7fa60fa3 Fam Zheng
        }
697 7fa60fa3 Fam Zheng
next_line:
698 7fa60fa3 Fam Zheng
        /* move to next line */
699 7fa60fa3 Fam Zheng
        while (*p && *p != '\n') {
700 7fa60fa3 Fam Zheng
            p++;
701 7fa60fa3 Fam Zheng
        }
702 7fa60fa3 Fam Zheng
        p++;
703 7fa60fa3 Fam Zheng
    }
704 7fa60fa3 Fam Zheng
    return 0;
705 7fa60fa3 Fam Zheng
}
706 7fa60fa3 Fam Zheng
707 f16f509d Fam Zheng
static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
708 f16f509d Fam Zheng
                               int64_t desc_offset)
709 7fa60fa3 Fam Zheng
{
710 7fa60fa3 Fam Zheng
    int ret;
711 7fa60fa3 Fam Zheng
    char buf[2048];
712 7fa60fa3 Fam Zheng
    char ct[128];
713 7fa60fa3 Fam Zheng
    BDRVVmdkState *s = bs->opaque;
714 7fa60fa3 Fam Zheng
715 f16f509d Fam Zheng
    ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf));
716 7fa60fa3 Fam Zheng
    if (ret < 0) {
717 7fa60fa3 Fam Zheng
        return ret;
718 7fa60fa3 Fam Zheng
    }
719 7fa60fa3 Fam Zheng
    buf[2047] = '\0';
720 7fa60fa3 Fam Zheng
    if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
721 7fa60fa3 Fam Zheng
        return -EINVAL;
722 7fa60fa3 Fam Zheng
    }
723 6398de51 Fam Zheng
    if (strcmp(ct, "monolithicFlat") &&
724 86c6b429 Fam Zheng
        strcmp(ct, "twoGbMaxExtentSparse") &&
725 6398de51 Fam Zheng
        strcmp(ct, "twoGbMaxExtentFlat")) {
726 7fa60fa3 Fam Zheng
        fprintf(stderr,
727 7fa60fa3 Fam Zheng
                "VMDK: Not supported image type \"%s\""".\n", ct);
728 7fa60fa3 Fam Zheng
        return -ENOTSUP;
729 7fa60fa3 Fam Zheng
    }
730 7fa60fa3 Fam Zheng
    s->desc_offset = 0;
731 bae0a0cc Paolo Bonzini
    return vmdk_parse_extents(buf, bs, bs->file->filename);
732 7fa60fa3 Fam Zheng
}
733 7fa60fa3 Fam Zheng
734 b4b3ab14 Fam Zheng
static int vmdk_open(BlockDriverState *bs, int flags)
735 b4b3ab14 Fam Zheng
{
736 86c6b429 Fam Zheng
    int ret;
737 86c6b429 Fam Zheng
    BDRVVmdkState *s = bs->opaque;
738 b4b3ab14 Fam Zheng
739 86c6b429 Fam Zheng
    if (vmdk_open_sparse(bs, bs->file, flags) == 0) {
740 86c6b429 Fam Zheng
        s->desc_offset = 0x200;
741 bae0a0cc Paolo Bonzini
    } else {
742 bae0a0cc Paolo Bonzini
        ret = vmdk_open_desc_file(bs, flags, 0);
743 86c6b429 Fam Zheng
        if (ret) {
744 bae0a0cc Paolo Bonzini
            goto fail;
745 86c6b429 Fam Zheng
        }
746 b4b3ab14 Fam Zheng
    }
747 bae0a0cc Paolo Bonzini
    /* try to open parent images, if exist */
748 bae0a0cc Paolo Bonzini
    ret = vmdk_parent_open(bs);
749 bae0a0cc Paolo Bonzini
    if (ret) {
750 bae0a0cc Paolo Bonzini
        goto fail;
751 bae0a0cc Paolo Bonzini
    }
752 bae0a0cc Paolo Bonzini
    s->parent_cid = vmdk_read_cid(bs, 1);
753 848c66e8 Paolo Bonzini
    qemu_co_mutex_init(&s->lock);
754 2bc3166c Kevin Wolf
755 2bc3166c Kevin Wolf
    /* Disable migration when VMDK images are used */
756 2bc3166c Kevin Wolf
    error_set(&s->migration_blocker,
757 2bc3166c Kevin Wolf
              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
758 2bc3166c Kevin Wolf
              "vmdk", bs->device_name, "live migration");
759 2bc3166c Kevin Wolf
    migrate_add_blocker(s->migration_blocker);
760 2bc3166c Kevin Wolf
761 2bc3166c Kevin Wolf
    return 0;
762 bae0a0cc Paolo Bonzini
763 bae0a0cc Paolo Bonzini
fail:
764 bae0a0cc Paolo Bonzini
    vmdk_free_extents(bs);
765 bae0a0cc Paolo Bonzini
    return ret;
766 ea2384d3 bellard
}
767 ea2384d3 bellard
768 b3976d3c Fam Zheng
static int get_whole_cluster(BlockDriverState *bs,
769 b3976d3c Fam Zheng
                VmdkExtent *extent,
770 b3976d3c Fam Zheng
                uint64_t cluster_offset,
771 b3976d3c Fam Zheng
                uint64_t offset,
772 b3976d3c Fam Zheng
                bool allocate)
773 5f4da8c0 ths
{
774 b3976d3c Fam Zheng
    /* 128 sectors * 512 bytes each = grain size 64KB */
775 b3976d3c Fam Zheng
    uint8_t  whole_grain[extent->cluster_sectors * 512];
776 5f4da8c0 ths
777 0e69c543 Fam Zheng
    /* we will be here if it's first write on non-exist grain(cluster).
778 0e69c543 Fam Zheng
     * try to read from parent image, if exist */
779 b171271a Kevin Wolf
    if (bs->backing_hd) {
780 c336500d Kevin Wolf
        int ret;
781 5f4da8c0 ths
782 ae261c86 Fam Zheng
        if (!vmdk_is_cid_valid(bs)) {
783 5f4da8c0 ths
            return -1;
784 ae261c86 Fam Zheng
        }
785 5f4da8c0 ths
786 0e69c543 Fam Zheng
        /* floor offset to cluster */
787 0e69c543 Fam Zheng
        offset -= offset % (extent->cluster_sectors * 512);
788 c336500d Kevin Wolf
        ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
789 b3976d3c Fam Zheng
                extent->cluster_sectors);
790 c336500d Kevin Wolf
        if (ret < 0) {
791 c336500d Kevin Wolf
            return -1;
792 c336500d Kevin Wolf
        }
793 630530a6 ths
794 0e69c543 Fam Zheng
        /* Write grain only into the active image */
795 b3976d3c Fam Zheng
        ret = bdrv_write(extent->file, cluster_offset, whole_grain,
796 b3976d3c Fam Zheng
                extent->cluster_sectors);
797 c336500d Kevin Wolf
        if (ret < 0) {
798 c336500d Kevin Wolf
            return -1;
799 630530a6 ths
        }
800 630530a6 ths
    }
801 630530a6 ths
    return 0;
802 630530a6 ths
}
803 630530a6 ths
804 b3976d3c Fam Zheng
static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
805 630530a6 ths
{
806 630530a6 ths
    /* update L2 table */
807 b3976d3c Fam Zheng
    if (bdrv_pwrite_sync(
808 b3976d3c Fam Zheng
                extent->file,
809 b3976d3c Fam Zheng
                ((int64_t)m_data->l2_offset * 512)
810 b3976d3c Fam Zheng
                    + (m_data->l2_index * sizeof(m_data->offset)),
811 b3976d3c Fam Zheng
                &(m_data->offset),
812 b3976d3c Fam Zheng
                sizeof(m_data->offset)
813 b3976d3c Fam Zheng
            ) < 0) {
814 630530a6 ths
        return -1;
815 b3976d3c Fam Zheng
    }
816 630530a6 ths
    /* update backup L2 table */
817 b3976d3c Fam Zheng
    if (extent->l1_backup_table_offset != 0) {
818 b3976d3c Fam Zheng
        m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
819 b3976d3c Fam Zheng
        if (bdrv_pwrite_sync(
820 b3976d3c Fam Zheng
                    extent->file,
821 b3976d3c Fam Zheng
                    ((int64_t)m_data->l2_offset * 512)
822 b3976d3c Fam Zheng
                        + (m_data->l2_index * sizeof(m_data->offset)),
823 b3976d3c Fam Zheng
                    &(m_data->offset), sizeof(m_data->offset)
824 b3976d3c Fam Zheng
                ) < 0) {
825 5f4da8c0 ths
            return -1;
826 b3976d3c Fam Zheng
        }
827 5f4da8c0 ths
    }
828 630530a6 ths
829 5f4da8c0 ths
    return 0;
830 5f4da8c0 ths
}
831 5f4da8c0 ths
832 91b85bd3 Fam Zheng
static int get_cluster_offset(BlockDriverState *bs,
833 b3976d3c Fam Zheng
                                    VmdkExtent *extent,
834 b3976d3c Fam Zheng
                                    VmdkMetaData *m_data,
835 91b85bd3 Fam Zheng
                                    uint64_t offset,
836 91b85bd3 Fam Zheng
                                    int allocate,
837 91b85bd3 Fam Zheng
                                    uint64_t *cluster_offset)
838 ea2384d3 bellard
{
839 ea2384d3 bellard
    unsigned int l1_index, l2_offset, l2_index;
840 ea2384d3 bellard
    int min_index, i, j;
841 630530a6 ths
    uint32_t min_count, *l2_table, tmp = 0;
842 630530a6 ths
843 ae261c86 Fam Zheng
    if (m_data) {
844 630530a6 ths
        m_data->valid = 0;
845 ae261c86 Fam Zheng
    }
846 91b85bd3 Fam Zheng
    if (extent->flat) {
847 7fa60fa3 Fam Zheng
        *cluster_offset = extent->flat_start_offset;
848 91b85bd3 Fam Zheng
        return 0;
849 91b85bd3 Fam Zheng
    }
850 630530a6 ths
851 6398de51 Fam Zheng
    offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE;
852 b3976d3c Fam Zheng
    l1_index = (offset >> 9) / extent->l1_entry_sectors;
853 b3976d3c Fam Zheng
    if (l1_index >= extent->l1_size) {
854 91b85bd3 Fam Zheng
        return -1;
855 b3976d3c Fam Zheng
    }
856 b3976d3c Fam Zheng
    l2_offset = extent->l1_table[l1_index];
857 b3976d3c Fam Zheng
    if (!l2_offset) {
858 91b85bd3 Fam Zheng
        return -1;
859 b3976d3c Fam Zheng
    }
860 b4b3ab14 Fam Zheng
    for (i = 0; i < L2_CACHE_SIZE; i++) {
861 b3976d3c Fam Zheng
        if (l2_offset == extent->l2_cache_offsets[i]) {
862 ea2384d3 bellard
            /* increment the hit count */
863 b3976d3c Fam Zheng
            if (++extent->l2_cache_counts[i] == 0xffffffff) {
864 b4b3ab14 Fam Zheng
                for (j = 0; j < L2_CACHE_SIZE; j++) {
865 b3976d3c Fam Zheng
                    extent->l2_cache_counts[j] >>= 1;
866 ea2384d3 bellard
                }
867 ea2384d3 bellard
            }
868 b3976d3c Fam Zheng
            l2_table = extent->l2_cache + (i * extent->l2_size);
869 ea2384d3 bellard
            goto found;
870 ea2384d3 bellard
        }
871 ea2384d3 bellard
    }
872 ea2384d3 bellard
    /* not found: load a new entry in the least used one */
873 ea2384d3 bellard
    min_index = 0;
874 ea2384d3 bellard
    min_count = 0xffffffff;
875 b4b3ab14 Fam Zheng
    for (i = 0; i < L2_CACHE_SIZE; i++) {
876 b3976d3c Fam Zheng
        if (extent->l2_cache_counts[i] < min_count) {
877 b3976d3c Fam Zheng
            min_count = extent->l2_cache_counts[i];
878 ea2384d3 bellard
            min_index = i;
879 ea2384d3 bellard
        }
880 ea2384d3 bellard
    }
881 b3976d3c Fam Zheng
    l2_table = extent->l2_cache + (min_index * extent->l2_size);
882 b3976d3c Fam Zheng
    if (bdrv_pread(
883 b3976d3c Fam Zheng
                extent->file,
884 b3976d3c Fam Zheng
                (int64_t)l2_offset * 512,
885 b3976d3c Fam Zheng
                l2_table,
886 b3976d3c Fam Zheng
                extent->l2_size * sizeof(uint32_t)
887 b3976d3c Fam Zheng
            ) != extent->l2_size * sizeof(uint32_t)) {
888 91b85bd3 Fam Zheng
        return -1;
889 b3976d3c Fam Zheng
    }
890 5f4da8c0 ths
891 b3976d3c Fam Zheng
    extent->l2_cache_offsets[min_index] = l2_offset;
892 b3976d3c Fam Zheng
    extent->l2_cache_counts[min_index] = 1;
893 ea2384d3 bellard
 found:
894 b3976d3c Fam Zheng
    l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
895 91b85bd3 Fam Zheng
    *cluster_offset = le32_to_cpu(l2_table[l2_index]);
896 630530a6 ths
897 91b85bd3 Fam Zheng
    if (!*cluster_offset) {
898 91b85bd3 Fam Zheng
        if (!allocate) {
899 91b85bd3 Fam Zheng
            return -1;
900 91b85bd3 Fam Zheng
        }
901 9949f97e Kevin Wolf
902 ae261c86 Fam Zheng
        /* Avoid the L2 tables update for the images that have snapshots. */
903 91b85bd3 Fam Zheng
        *cluster_offset = bdrv_getlength(extent->file);
904 2b2c8c5d Fam Zheng
        if (!extent->compressed) {
905 2b2c8c5d Fam Zheng
            bdrv_truncate(
906 2b2c8c5d Fam Zheng
                extent->file,
907 2b2c8c5d Fam Zheng
                *cluster_offset + (extent->cluster_sectors << 9)
908 2b2c8c5d Fam Zheng
            );
909 2b2c8c5d Fam Zheng
        }
910 9949f97e Kevin Wolf
911 91b85bd3 Fam Zheng
        *cluster_offset >>= 9;
912 91b85bd3 Fam Zheng
        tmp = cpu_to_le32(*cluster_offset);
913 9949f97e Kevin Wolf
        l2_table[l2_index] = tmp;
914 630530a6 ths
915 630530a6 ths
        /* First of all we write grain itself, to avoid race condition
916 630530a6 ths
         * that may to corrupt the image.
917 630530a6 ths
         * This problem may occur because of insufficient space on host disk
918 630530a6 ths
         * or inappropriate VM shutdown.
919 630530a6 ths
         */
920 b3976d3c Fam Zheng
        if (get_whole_cluster(
921 ae261c86 Fam Zheng
                bs, extent, *cluster_offset, offset, allocate) == -1) {
922 91b85bd3 Fam Zheng
            return -1;
923 ae261c86 Fam Zheng
        }
924 630530a6 ths
925 630530a6 ths
        if (m_data) {
926 630530a6 ths
            m_data->offset = tmp;
927 630530a6 ths
            m_data->l1_index = l1_index;
928 630530a6 ths
            m_data->l2_index = l2_index;
929 630530a6 ths
            m_data->l2_offset = l2_offset;
930 630530a6 ths
            m_data->valid = 1;
931 630530a6 ths
        }
932 ff1afc72 bellard
    }
933 91b85bd3 Fam Zheng
    *cluster_offset <<= 9;
934 91b85bd3 Fam Zheng
    return 0;
935 ea2384d3 bellard
}
936 ea2384d3 bellard
937 b3976d3c Fam Zheng
static VmdkExtent *find_extent(BDRVVmdkState *s,
938 b3976d3c Fam Zheng
                                int64_t sector_num, VmdkExtent *start_hint)
939 b3976d3c Fam Zheng
{
940 b3976d3c Fam Zheng
    VmdkExtent *extent = start_hint;
941 b3976d3c Fam Zheng
942 b3976d3c Fam Zheng
    if (!extent) {
943 b3976d3c Fam Zheng
        extent = &s->extents[0];
944 b3976d3c Fam Zheng
    }
945 b3976d3c Fam Zheng
    while (extent < &s->extents[s->num_extents]) {
946 b3976d3c Fam Zheng
        if (sector_num < extent->end_sector) {
947 b3976d3c Fam Zheng
            return extent;
948 b3976d3c Fam Zheng
        }
949 b3976d3c Fam Zheng
        extent++;
950 b3976d3c Fam Zheng
    }
951 b3976d3c Fam Zheng
    return NULL;
952 b3976d3c Fam Zheng
}
953 b3976d3c Fam Zheng
954 f8a2e5e3 Stefan Hajnoczi
static int coroutine_fn vmdk_co_is_allocated(BlockDriverState *bs,
955 f8a2e5e3 Stefan Hajnoczi
        int64_t sector_num, int nb_sectors, int *pnum)
956 ea2384d3 bellard
{
957 ea2384d3 bellard
    BDRVVmdkState *s = bs->opaque;
958 b3976d3c Fam Zheng
    int64_t index_in_cluster, n, ret;
959 b3976d3c Fam Zheng
    uint64_t offset;
960 b3976d3c Fam Zheng
    VmdkExtent *extent;
961 b3976d3c Fam Zheng
962 b3976d3c Fam Zheng
    extent = find_extent(s, sector_num, NULL);
963 b3976d3c Fam Zheng
    if (!extent) {
964 b3976d3c Fam Zheng
        return 0;
965 b3976d3c Fam Zheng
    }
966 f8a2e5e3 Stefan Hajnoczi
    qemu_co_mutex_lock(&s->lock);
967 91b85bd3 Fam Zheng
    ret = get_cluster_offset(bs, extent, NULL,
968 91b85bd3 Fam Zheng
                            sector_num * 512, 0, &offset);
969 f8a2e5e3 Stefan Hajnoczi
    qemu_co_mutex_unlock(&s->lock);
970 91b85bd3 Fam Zheng
    /* get_cluster_offset returning 0 means success */
971 91b85bd3 Fam Zheng
    ret = !ret;
972 91b85bd3 Fam Zheng
973 91b85bd3 Fam Zheng
    index_in_cluster = sector_num % extent->cluster_sectors;
974 91b85bd3 Fam Zheng
    n = extent->cluster_sectors - index_in_cluster;
975 ae261c86 Fam Zheng
    if (n > nb_sectors) {
976 ea2384d3 bellard
        n = nb_sectors;
977 ae261c86 Fam Zheng
    }
978 ea2384d3 bellard
    *pnum = n;
979 b3976d3c Fam Zheng
    return ret;
980 ea2384d3 bellard
}
981 ea2384d3 bellard
982 dd3f6ee2 Fam Zheng
static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
983 dd3f6ee2 Fam Zheng
                            int64_t offset_in_cluster, const uint8_t *buf,
984 dd3f6ee2 Fam Zheng
                            int nb_sectors, int64_t sector_num)
985 dd3f6ee2 Fam Zheng
{
986 dd3f6ee2 Fam Zheng
    int ret;
987 2b2c8c5d Fam Zheng
    VmdkGrainMarker *data = NULL;
988 2b2c8c5d Fam Zheng
    uLongf buf_len;
989 dd3f6ee2 Fam Zheng
    const uint8_t *write_buf = buf;
990 dd3f6ee2 Fam Zheng
    int write_len = nb_sectors * 512;
991 dd3f6ee2 Fam Zheng
992 2b2c8c5d Fam Zheng
    if (extent->compressed) {
993 2b2c8c5d Fam Zheng
        if (!extent->has_marker) {
994 2b2c8c5d Fam Zheng
            ret = -EINVAL;
995 2b2c8c5d Fam Zheng
            goto out;
996 2b2c8c5d Fam Zheng
        }
997 2b2c8c5d Fam Zheng
        buf_len = (extent->cluster_sectors << 9) * 2;
998 2b2c8c5d Fam Zheng
        data = g_malloc(buf_len + sizeof(VmdkGrainMarker));
999 2b2c8c5d Fam Zheng
        if (compress(data->data, &buf_len, buf, nb_sectors << 9) != Z_OK ||
1000 2b2c8c5d Fam Zheng
                buf_len == 0) {
1001 2b2c8c5d Fam Zheng
            ret = -EINVAL;
1002 2b2c8c5d Fam Zheng
            goto out;
1003 2b2c8c5d Fam Zheng
        }
1004 2b2c8c5d Fam Zheng
        data->lba = sector_num;
1005 2b2c8c5d Fam Zheng
        data->size = buf_len;
1006 2b2c8c5d Fam Zheng
        write_buf = (uint8_t *)data;
1007 2b2c8c5d Fam Zheng
        write_len = buf_len + sizeof(VmdkGrainMarker);
1008 2b2c8c5d Fam Zheng
    }
1009 dd3f6ee2 Fam Zheng
    ret = bdrv_pwrite(extent->file,
1010 dd3f6ee2 Fam Zheng
                        cluster_offset + offset_in_cluster,
1011 dd3f6ee2 Fam Zheng
                        write_buf,
1012 dd3f6ee2 Fam Zheng
                        write_len);
1013 dd3f6ee2 Fam Zheng
    if (ret != write_len) {
1014 dd3f6ee2 Fam Zheng
        ret = ret < 0 ? ret : -EIO;
1015 dd3f6ee2 Fam Zheng
        goto out;
1016 dd3f6ee2 Fam Zheng
    }
1017 dd3f6ee2 Fam Zheng
    ret = 0;
1018 dd3f6ee2 Fam Zheng
 out:
1019 2b2c8c5d Fam Zheng
    g_free(data);
1020 dd3f6ee2 Fam Zheng
    return ret;
1021 dd3f6ee2 Fam Zheng
}
1022 dd3f6ee2 Fam Zheng
1023 dd3f6ee2 Fam Zheng
static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1024 dd3f6ee2 Fam Zheng
                            int64_t offset_in_cluster, uint8_t *buf,
1025 dd3f6ee2 Fam Zheng
                            int nb_sectors)
1026 dd3f6ee2 Fam Zheng
{
1027 dd3f6ee2 Fam Zheng
    int ret;
1028 2b2c8c5d Fam Zheng
    int cluster_bytes, buf_bytes;
1029 2b2c8c5d Fam Zheng
    uint8_t *cluster_buf, *compressed_data;
1030 2b2c8c5d Fam Zheng
    uint8_t *uncomp_buf;
1031 2b2c8c5d Fam Zheng
    uint32_t data_len;
1032 2b2c8c5d Fam Zheng
    VmdkGrainMarker *marker;
1033 2b2c8c5d Fam Zheng
    uLongf buf_len;
1034 2b2c8c5d Fam Zheng
1035 dd3f6ee2 Fam Zheng
1036 2b2c8c5d Fam Zheng
    if (!extent->compressed) {
1037 2b2c8c5d Fam Zheng
        ret = bdrv_pread(extent->file,
1038 2b2c8c5d Fam Zheng
                          cluster_offset + offset_in_cluster,
1039 2b2c8c5d Fam Zheng
                          buf, nb_sectors * 512);
1040 2b2c8c5d Fam Zheng
        if (ret == nb_sectors * 512) {
1041 2b2c8c5d Fam Zheng
            return 0;
1042 2b2c8c5d Fam Zheng
        } else {
1043 2b2c8c5d Fam Zheng
            return -EIO;
1044 2b2c8c5d Fam Zheng
        }
1045 2b2c8c5d Fam Zheng
    }
1046 2b2c8c5d Fam Zheng
    cluster_bytes = extent->cluster_sectors * 512;
1047 2b2c8c5d Fam Zheng
    /* Read two clusters in case GrainMarker + compressed data > one cluster */
1048 2b2c8c5d Fam Zheng
    buf_bytes = cluster_bytes * 2;
1049 2b2c8c5d Fam Zheng
    cluster_buf = g_malloc(buf_bytes);
1050 2b2c8c5d Fam Zheng
    uncomp_buf = g_malloc(cluster_bytes);
1051 dd3f6ee2 Fam Zheng
    ret = bdrv_pread(extent->file,
1052 2b2c8c5d Fam Zheng
                cluster_offset,
1053 2b2c8c5d Fam Zheng
                cluster_buf, buf_bytes);
1054 2b2c8c5d Fam Zheng
    if (ret < 0) {
1055 2b2c8c5d Fam Zheng
        goto out;
1056 2b2c8c5d Fam Zheng
    }
1057 2b2c8c5d Fam Zheng
    compressed_data = cluster_buf;
1058 2b2c8c5d Fam Zheng
    buf_len = cluster_bytes;
1059 2b2c8c5d Fam Zheng
    data_len = cluster_bytes;
1060 2b2c8c5d Fam Zheng
    if (extent->has_marker) {
1061 2b2c8c5d Fam Zheng
        marker = (VmdkGrainMarker *)cluster_buf;
1062 2b2c8c5d Fam Zheng
        compressed_data = marker->data;
1063 2b2c8c5d Fam Zheng
        data_len = le32_to_cpu(marker->size);
1064 2b2c8c5d Fam Zheng
    }
1065 2b2c8c5d Fam Zheng
    if (!data_len || data_len > buf_bytes) {
1066 2b2c8c5d Fam Zheng
        ret = -EINVAL;
1067 2b2c8c5d Fam Zheng
        goto out;
1068 2b2c8c5d Fam Zheng
    }
1069 2b2c8c5d Fam Zheng
    ret = uncompress(uncomp_buf, &buf_len, compressed_data, data_len);
1070 2b2c8c5d Fam Zheng
    if (ret != Z_OK) {
1071 2b2c8c5d Fam Zheng
        ret = -EINVAL;
1072 2b2c8c5d Fam Zheng
        goto out;
1073 2b2c8c5d Fam Zheng
1074 2b2c8c5d Fam Zheng
    }
1075 2b2c8c5d Fam Zheng
    if (offset_in_cluster < 0 ||
1076 2b2c8c5d Fam Zheng
            offset_in_cluster + nb_sectors * 512 > buf_len) {
1077 2b2c8c5d Fam Zheng
        ret = -EINVAL;
1078 2b2c8c5d Fam Zheng
        goto out;
1079 dd3f6ee2 Fam Zheng
    }
1080 2b2c8c5d Fam Zheng
    memcpy(buf, uncomp_buf + offset_in_cluster, nb_sectors * 512);
1081 2b2c8c5d Fam Zheng
    ret = 0;
1082 2b2c8c5d Fam Zheng
1083 2b2c8c5d Fam Zheng
 out:
1084 2b2c8c5d Fam Zheng
    g_free(uncomp_buf);
1085 2b2c8c5d Fam Zheng
    g_free(cluster_buf);
1086 2b2c8c5d Fam Zheng
    return ret;
1087 dd3f6ee2 Fam Zheng
}
1088 dd3f6ee2 Fam Zheng
1089 5fafdf24 ths
static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
1090 ea2384d3 bellard
                    uint8_t *buf, int nb_sectors)
1091 ea2384d3 bellard
{
1092 ea2384d3 bellard
    BDRVVmdkState *s = bs->opaque;
1093 b3976d3c Fam Zheng
    int ret;
1094 b3976d3c Fam Zheng
    uint64_t n, index_in_cluster;
1095 b3976d3c Fam Zheng
    VmdkExtent *extent = NULL;
1096 ea2384d3 bellard
    uint64_t cluster_offset;
1097 5f4da8c0 ths
1098 ea2384d3 bellard
    while (nb_sectors > 0) {
1099 b3976d3c Fam Zheng
        extent = find_extent(s, sector_num, extent);
1100 b3976d3c Fam Zheng
        if (!extent) {
1101 b3976d3c Fam Zheng
            return -EIO;
1102 b3976d3c Fam Zheng
        }
1103 91b85bd3 Fam Zheng
        ret = get_cluster_offset(
1104 91b85bd3 Fam Zheng
                            bs, extent, NULL,
1105 91b85bd3 Fam Zheng
                            sector_num << 9, 0, &cluster_offset);
1106 b3976d3c Fam Zheng
        index_in_cluster = sector_num % extent->cluster_sectors;
1107 b3976d3c Fam Zheng
        n = extent->cluster_sectors - index_in_cluster;
1108 ae261c86 Fam Zheng
        if (n > nb_sectors) {
1109 ea2384d3 bellard
            n = nb_sectors;
1110 ae261c86 Fam Zheng
        }
1111 91b85bd3 Fam Zheng
        if (ret) {
1112 91b85bd3 Fam Zheng
            /* if not allocated, try to read from parent image, if exist */
1113 b171271a Kevin Wolf
            if (bs->backing_hd) {
1114 ae261c86 Fam Zheng
                if (!vmdk_is_cid_valid(bs)) {
1115 7fa60fa3 Fam Zheng
                    return -EINVAL;
1116 ae261c86 Fam Zheng
                }
1117 b171271a Kevin Wolf
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
1118 ae261c86 Fam Zheng
                if (ret < 0) {
1119 7fa60fa3 Fam Zheng
                    return ret;
1120 ae261c86 Fam Zheng
                }
1121 5f4da8c0 ths
            } else {
1122 5f4da8c0 ths
                memset(buf, 0, 512 * n);
1123 5f4da8c0 ths
            }
1124 ea2384d3 bellard
        } else {
1125 dd3f6ee2 Fam Zheng
            ret = vmdk_read_extent(extent,
1126 dd3f6ee2 Fam Zheng
                            cluster_offset, index_in_cluster * 512,
1127 dd3f6ee2 Fam Zheng
                            buf, n);
1128 dd3f6ee2 Fam Zheng
            if (ret) {
1129 7fa60fa3 Fam Zheng
                return ret;
1130 7fa60fa3 Fam Zheng
            }
1131 ea2384d3 bellard
        }
1132 ea2384d3 bellard
        nb_sectors -= n;
1133 ea2384d3 bellard
        sector_num += n;
1134 ea2384d3 bellard
        buf += n * 512;
1135 ea2384d3 bellard
    }
1136 ea2384d3 bellard
    return 0;
1137 ea2384d3 bellard
}
1138 ea2384d3 bellard
1139 2914caa0 Paolo Bonzini
static coroutine_fn int vmdk_co_read(BlockDriverState *bs, int64_t sector_num,
1140 2914caa0 Paolo Bonzini
                                     uint8_t *buf, int nb_sectors)
1141 2914caa0 Paolo Bonzini
{
1142 2914caa0 Paolo Bonzini
    int ret;
1143 2914caa0 Paolo Bonzini
    BDRVVmdkState *s = bs->opaque;
1144 2914caa0 Paolo Bonzini
    qemu_co_mutex_lock(&s->lock);
1145 2914caa0 Paolo Bonzini
    ret = vmdk_read(bs, sector_num, buf, nb_sectors);
1146 2914caa0 Paolo Bonzini
    qemu_co_mutex_unlock(&s->lock);
1147 2914caa0 Paolo Bonzini
    return ret;
1148 2914caa0 Paolo Bonzini
}
1149 2914caa0 Paolo Bonzini
1150 5fafdf24 ths
static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
1151 ea2384d3 bellard
                     const uint8_t *buf, int nb_sectors)
1152 ea2384d3 bellard
{
1153 ff1afc72 bellard
    BDRVVmdkState *s = bs->opaque;
1154 b3976d3c Fam Zheng
    VmdkExtent *extent = NULL;
1155 91b85bd3 Fam Zheng
    int n, ret;
1156 b3976d3c Fam Zheng
    int64_t index_in_cluster;
1157 ff1afc72 bellard
    uint64_t cluster_offset;
1158 b3976d3c Fam Zheng
    VmdkMetaData m_data;
1159 ff1afc72 bellard
1160 630530a6 ths
    if (sector_num > bs->total_sectors) {
1161 630530a6 ths
        fprintf(stderr,
1162 92868412 j_mayer
                "(VMDK) Wrong offset: sector_num=0x%" PRIx64
1163 92868412 j_mayer
                " total_sectors=0x%" PRIx64 "\n",
1164 630530a6 ths
                sector_num, bs->total_sectors);
1165 7fa60fa3 Fam Zheng
        return -EIO;
1166 630530a6 ths
    }
1167 630530a6 ths
1168 ff1afc72 bellard
    while (nb_sectors > 0) {
1169 b3976d3c Fam Zheng
        extent = find_extent(s, sector_num, extent);
1170 b3976d3c Fam Zheng
        if (!extent) {
1171 b3976d3c Fam Zheng
            return -EIO;
1172 b3976d3c Fam Zheng
        }
1173 91b85bd3 Fam Zheng
        ret = get_cluster_offset(
1174 b3976d3c Fam Zheng
                                bs,
1175 b3976d3c Fam Zheng
                                extent,
1176 b3976d3c Fam Zheng
                                &m_data,
1177 2b2c8c5d Fam Zheng
                                sector_num << 9, !extent->compressed,
1178 91b85bd3 Fam Zheng
                                &cluster_offset);
1179 2b2c8c5d Fam Zheng
        if (extent->compressed) {
1180 2b2c8c5d Fam Zheng
            if (ret == 0) {
1181 2b2c8c5d Fam Zheng
                /* Refuse write to allocated cluster for streamOptimized */
1182 2b2c8c5d Fam Zheng
                fprintf(stderr,
1183 2b2c8c5d Fam Zheng
                        "VMDK: can't write to allocated cluster"
1184 2b2c8c5d Fam Zheng
                        " for streamOptimized\n");
1185 2b2c8c5d Fam Zheng
                return -EIO;
1186 2b2c8c5d Fam Zheng
            } else {
1187 2b2c8c5d Fam Zheng
                /* allocate */
1188 2b2c8c5d Fam Zheng
                ret = get_cluster_offset(
1189 2b2c8c5d Fam Zheng
                                        bs,
1190 2b2c8c5d Fam Zheng
                                        extent,
1191 2b2c8c5d Fam Zheng
                                        &m_data,
1192 2b2c8c5d Fam Zheng
                                        sector_num << 9, 1,
1193 2b2c8c5d Fam Zheng
                                        &cluster_offset);
1194 2b2c8c5d Fam Zheng
            }
1195 2b2c8c5d Fam Zheng
        }
1196 91b85bd3 Fam Zheng
        if (ret) {
1197 91b85bd3 Fam Zheng
            return -EINVAL;
1198 b3976d3c Fam Zheng
        }
1199 b3976d3c Fam Zheng
        index_in_cluster = sector_num % extent->cluster_sectors;
1200 b3976d3c Fam Zheng
        n = extent->cluster_sectors - index_in_cluster;
1201 b3976d3c Fam Zheng
        if (n > nb_sectors) {
1202 b3976d3c Fam Zheng
            n = nb_sectors;
1203 b3976d3c Fam Zheng
        }
1204 630530a6 ths
1205 dd3f6ee2 Fam Zheng
        ret = vmdk_write_extent(extent,
1206 dd3f6ee2 Fam Zheng
                        cluster_offset, index_in_cluster * 512,
1207 dd3f6ee2 Fam Zheng
                        buf, n, sector_num);
1208 dd3f6ee2 Fam Zheng
        if (ret) {
1209 7fa60fa3 Fam Zheng
            return ret;
1210 b3976d3c Fam Zheng
        }
1211 630530a6 ths
        if (m_data.valid) {
1212 630530a6 ths
            /* update L2 tables */
1213 b3976d3c Fam Zheng
            if (vmdk_L2update(extent, &m_data) == -1) {
1214 7fa60fa3 Fam Zheng
                return -EIO;
1215 b3976d3c Fam Zheng
            }
1216 630530a6 ths
        }
1217 ff1afc72 bellard
        nb_sectors -= n;
1218 ff1afc72 bellard
        sector_num += n;
1219 ff1afc72 bellard
        buf += n * 512;
1220 5f4da8c0 ths
1221 ae261c86 Fam Zheng
        /* update CID on the first write every time the virtual disk is
1222 ae261c86 Fam Zheng
         * opened */
1223 69b4d86d Fam Zheng
        if (!s->cid_updated) {
1224 99f1835d Kevin Wolf
            ret = vmdk_write_cid(bs, time(NULL));
1225 99f1835d Kevin Wolf
            if (ret < 0) {
1226 99f1835d Kevin Wolf
                return ret;
1227 99f1835d Kevin Wolf
            }
1228 69b4d86d Fam Zheng
            s->cid_updated = true;
1229 5f4da8c0 ths
        }
1230 ff1afc72 bellard
    }
1231 ff1afc72 bellard
    return 0;
1232 ea2384d3 bellard
}
1233 ea2384d3 bellard
1234 e183ef75 Paolo Bonzini
static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
1235 e183ef75 Paolo Bonzini
                                      const uint8_t *buf, int nb_sectors)
1236 e183ef75 Paolo Bonzini
{
1237 e183ef75 Paolo Bonzini
    int ret;
1238 e183ef75 Paolo Bonzini
    BDRVVmdkState *s = bs->opaque;
1239 e183ef75 Paolo Bonzini
    qemu_co_mutex_lock(&s->lock);
1240 e183ef75 Paolo Bonzini
    ret = vmdk_write(bs, sector_num, buf, nb_sectors);
1241 e183ef75 Paolo Bonzini
    qemu_co_mutex_unlock(&s->lock);
1242 e183ef75 Paolo Bonzini
    return ret;
1243 e183ef75 Paolo Bonzini
}
1244 e183ef75 Paolo Bonzini
1245 f66fd6c3 Fam Zheng
1246 6c031aac Fam Zheng
static int vmdk_create_extent(const char *filename, int64_t filesize,
1247 6c031aac Fam Zheng
                              bool flat, bool compress)
1248 8979b227 bellard
{
1249 f66fd6c3 Fam Zheng
    int ret, i;
1250 f66fd6c3 Fam Zheng
    int fd = 0;
1251 8979b227 bellard
    VMDK4Header header;
1252 8979b227 bellard
    uint32_t tmp, magic, grains, gd_size, gt_size, gt_count;
1253 0e7e1989 Kevin Wolf
1254 6165f4d8 Corey Bryant
    fd = qemu_open(filename,
1255 6165f4d8 Corey Bryant
                   O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
1256 6165f4d8 Corey Bryant
                   0644);
1257 f66fd6c3 Fam Zheng
    if (fd < 0) {
1258 f66fd6c3 Fam Zheng
        return -errno;
1259 0e7e1989 Kevin Wolf
    }
1260 f66fd6c3 Fam Zheng
    if (flat) {
1261 f66fd6c3 Fam Zheng
        ret = ftruncate(fd, filesize);
1262 f66fd6c3 Fam Zheng
        if (ret < 0) {
1263 f66fd6c3 Fam Zheng
            ret = -errno;
1264 f66fd6c3 Fam Zheng
        }
1265 f66fd6c3 Fam Zheng
        goto exit;
1266 5f4da8c0 ths
    }
1267 8979b227 bellard
    magic = cpu_to_be32(VMDK4_MAGIC);
1268 8979b227 bellard
    memset(&header, 0, sizeof(header));
1269 16372ff0 Alexander Graf
    header.version = 1;
1270 6c031aac Fam Zheng
    header.flags =
1271 6c031aac Fam Zheng
        3 | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0);
1272 6c031aac Fam Zheng
    header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
1273 f66fd6c3 Fam Zheng
    header.capacity = filesize / 512;
1274 16372ff0 Alexander Graf
    header.granularity = 128;
1275 16372ff0 Alexander Graf
    header.num_gtes_per_gte = 512;
1276 8979b227 bellard
1277 f66fd6c3 Fam Zheng
    grains = (filesize / 512 + header.granularity - 1) / header.granularity;
1278 8979b227 bellard
    gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
1279 f66fd6c3 Fam Zheng
    gt_count =
1280 f66fd6c3 Fam Zheng
        (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
1281 8979b227 bellard
    gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
1282 8979b227 bellard
1283 8979b227 bellard
    header.desc_offset = 1;
1284 8979b227 bellard
    header.desc_size = 20;
1285 8979b227 bellard
    header.rgd_offset = header.desc_offset + header.desc_size;
1286 8979b227 bellard
    header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
1287 8979b227 bellard
    header.grain_offset =
1288 8979b227 bellard
       ((header.gd_offset + gd_size + (gt_size * gt_count) +
1289 8979b227 bellard
         header.granularity - 1) / header.granularity) *
1290 8979b227 bellard
        header.granularity;
1291 16372ff0 Alexander Graf
    /* swap endianness for all header fields */
1292 16372ff0 Alexander Graf
    header.version = cpu_to_le32(header.version);
1293 16372ff0 Alexander Graf
    header.flags = cpu_to_le32(header.flags);
1294 16372ff0 Alexander Graf
    header.capacity = cpu_to_le64(header.capacity);
1295 16372ff0 Alexander Graf
    header.granularity = cpu_to_le64(header.granularity);
1296 16372ff0 Alexander Graf
    header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte);
1297 8979b227 bellard
    header.desc_offset = cpu_to_le64(header.desc_offset);
1298 8979b227 bellard
    header.desc_size = cpu_to_le64(header.desc_size);
1299 8979b227 bellard
    header.rgd_offset = cpu_to_le64(header.rgd_offset);
1300 8979b227 bellard
    header.gd_offset = cpu_to_le64(header.gd_offset);
1301 8979b227 bellard
    header.grain_offset = cpu_to_le64(header.grain_offset);
1302 6c031aac Fam Zheng
    header.compressAlgorithm = cpu_to_le16(header.compressAlgorithm);
1303 8979b227 bellard
1304 8979b227 bellard
    header.check_bytes[0] = 0xa;
1305 8979b227 bellard
    header.check_bytes[1] = 0x20;
1306 8979b227 bellard
    header.check_bytes[2] = 0xd;
1307 8979b227 bellard
    header.check_bytes[3] = 0xa;
1308 3b46e624 ths
1309 3b46e624 ths
    /* write all the data */
1310 1640366c Kirill A. Shutemov
    ret = qemu_write_full(fd, &magic, sizeof(magic));
1311 1640366c Kirill A. Shutemov
    if (ret != sizeof(magic)) {
1312 b781cce5 Juan Quintela
        ret = -errno;
1313 1640366c Kirill A. Shutemov
        goto exit;
1314 1640366c Kirill A. Shutemov
    }
1315 1640366c Kirill A. Shutemov
    ret = qemu_write_full(fd, &header, sizeof(header));
1316 1640366c Kirill A. Shutemov
    if (ret != sizeof(header)) {
1317 b781cce5 Juan Quintela
        ret = -errno;
1318 1640366c Kirill A. Shutemov
        goto exit;
1319 1640366c Kirill A. Shutemov
    }
1320 8979b227 bellard
1321 16372ff0 Alexander Graf
    ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9);
1322 1640366c Kirill A. Shutemov
    if (ret < 0) {
1323 b781cce5 Juan Quintela
        ret = -errno;
1324 1640366c Kirill A. Shutemov
        goto exit;
1325 1640366c Kirill A. Shutemov
    }
1326 8979b227 bellard
1327 8979b227 bellard
    /* write grain directory */
1328 8979b227 bellard
    lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
1329 16372ff0 Alexander Graf
    for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size;
1330 1640366c Kirill A. Shutemov
         i < gt_count; i++, tmp += gt_size) {
1331 1640366c Kirill A. Shutemov
        ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1332 1640366c Kirill A. Shutemov
        if (ret != sizeof(tmp)) {
1333 b781cce5 Juan Quintela
            ret = -errno;
1334 1640366c Kirill A. Shutemov
            goto exit;
1335 1640366c Kirill A. Shutemov
        }
1336 1640366c Kirill A. Shutemov
    }
1337 3b46e624 ths
1338 8979b227 bellard
    /* write backup grain directory */
1339 8979b227 bellard
    lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
1340 16372ff0 Alexander Graf
    for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size;
1341 1640366c Kirill A. Shutemov
         i < gt_count; i++, tmp += gt_size) {
1342 1640366c Kirill A. Shutemov
        ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1343 1640366c Kirill A. Shutemov
        if (ret != sizeof(tmp)) {
1344 b781cce5 Juan Quintela
            ret = -errno;
1345 1640366c Kirill A. Shutemov
            goto exit;
1346 1640366c Kirill A. Shutemov
        }
1347 1640366c Kirill A. Shutemov
    }
1348 8979b227 bellard
1349 f66fd6c3 Fam Zheng
    ret = 0;
1350 f66fd6c3 Fam Zheng
 exit:
1351 2e1e79da Corey Bryant
    qemu_close(fd);
1352 f66fd6c3 Fam Zheng
    return ret;
1353 f66fd6c3 Fam Zheng
}
1354 f66fd6c3 Fam Zheng
1355 f66fd6c3 Fam Zheng
static int filename_decompose(const char *filename, char *path, char *prefix,
1356 f66fd6c3 Fam Zheng
        char *postfix, size_t buf_len)
1357 f66fd6c3 Fam Zheng
{
1358 f66fd6c3 Fam Zheng
    const char *p, *q;
1359 f66fd6c3 Fam Zheng
1360 f66fd6c3 Fam Zheng
    if (filename == NULL || !strlen(filename)) {
1361 f66fd6c3 Fam Zheng
        fprintf(stderr, "Vmdk: no filename provided.\n");
1362 f66fd6c3 Fam Zheng
        return -1;
1363 f66fd6c3 Fam Zheng
    }
1364 f66fd6c3 Fam Zheng
    p = strrchr(filename, '/');
1365 f66fd6c3 Fam Zheng
    if (p == NULL) {
1366 f66fd6c3 Fam Zheng
        p = strrchr(filename, '\\');
1367 f66fd6c3 Fam Zheng
    }
1368 f66fd6c3 Fam Zheng
    if (p == NULL) {
1369 f66fd6c3 Fam Zheng
        p = strrchr(filename, ':');
1370 f66fd6c3 Fam Zheng
    }
1371 f66fd6c3 Fam Zheng
    if (p != NULL) {
1372 f66fd6c3 Fam Zheng
        p++;
1373 f66fd6c3 Fam Zheng
        if (p - filename >= buf_len) {
1374 f66fd6c3 Fam Zheng
            return -1;
1375 f66fd6c3 Fam Zheng
        }
1376 f66fd6c3 Fam Zheng
        pstrcpy(path, p - filename + 1, filename);
1377 f66fd6c3 Fam Zheng
    } else {
1378 f66fd6c3 Fam Zheng
        p = filename;
1379 f66fd6c3 Fam Zheng
        path[0] = '\0';
1380 f66fd6c3 Fam Zheng
    }
1381 f66fd6c3 Fam Zheng
    q = strrchr(p, '.');
1382 f66fd6c3 Fam Zheng
    if (q == NULL) {
1383 f66fd6c3 Fam Zheng
        pstrcpy(prefix, buf_len, p);
1384 f66fd6c3 Fam Zheng
        postfix[0] = '\0';
1385 f66fd6c3 Fam Zheng
    } else {
1386 f66fd6c3 Fam Zheng
        if (q - p >= buf_len) {
1387 f66fd6c3 Fam Zheng
            return -1;
1388 f66fd6c3 Fam Zheng
        }
1389 f66fd6c3 Fam Zheng
        pstrcpy(prefix, q - p + 1, p);
1390 f66fd6c3 Fam Zheng
        pstrcpy(postfix, buf_len, q);
1391 f66fd6c3 Fam Zheng
    }
1392 f66fd6c3 Fam Zheng
    return 0;
1393 f66fd6c3 Fam Zheng
}
1394 f66fd6c3 Fam Zheng
1395 f66fd6c3 Fam Zheng
static int relative_path(char *dest, int dest_size,
1396 f66fd6c3 Fam Zheng
        const char *base, const char *target)
1397 f66fd6c3 Fam Zheng
{
1398 f66fd6c3 Fam Zheng
    int i = 0;
1399 f66fd6c3 Fam Zheng
    int n = 0;
1400 f66fd6c3 Fam Zheng
    const char *p, *q;
1401 f66fd6c3 Fam Zheng
#ifdef _WIN32
1402 f66fd6c3 Fam Zheng
    const char *sep = "\\";
1403 f66fd6c3 Fam Zheng
#else
1404 f66fd6c3 Fam Zheng
    const char *sep = "/";
1405 f66fd6c3 Fam Zheng
#endif
1406 f66fd6c3 Fam Zheng
1407 f66fd6c3 Fam Zheng
    if (!(dest && base && target)) {
1408 f66fd6c3 Fam Zheng
        return -1;
1409 f66fd6c3 Fam Zheng
    }
1410 f66fd6c3 Fam Zheng
    if (path_is_absolute(target)) {
1411 f66fd6c3 Fam Zheng
        dest[dest_size - 1] = '\0';
1412 f66fd6c3 Fam Zheng
        strncpy(dest, target, dest_size - 1);
1413 f66fd6c3 Fam Zheng
        return 0;
1414 f66fd6c3 Fam Zheng
    }
1415 f66fd6c3 Fam Zheng
    while (base[i] == target[i]) {
1416 f66fd6c3 Fam Zheng
        i++;
1417 f66fd6c3 Fam Zheng
    }
1418 f66fd6c3 Fam Zheng
    p = &base[i];
1419 f66fd6c3 Fam Zheng
    q = &target[i];
1420 f66fd6c3 Fam Zheng
    while (*p) {
1421 f66fd6c3 Fam Zheng
        if (*p == *sep) {
1422 f66fd6c3 Fam Zheng
            n++;
1423 f66fd6c3 Fam Zheng
        }
1424 f66fd6c3 Fam Zheng
        p++;
1425 f66fd6c3 Fam Zheng
    }
1426 f66fd6c3 Fam Zheng
    dest[0] = '\0';
1427 f66fd6c3 Fam Zheng
    for (; n; n--) {
1428 f66fd6c3 Fam Zheng
        pstrcat(dest, dest_size, "..");
1429 f66fd6c3 Fam Zheng
        pstrcat(dest, dest_size, sep);
1430 f66fd6c3 Fam Zheng
    }
1431 f66fd6c3 Fam Zheng
    pstrcat(dest, dest_size, q);
1432 f66fd6c3 Fam Zheng
    return 0;
1433 f66fd6c3 Fam Zheng
}
1434 f66fd6c3 Fam Zheng
1435 f66fd6c3 Fam Zheng
static int vmdk_create(const char *filename, QEMUOptionParameter *options)
1436 f66fd6c3 Fam Zheng
{
1437 f66fd6c3 Fam Zheng
    int fd, idx = 0;
1438 f66fd6c3 Fam Zheng
    char desc[BUF_SIZE];
1439 f66fd6c3 Fam Zheng
    int64_t total_size = 0, filesize;
1440 f66fd6c3 Fam Zheng
    const char *backing_file = NULL;
1441 f66fd6c3 Fam Zheng
    const char *fmt = NULL;
1442 f66fd6c3 Fam Zheng
    int flags = 0;
1443 f66fd6c3 Fam Zheng
    int ret = 0;
1444 6c031aac Fam Zheng
    bool flat, split, compress;
1445 f66fd6c3 Fam Zheng
    char ext_desc_lines[BUF_SIZE] = "";
1446 f66fd6c3 Fam Zheng
    char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
1447 f66fd6c3 Fam Zheng
    const int64_t split_size = 0x80000000;  /* VMDK has constant split size */
1448 f66fd6c3 Fam Zheng
    const char *desc_extent_line;
1449 f66fd6c3 Fam Zheng
    char parent_desc_line[BUF_SIZE] = "";
1450 f66fd6c3 Fam Zheng
    uint32_t parent_cid = 0xffffffff;
1451 f66fd6c3 Fam Zheng
    const char desc_template[] =
1452 f66fd6c3 Fam Zheng
        "# Disk DescriptorFile\n"
1453 f66fd6c3 Fam Zheng
        "version=1\n"
1454 f66fd6c3 Fam Zheng
        "CID=%x\n"
1455 f66fd6c3 Fam Zheng
        "parentCID=%x\n"
1456 f66fd6c3 Fam Zheng
        "createType=\"%s\"\n"
1457 f66fd6c3 Fam Zheng
        "%s"
1458 f66fd6c3 Fam Zheng
        "\n"
1459 f66fd6c3 Fam Zheng
        "# Extent description\n"
1460 f66fd6c3 Fam Zheng
        "%s"
1461 f66fd6c3 Fam Zheng
        "\n"
1462 f66fd6c3 Fam Zheng
        "# The Disk Data Base\n"
1463 f66fd6c3 Fam Zheng
        "#DDB\n"
1464 f66fd6c3 Fam Zheng
        "\n"
1465 f66fd6c3 Fam Zheng
        "ddb.virtualHWVersion = \"%d\"\n"
1466 f66fd6c3 Fam Zheng
        "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
1467 f66fd6c3 Fam Zheng
        "ddb.geometry.heads = \"16\"\n"
1468 f66fd6c3 Fam Zheng
        "ddb.geometry.sectors = \"63\"\n"
1469 f66fd6c3 Fam Zheng
        "ddb.adapterType = \"ide\"\n";
1470 f66fd6c3 Fam Zheng
1471 f66fd6c3 Fam Zheng
    if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) {
1472 f66fd6c3 Fam Zheng
        return -EINVAL;
1473 f66fd6c3 Fam Zheng
    }
1474 f66fd6c3 Fam Zheng
    /* Read out options */
1475 f66fd6c3 Fam Zheng
    while (options && options->name) {
1476 f66fd6c3 Fam Zheng
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
1477 f66fd6c3 Fam Zheng
            total_size = options->value.n;
1478 f66fd6c3 Fam Zheng
        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
1479 f66fd6c3 Fam Zheng
            backing_file = options->value.s;
1480 f66fd6c3 Fam Zheng
        } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
1481 f66fd6c3 Fam Zheng
            flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0;
1482 f66fd6c3 Fam Zheng
        } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
1483 f66fd6c3 Fam Zheng
            fmt = options->value.s;
1484 f66fd6c3 Fam Zheng
        }
1485 f66fd6c3 Fam Zheng
        options++;
1486 f66fd6c3 Fam Zheng
    }
1487 f66fd6c3 Fam Zheng
    if (!fmt) {
1488 f66fd6c3 Fam Zheng
        /* Default format to monolithicSparse */
1489 f66fd6c3 Fam Zheng
        fmt = "monolithicSparse";
1490 f66fd6c3 Fam Zheng
    } else if (strcmp(fmt, "monolithicFlat") &&
1491 f66fd6c3 Fam Zheng
               strcmp(fmt, "monolithicSparse") &&
1492 f66fd6c3 Fam Zheng
               strcmp(fmt, "twoGbMaxExtentSparse") &&
1493 6c031aac Fam Zheng
               strcmp(fmt, "twoGbMaxExtentFlat") &&
1494 6c031aac Fam Zheng
               strcmp(fmt, "streamOptimized")) {
1495 f66fd6c3 Fam Zheng
        fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt);
1496 f66fd6c3 Fam Zheng
        return -EINVAL;
1497 f66fd6c3 Fam Zheng
    }
1498 f66fd6c3 Fam Zheng
    split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
1499 f66fd6c3 Fam Zheng
              strcmp(fmt, "twoGbMaxExtentSparse"));
1500 f66fd6c3 Fam Zheng
    flat = !(strcmp(fmt, "monolithicFlat") &&
1501 f66fd6c3 Fam Zheng
             strcmp(fmt, "twoGbMaxExtentFlat"));
1502 6c031aac Fam Zheng
    compress = !strcmp(fmt, "streamOptimized");
1503 f66fd6c3 Fam Zheng
    if (flat) {
1504 f66fd6c3 Fam Zheng
        desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
1505 f66fd6c3 Fam Zheng
    } else {
1506 f66fd6c3 Fam Zheng
        desc_extent_line = "RW %lld SPARSE \"%s\"\n";
1507 f66fd6c3 Fam Zheng
    }
1508 f66fd6c3 Fam Zheng
    if (flat && backing_file) {
1509 f66fd6c3 Fam Zheng
        /* not supporting backing file for flat image */
1510 f66fd6c3 Fam Zheng
        return -ENOTSUP;
1511 f66fd6c3 Fam Zheng
    }
1512 f66fd6c3 Fam Zheng
    if (backing_file) {
1513 f66fd6c3 Fam Zheng
        char parent_filename[PATH_MAX];
1514 f66fd6c3 Fam Zheng
        BlockDriverState *bs = bdrv_new("");
1515 f66fd6c3 Fam Zheng
        ret = bdrv_open(bs, backing_file, 0, NULL);
1516 f66fd6c3 Fam Zheng
        if (ret != 0) {
1517 f66fd6c3 Fam Zheng
            bdrv_delete(bs);
1518 f66fd6c3 Fam Zheng
            return ret;
1519 f66fd6c3 Fam Zheng
        }
1520 f66fd6c3 Fam Zheng
        if (strcmp(bs->drv->format_name, "vmdk")) {
1521 f66fd6c3 Fam Zheng
            bdrv_delete(bs);
1522 f66fd6c3 Fam Zheng
            return -EINVAL;
1523 f66fd6c3 Fam Zheng
        }
1524 f66fd6c3 Fam Zheng
        parent_cid = vmdk_read_cid(bs, 0);
1525 f66fd6c3 Fam Zheng
        bdrv_delete(bs);
1526 f66fd6c3 Fam Zheng
        relative_path(parent_filename, sizeof(parent_filename),
1527 f66fd6c3 Fam Zheng
                      filename, backing_file);
1528 f66fd6c3 Fam Zheng
        snprintf(parent_desc_line, sizeof(parent_desc_line),
1529 f66fd6c3 Fam Zheng
                "parentFileNameHint=\"%s\"", parent_filename);
1530 f66fd6c3 Fam Zheng
    }
1531 f66fd6c3 Fam Zheng
1532 f66fd6c3 Fam Zheng
    /* Create extents */
1533 f66fd6c3 Fam Zheng
    filesize = total_size;
1534 f66fd6c3 Fam Zheng
    while (filesize > 0) {
1535 f66fd6c3 Fam Zheng
        char desc_line[BUF_SIZE];
1536 f66fd6c3 Fam Zheng
        char ext_filename[PATH_MAX];
1537 f66fd6c3 Fam Zheng
        char desc_filename[PATH_MAX];
1538 f66fd6c3 Fam Zheng
        int64_t size = filesize;
1539 f66fd6c3 Fam Zheng
1540 f66fd6c3 Fam Zheng
        if (split && size > split_size) {
1541 f66fd6c3 Fam Zheng
            size = split_size;
1542 f66fd6c3 Fam Zheng
        }
1543 f66fd6c3 Fam Zheng
        if (split) {
1544 f66fd6c3 Fam Zheng
            snprintf(desc_filename, sizeof(desc_filename), "%s-%c%03d%s",
1545 f66fd6c3 Fam Zheng
                    prefix, flat ? 'f' : 's', ++idx, postfix);
1546 f66fd6c3 Fam Zheng
        } else if (flat) {
1547 f66fd6c3 Fam Zheng
            snprintf(desc_filename, sizeof(desc_filename), "%s-flat%s",
1548 f66fd6c3 Fam Zheng
                    prefix, postfix);
1549 f66fd6c3 Fam Zheng
        } else {
1550 f66fd6c3 Fam Zheng
            snprintf(desc_filename, sizeof(desc_filename), "%s%s",
1551 f66fd6c3 Fam Zheng
                    prefix, postfix);
1552 f66fd6c3 Fam Zheng
        }
1553 f66fd6c3 Fam Zheng
        snprintf(ext_filename, sizeof(ext_filename), "%s%s",
1554 f66fd6c3 Fam Zheng
                path, desc_filename);
1555 f66fd6c3 Fam Zheng
1556 6c031aac Fam Zheng
        if (vmdk_create_extent(ext_filename, size, flat, compress)) {
1557 f66fd6c3 Fam Zheng
            return -EINVAL;
1558 f66fd6c3 Fam Zheng
        }
1559 f66fd6c3 Fam Zheng
        filesize -= size;
1560 f66fd6c3 Fam Zheng
1561 f66fd6c3 Fam Zheng
        /* Format description line */
1562 f66fd6c3 Fam Zheng
        snprintf(desc_line, sizeof(desc_line),
1563 f66fd6c3 Fam Zheng
                    desc_extent_line, size / 512, desc_filename);
1564 f66fd6c3 Fam Zheng
        pstrcat(ext_desc_lines, sizeof(ext_desc_lines), desc_line);
1565 f66fd6c3 Fam Zheng
    }
1566 f66fd6c3 Fam Zheng
    /* generate descriptor file */
1567 f66fd6c3 Fam Zheng
    snprintf(desc, sizeof(desc), desc_template,
1568 f66fd6c3 Fam Zheng
            (unsigned int)time(NULL),
1569 f66fd6c3 Fam Zheng
            parent_cid,
1570 f66fd6c3 Fam Zheng
            fmt,
1571 f66fd6c3 Fam Zheng
            parent_desc_line,
1572 f66fd6c3 Fam Zheng
            ext_desc_lines,
1573 f66fd6c3 Fam Zheng
            (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
1574 f66fd6c3 Fam Zheng
            total_size / (int64_t)(63 * 16 * 512));
1575 f66fd6c3 Fam Zheng
    if (split || flat) {
1576 6165f4d8 Corey Bryant
        fd = qemu_open(filename,
1577 6165f4d8 Corey Bryant
                       O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
1578 6165f4d8 Corey Bryant
                       0644);
1579 f66fd6c3 Fam Zheng
    } else {
1580 6165f4d8 Corey Bryant
        fd = qemu_open(filename,
1581 6165f4d8 Corey Bryant
                       O_WRONLY | O_BINARY | O_LARGEFILE,
1582 6165f4d8 Corey Bryant
                       0644);
1583 f66fd6c3 Fam Zheng
    }
1584 f66fd6c3 Fam Zheng
    if (fd < 0) {
1585 f66fd6c3 Fam Zheng
        return -errno;
1586 f66fd6c3 Fam Zheng
    }
1587 f66fd6c3 Fam Zheng
    /* the descriptor offset = 0x200 */
1588 f66fd6c3 Fam Zheng
    if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
1589 f66fd6c3 Fam Zheng
        ret = -errno;
1590 f66fd6c3 Fam Zheng
        goto exit;
1591 f66fd6c3 Fam Zheng
    }
1592 1640366c Kirill A. Shutemov
    ret = qemu_write_full(fd, desc, strlen(desc));
1593 1640366c Kirill A. Shutemov
    if (ret != strlen(desc)) {
1594 b781cce5 Juan Quintela
        ret = -errno;
1595 1640366c Kirill A. Shutemov
        goto exit;
1596 1640366c Kirill A. Shutemov
    }
1597 1640366c Kirill A. Shutemov
    ret = 0;
1598 1640366c Kirill A. Shutemov
exit:
1599 2e1e79da Corey Bryant
    qemu_close(fd);
1600 1640366c Kirill A. Shutemov
    return ret;
1601 8979b227 bellard
}
1602 8979b227 bellard
1603 e2731add bellard
static void vmdk_close(BlockDriverState *bs)
1604 ea2384d3 bellard
{
1605 2bc3166c Kevin Wolf
    BDRVVmdkState *s = bs->opaque;
1606 2bc3166c Kevin Wolf
1607 b3976d3c Fam Zheng
    vmdk_free_extents(bs);
1608 2bc3166c Kevin Wolf
1609 2bc3166c Kevin Wolf
    migrate_del_blocker(s->migration_blocker);
1610 2bc3166c Kevin Wolf
    error_free(s->migration_blocker);
1611 ea2384d3 bellard
}
1612 ea2384d3 bellard
1613 8b94ff85 Paolo Bonzini
static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
1614 7a6cba61 pbrook
{
1615 333c574d Fam Zheng
    BDRVVmdkState *s = bs->opaque;
1616 29cdb251 Paolo Bonzini
    int i, err;
1617 29cdb251 Paolo Bonzini
    int ret = 0;
1618 333c574d Fam Zheng
1619 333c574d Fam Zheng
    for (i = 0; i < s->num_extents; i++) {
1620 8b94ff85 Paolo Bonzini
        err = bdrv_co_flush(s->extents[i].file);
1621 333c574d Fam Zheng
        if (err < 0) {
1622 333c574d Fam Zheng
            ret = err;
1623 333c574d Fam Zheng
        }
1624 333c574d Fam Zheng
    }
1625 333c574d Fam Zheng
    return ret;
1626 7a6cba61 pbrook
}
1627 7a6cba61 pbrook
1628 4a1d5e1f Fam Zheng
static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
1629 4a1d5e1f Fam Zheng
{
1630 4a1d5e1f Fam Zheng
    int i;
1631 4a1d5e1f Fam Zheng
    int64_t ret = 0;
1632 4a1d5e1f Fam Zheng
    int64_t r;
1633 4a1d5e1f Fam Zheng
    BDRVVmdkState *s = bs->opaque;
1634 4a1d5e1f Fam Zheng
1635 4a1d5e1f Fam Zheng
    ret = bdrv_get_allocated_file_size(bs->file);
1636 4a1d5e1f Fam Zheng
    if (ret < 0) {
1637 4a1d5e1f Fam Zheng
        return ret;
1638 4a1d5e1f Fam Zheng
    }
1639 4a1d5e1f Fam Zheng
    for (i = 0; i < s->num_extents; i++) {
1640 4a1d5e1f Fam Zheng
        if (s->extents[i].file == bs->file) {
1641 4a1d5e1f Fam Zheng
            continue;
1642 4a1d5e1f Fam Zheng
        }
1643 4a1d5e1f Fam Zheng
        r = bdrv_get_allocated_file_size(s->extents[i].file);
1644 4a1d5e1f Fam Zheng
        if (r < 0) {
1645 4a1d5e1f Fam Zheng
            return r;
1646 4a1d5e1f Fam Zheng
        }
1647 4a1d5e1f Fam Zheng
        ret += r;
1648 4a1d5e1f Fam Zheng
    }
1649 4a1d5e1f Fam Zheng
    return ret;
1650 4a1d5e1f Fam Zheng
}
1651 0e7e1989 Kevin Wolf
1652 0e7e1989 Kevin Wolf
static QEMUOptionParameter vmdk_create_options[] = {
1653 db08adf5 Kevin Wolf
    {
1654 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_SIZE,
1655 db08adf5 Kevin Wolf
        .type = OPT_SIZE,
1656 db08adf5 Kevin Wolf
        .help = "Virtual disk size"
1657 db08adf5 Kevin Wolf
    },
1658 db08adf5 Kevin Wolf
    {
1659 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_BACKING_FILE,
1660 db08adf5 Kevin Wolf
        .type = OPT_STRING,
1661 db08adf5 Kevin Wolf
        .help = "File name of a base image"
1662 db08adf5 Kevin Wolf
    },
1663 db08adf5 Kevin Wolf
    {
1664 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_COMPAT6,
1665 db08adf5 Kevin Wolf
        .type = OPT_FLAG,
1666 db08adf5 Kevin Wolf
        .help = "VMDK version 6 image"
1667 db08adf5 Kevin Wolf
    },
1668 f66fd6c3 Fam Zheng
    {
1669 f66fd6c3 Fam Zheng
        .name = BLOCK_OPT_SUBFMT,
1670 f66fd6c3 Fam Zheng
        .type = OPT_STRING,
1671 f66fd6c3 Fam Zheng
        .help =
1672 f66fd6c3 Fam Zheng
            "VMDK flat extent format, can be one of "
1673 6c031aac Fam Zheng
            "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
1674 f66fd6c3 Fam Zheng
    },
1675 0e7e1989 Kevin Wolf
    { NULL }
1676 0e7e1989 Kevin Wolf
};
1677 0e7e1989 Kevin Wolf
1678 5efa9d5a Anthony Liguori
static BlockDriver bdrv_vmdk = {
1679 ae261c86 Fam Zheng
    .format_name    = "vmdk",
1680 ae261c86 Fam Zheng
    .instance_size  = sizeof(BDRVVmdkState),
1681 ae261c86 Fam Zheng
    .bdrv_probe     = vmdk_probe,
1682 6511ef77 Kevin Wolf
    .bdrv_open      = vmdk_open,
1683 3897575f Jeff Cody
    .bdrv_reopen_prepare = vmdk_reopen_prepare,
1684 2914caa0 Paolo Bonzini
    .bdrv_read      = vmdk_co_read,
1685 e183ef75 Paolo Bonzini
    .bdrv_write     = vmdk_co_write,
1686 ae261c86 Fam Zheng
    .bdrv_close     = vmdk_close,
1687 ae261c86 Fam Zheng
    .bdrv_create    = vmdk_create,
1688 c68b89ac Kevin Wolf
    .bdrv_co_flush_to_disk  = vmdk_co_flush,
1689 f8a2e5e3 Stefan Hajnoczi
    .bdrv_co_is_allocated   = vmdk_co_is_allocated,
1690 4a1d5e1f Fam Zheng
    .bdrv_get_allocated_file_size  = vmdk_get_allocated_file_size,
1691 0e7e1989 Kevin Wolf
1692 0e7e1989 Kevin Wolf
    .create_options = vmdk_create_options,
1693 ea2384d3 bellard
};
1694 5efa9d5a Anthony Liguori
1695 5efa9d5a Anthony Liguori
static void bdrv_vmdk_init(void)
1696 5efa9d5a Anthony Liguori
{
1697 5efa9d5a Anthony Liguori
    bdrv_register(&bdrv_vmdk);
1698 5efa9d5a Anthony Liguori
}
1699 5efa9d5a Anthony Liguori
1700 5efa9d5a Anthony Liguori
block_init(bdrv_vmdk_init);