Statistics
| Branch: | Revision:

root / block / vmdk.c @ 73f5e313

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