1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26: #include "qemu-common.h"
27: #include "block_int.h"
28:
29: #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
30: #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
31:
32: typedef struct {
33: uint32_t version;
34: uint32_t flags;
35: uint32_t disk_sectors;
36: uint32_t granularity;
37: uint32_t l1dir_offset;
38: uint32_t l1dir_size;
39: uint32_t file_sectors;
40: uint32_t cylinders;
41: uint32_t heads;
42: uint32_t sectors_per_track;
43: } VMDK3Header;
44:
45: typedef struct {
46: uint32_t version;
47: uint32_t flags;
48: int64_t capacity;
49: int64_t granularity;
50: int64_t desc_offset;
51: int64_t desc_size;
52: int32_t num_gtes_per_gte;
53: int64_t rgd_offset;
54: int64_t gd_offset;
55: int64_t grain_offset;
56: char filler[1];
57: char check_bytes[4];
58: } __attribute__((packed)) VMDK4Header;
59:
60: #define L2_CACHE_SIZE 16
61:
62: typedef struct BDRVVmdkState {
63: BlockDriverState *hd;
64: int64_t l1_table_offset;
65: int64_t l1_backup_table_offset;
66: uint32_t *l1_table;
67: uint32_t *l1_backup_table;
68: unsigned int l1_size;
69: uint32_t l1_entry_sectors;
70:
71: unsigned int l2_size;
72: uint32_t *l2_cache;
73: uint32_t l2_cache_offsets[L2_CACHE_SIZE];
74: uint32_t l2_cache_counts[L2_CACHE_SIZE];
75:
76: unsigned int cluster_sectors;
77: uint32_t parent_cid;
78: int is_parent;
79: } BDRVVmdkState;
80:
81: typedef struct VmdkMetaData {
82: uint32_t offset;
83: unsigned int l1_index;
84: unsigned int l2_index;
85: unsigned int l2_offset;
86: int valid;
87: } VmdkMetaData;
88:
89: typedef struct ActiveBDRVState{
90: BlockDriverState *hd;
91: uint64_t cluster_offset;
92: }ActiveBDRVState;
93:
94: static ActiveBDRVState activeBDRV;
95:
96:
97: static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
98: {
99: uint32_t magic;
100:
101: if (buf_size < 4)
102: return 0;
103: magic = be32_to_cpu(*(uint32_t *)buf);
104: if (magic == VMDK3_MAGIC ||
105: magic == VMDK4_MAGIC)
106: return 100;
107: else
108: return 0;
109: }
110:
111: #define CHECK_CID 1
112:
113: #define SECTOR_SIZE 512
114: #define DESC_SIZE 20*SECTOR_SIZE
115: #define HEADER_SIZE 512
116:
117: static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
118: {
119: BDRVVmdkState *s = bs->opaque;
120: char desc[DESC_SIZE];
121: uint32_t cid;
122: char *p_name, *cid_str;
123: size_t cid_str_size;
124:
125:
126: if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
127: return 0;
128:
129: if (parent) {
130: cid_str = "parentCID";
131: cid_str_size = sizeof("parentCID");
132: } else {
133: cid_str = "CID";
134: cid_str_size = sizeof("CID");
135: }
136:
137: if ((p_name = strstr(desc,cid_str)) != 0) {
138: p_name += cid_str_size;
139: sscanf(p_name,"%x",&cid);
140: }
141:
142: return cid;
143: }
144:
145: static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
146: {
147: BDRVVmdkState *s = bs->opaque;
148: char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
149: char *p_name, *tmp_str;
150:
151:
152: if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
153: return -1;
154:
155: tmp_str = strstr(desc,"parentCID");
156: strcpy(tmp_desc, tmp_str);
157: if ((p_name = strstr(desc,"CID")) != 0) {
158: p_name += sizeof("CID");
159: sprintf(p_name,"%x\n",cid);
160: strcat(desc,tmp_desc);
161: }
162:
163: if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
164: return -1;
165: return 0;
166: }
167:
168: static int vmdk_is_cid_valid(BlockDriverState *bs)
169: {
170: #ifdef CHECK_CID
171: BDRVVmdkState *s = bs->opaque;
172: BlockDriverState *p_bs = s->hd->backing_hd;
173: uint32_t cur_pcid;
174:
175: if (p_bs) {
176: cur_pcid = vmdk_read_cid(p_bs,0);
177: if (s->parent_cid != cur_pcid)
178:
179: return 0;
180: }
181: #endif
182:
183: return 1;
184: }
185:
186: static int vmdk_snapshot_create(const char *filename, const char *backing_file)
187: {
188: int snp_fd, p_fd;
189: uint32_t p_cid;
190: char *p_name, *gd_buf, *rgd_buf;
191: const char *real_filename, *temp_str;
192: VMDK4Header header;
193: uint32_t gde_entries, gd_size;
194: int64_t gd_offset, rgd_offset, capacity, gt_size;
195: char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
196: char *desc_template =
197: "# Disk DescriptorFile\n"
198: "version=1\n"
199: "CID=%x\n"
200: "parentCID=%x\n"
201: "createType=\"monolithicSparse\"\n"
202: "parentFileNameHint=\"%s\"\n"
203: "\n"
204: "# Extent description\n"
205: "RW %lu SPARSE \"%s\"\n"
206: "\n"
207: "# The Disk Data Base \n"
208: "#DDB\n"
209: "\n";
210:
211: snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
212: if (snp_fd < 0)
213: return -1;
214: p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
215: if (p_fd < 0) {
216: close(snp_fd);
217: return -1;
218: }
219:
220:
221: if (lseek(p_fd, 0x0, SEEK_SET) == -1)
222: goto fail;
223: if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
224: goto fail;
225:
226:
227: if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
228: goto fail;
229: if (write(snp_fd, hdr, HEADER_SIZE) == -1)
230: goto fail;
231:
232: memset(&header, 0, sizeof(header));
233: memcpy(&header,&hdr[4], sizeof(header));
234:
235: ftruncate(snp_fd, header.grain_offset << 9);
236:
237: if (lseek(p_fd, 0x200, SEEK_SET) == -1)
238: goto fail;
239: if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
240: goto fail;
241:
242: if ((p_name = strstr(p_desc,"CID")) != 0) {
243: p_name += sizeof("CID");
244: sscanf(p_name,"%x",&p_cid);
245: }
246:
247: real_filename = filename;
248: if ((temp_str = strrchr(real_filename, '\\')) != NULL)
249: real_filename = temp_str + 1;
250: if ((temp_str = strrchr(real_filename, '/')) != NULL)
251: real_filename = temp_str + 1;
252: if ((temp_str = strrchr(real_filename, ':')) != NULL)
253: real_filename = temp_str + 1;
254:
255: sprintf(s_desc, desc_template, p_cid, p_cid, backing_file
256: , (uint32_t)header.capacity, real_filename);
257:
258:
259: if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
260: goto fail;
261: if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
262: goto fail;
263:
264: gd_offset = header.gd_offset * SECTOR_SIZE;
265: rgd_offset = header.rgd_offset * SECTOR_SIZE;
266: capacity = header.capacity * SECTOR_SIZE;
267:
268:
269:
270:
271: gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
272: if (!gt_size)
273: goto fail;
274: gde_entries = (uint32_t)(capacity / gt_size);
275: gd_size = gde_entries * sizeof(uint32_t);
276:
277:
278: rgd_buf = qemu_malloc(gd_size);
279: if (!rgd_buf)
280: goto fail;
281: if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
282: goto fail_rgd;
283: if (read(p_fd, rgd_buf, gd_size) != gd_size)
284: goto fail_rgd;
285: if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
286: goto fail_rgd;
287: if (write(snp_fd, rgd_buf, gd_size) == -1)
288: goto fail_rgd;
289: qemu_free(rgd_buf);
290:
291:
292: gd_buf = qemu_malloc(gd_size);
293: if (!gd_buf)
294: goto fail_rgd;
295: if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
296: goto fail_gd;
297: if (read(p_fd, gd_buf, gd_size) != gd_size)
298: goto fail_gd;
299: if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
300: goto fail_gd;
301: if (write(snp_fd, gd_buf, gd_size) == -1)
302: goto fail_gd;
303: qemu_free(gd_buf);
304:
305: close(p_fd);
306: close(snp_fd);
307: return 0;
308:
309: fail_gd:
310: qemu_free(gd_buf);
311: fail_rgd:
312: qemu_free(rgd_buf);
313: fail:
314: close(p_fd);
315: close(snp_fd);
316: return -1;
317: }
318:
319: static void vmdk_parent_close(BlockDriverState *bs)
320: {
321: if (bs->backing_hd)
322: bdrv_close(bs->backing_hd);
323: }
324:
325: int parent_open = 0;
326: static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
327: {
328: BDRVVmdkState *s = bs->opaque;
329: char *p_name;
330: char desc[DESC_SIZE];
331: char parent_img_name[1024];
332:
333:
334: if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
335: return -1;
336:
337: if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
338: char *end_name;
339: struct stat file_buf;
340:
341: p_name += sizeof("parentFileNameHint") + 1;
342: if ((end_name = strchr(p_name,'\"')) == 0)
343: return -1;
344:
345: strncpy(s->hd->backing_file, p_name, end_name - p_name);
346: if (stat(s->hd->backing_file, &file_buf) != 0) {
347: path_combine(parent_img_name, sizeof(parent_img_name),
348: filename, s->hd->backing_file);
349: } else {
350: strcpy(parent_img_name, s->hd->backing_file);
351: }
352:
353: s->hd->backing_hd = bdrv_new("");
354: if (!s->hd->backing_hd) {
355: failure:
356: bdrv_close(s->hd);
357: return -1;
358: }
359: parent_open = 1;
360: if (bdrv_open(s->hd->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)
361: goto failure;
362: parent_open = 0;
363: }
364:
365: return 0;
366: }
367:
368: static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
369: {
370: BDRVVmdkState *s = bs->opaque;
371: uint32_t magic;
372: int l1_size, i, ret;
373:
374: if (parent_open)
375:
376: flags = BDRV_O_RDONLY;
377: fprintf(stderr, "(VMDK) image open: flags=0x%x filename=%s\n", flags, bs->filename);
378:
379: ret = bdrv_file_open(&s->hd, filename, flags);
380: if (ret < 0)
381: return ret;
382: if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
383: goto fail;
384:
385: magic = be32_to_cpu(magic);
386: if (magic == VMDK3_MAGIC) {
387: VMDK3Header header;
388:
389: if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
390: goto fail;
391: s->cluster_sectors = le32_to_cpu(header.granularity);
392: s->l2_size = 1 << 9;
393: s->l1_size = 1 << 6;
394: bs->total_sectors = le32_to_cpu(header.disk_sectors);
395: s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9;
396: s->l1_backup_table_offset = 0;
397: s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
398: } else if (magic == VMDK4_MAGIC) {
399: VMDK4Header header;
400:
401: if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
402: goto fail;
403: bs->total_sectors = le64_to_cpu(header.capacity);
404: s->cluster_sectors = le64_to_cpu(header.granularity);
405: s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
406: s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
407: if (s->l1_entry_sectors <= 0)
408: goto fail;
409: s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
410: / s->l1_entry_sectors;
411: s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
412: s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
413:
414: if (parent_open)
415: s->is_parent = 1;
416: else
417: s->is_parent = 0;
418:
419:
420: if (vmdk_parent_open(bs, filename) != 0)
421: goto fail;
422:
423: s->parent_cid = vmdk_read_cid(bs,1);
424: } else {
425: goto fail;
426: }
427:
428:
429: l1_size = s->l1_size * sizeof(uint32_t);
430: s->l1_table = qemu_malloc(l1_size);
431: if (!s->l1_table)
432: goto fail;
433: if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
434: goto fail;
435: for(i = 0; i < s->l1_size; i++) {
436: le32_to_cpus(&s->l1_table[i]);
437: }
438:
439: if (s->l1_backup_table_offset) {
440: s->l1_backup_table = qemu_malloc(l1_size);
441: if (!s->l1_backup_table)
442: goto fail;
443: if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
444: goto fail;
445: for(i = 0; i < s->l1_size; i++) {
446: le32_to_cpus(&s->l1_backup_table[i]);
447: }
448: }
449:
450: s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
451: if (!s->l2_cache)
452: goto fail;
453: return 0;
454: fail:
455: qemu_free(s->l1_backup_table);
456: qemu_free(s->l1_table);
457: qemu_free(s->l2_cache);
458: bdrv_delete(s->hd);
459: return -1;
460: }
461:
462: static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
463: uint64_t offset, int allocate);
464:
465: static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
466: uint64_t offset, int allocate)
467: {
468: uint64_t parent_cluster_offset;
469: BDRVVmdkState *s = bs->opaque;
470: uint8_t whole_grain[s->cluster_sectors*512];
471:
472:
473:
474: if (s->hd->backing_hd) {
475: BDRVVmdkState *ps = s->hd->backing_hd->opaque;
476:
477: if (!vmdk_is_cid_valid(bs))
478: return -1;
479:
480: parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, NULL, offset, allocate);
481:
482: if (parent_cluster_offset) {
483: BDRVVmdkState *act_s = activeBDRV.hd->opaque;
484:
485: if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != ps->cluster_sectors*512)
486: return -1;
487:
488:
489: if (bdrv_pwrite(act_s->hd, activeBDRV.cluster_offset << 9, whole_grain, sizeof(whole_grain)) != sizeof(whole_grain))
490: return -1;
491: }
492: }
493: return 0;
494: }
495:
496: static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)
497: {
498: BDRVVmdkState *s = bs->opaque;
499:
500:
501: if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
502: &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
503: return -1;
504:
505: if (s->l1_backup_table_offset != 0) {
506: m_data->l2_offset = s->l1_backup_table[m_data->l1_index];
507: if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
508: &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
509: return -1;
510: }
511:
512: return 0;
513: }
514:
515: static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
516: uint64_t offset, int allocate)
517: {
518: BDRVVmdkState *s = bs->opaque;
519: unsigned int l1_index, l2_offset, l2_index;
520: int min_index, i, j;
521: uint32_t min_count, *l2_table, tmp = 0;
522: uint64_t cluster_offset;
523:
524: if (m_data)
525: m_data->valid = 0;
526:
527: l1_index = (offset >> 9) / s->l1_entry_sectors;
528: if (l1_index >= s->l1_size)
529: return 0;
530: l2_offset = s->l1_table[l1_index];
531: if (!l2_offset)
532: return 0;
533: for(i = 0; i < L2_CACHE_SIZE; i++) {
534: if (l2_offset == s->l2_cache_offsets[i]) {
535:
536: if (++s->l2_cache_counts[i] == 0xffffffff) {
537: for(j = 0; j < L2_CACHE_SIZE; j++) {
538: s->l2_cache_counts[j] >>= 1;
539: }
540: }
541: l2_table = s->l2_cache + (i * s->l2_size);
542: goto found;
543: }
544: }
545:
546: min_index = 0;
547: min_count = 0xffffffff;
548: for(i = 0; i < L2_CACHE_SIZE; i++) {
549: if (s->l2_cache_counts[i] < min_count) {
550: min_count = s->l2_cache_counts[i];
551: min_index = i;
552: }
553: }
554: l2_table = s->l2_cache + (min_index * s->l2_size);