qcow_make_empty() support (Johannes Schindelin)
[qemu] / block.c
1 /*
2  * QEMU System Emulator block driver
3  * 
4  * Copyright (c) 2003 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25 #include "block_int.h"
26
27 #ifdef _BSD
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/queue.h>
32 #include <sys/disk.h>
33 #endif
34
35 #ifdef CONFIG_COCOA
36 #include <paths.h>
37 #include <sys/param.h>
38 #include <IOKit/IOKitLib.h>
39 #include <IOKit/IOBSD.h>
40 #include <IOKit/storage/IOMediaBSDClient.h>
41 #include <IOKit/storage/IOMedia.h>
42 #include <IOKit/storage/IOCDMedia.h>
43 //#include <IOKit/storage/IOCDTypes.h>
44 #include <CoreFoundation/CoreFoundation.h>
45 #endif
46
47 static BlockDriverState *bdrv_first;
48 static BlockDriver *first_drv;
49
50 #ifdef CONFIG_COCOA
51 static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
52 static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
53
54 kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
55 {
56     kern_return_t       kernResult; 
57     mach_port_t     masterPort;
58     CFMutableDictionaryRef  classesToMatch;
59
60     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
61     if ( KERN_SUCCESS != kernResult ) {
62         printf( "IOMasterPort returned %d\n", kernResult );
63     }
64     
65     classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
66     if ( classesToMatch == NULL ) {
67         printf( "IOServiceMatching returned a NULL dictionary.\n" );
68     } else {
69     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
70     }
71     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
72     if ( KERN_SUCCESS != kernResult )
73     {
74         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
75     }
76     
77     return kernResult;
78 }
79
80 kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
81 {
82     io_object_t     nextMedia;
83     kern_return_t   kernResult = KERN_FAILURE;
84     *bsdPath = '\0';
85     nextMedia = IOIteratorNext( mediaIterator );
86     if ( nextMedia )
87     {
88         CFTypeRef   bsdPathAsCFString;
89     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
90         if ( bsdPathAsCFString ) {
91             size_t devPathLength;
92             strcpy( bsdPath, _PATH_DEV );
93             strcat( bsdPath, "r" );
94             devPathLength = strlen( bsdPath );
95             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
96                 kernResult = KERN_SUCCESS;
97             }
98             CFRelease( bsdPathAsCFString );
99         }
100         IOObjectRelease( nextMedia );
101     }
102     
103     return kernResult;
104 }
105
106 #endif
107
108 void bdrv_register(BlockDriver *bdrv)
109 {
110     bdrv->next = first_drv;
111     first_drv = bdrv;
112 }
113
114 /* create a new block device (by default it is empty) */
115 BlockDriverState *bdrv_new(const char *device_name)
116 {
117     BlockDriverState **pbs, *bs;
118
119     bs = qemu_mallocz(sizeof(BlockDriverState));
120     if(!bs)
121         return NULL;
122     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
123     if (device_name[0] != '\0') {
124         /* insert at the end */
125         pbs = &bdrv_first;
126         while (*pbs != NULL)
127             pbs = &(*pbs)->next;
128         *pbs = bs;
129     }
130     return bs;
131 }
132
133 BlockDriver *bdrv_find_format(const char *format_name)
134 {
135     BlockDriver *drv1;
136     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
137         if (!strcmp(drv1->format_name, format_name))
138             return drv1;
139     }
140     return NULL;
141 }
142
143 int bdrv_create(BlockDriver *drv, 
144                 const char *filename, int64_t size_in_sectors,
145                 const char *backing_file, int flags)
146 {
147     if (!drv->bdrv_create)
148         return -ENOTSUP;
149     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
150 }
151
152 #ifdef _WIN32
153 void get_tmp_filename(char *filename, int size)
154 {
155     char* p = strrchr(filename, '/');
156
157     if (p == NULL)
158         return;
159
160     /* XXX: find a better function */
161     tmpnam(p);
162     *p = '/';
163 }
164 #else
165 void get_tmp_filename(char *filename, int size)
166 {
167     int fd;
168     /* XXX: race condition possible */
169     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
170     fd = mkstemp(filename);
171     close(fd);
172 }
173 #endif
174
175 /* XXX: force raw format if block or character device ? It would
176    simplify the BSD case */
177 static BlockDriver *find_image_format(const char *filename)
178 {
179     int fd, ret, score, score_max;
180     BlockDriver *drv1, *drv;
181     uint8_t *buf;
182     size_t bufsize = 1024;
183
184     fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
185     if (fd < 0) {
186         buf = NULL;
187         ret = 0;
188     } else {
189 #ifdef DIOCGSECTORSIZE
190         {
191             unsigned int sectorsize = 512;
192             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
193                 sectorsize > bufsize)
194                 bufsize = sectorsize;
195         }
196 #endif
197 #ifdef CONFIG_COCOA
198         u_int32_t   blockSize = 512;
199         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
200             bufsize = blockSize;
201         }
202 #endif
203         buf = qemu_malloc(bufsize);
204         if (!buf)
205             return NULL;
206         ret = read(fd, buf, bufsize);
207         if (ret < 0) {
208             close(fd);
209             qemu_free(buf);
210             return NULL;
211         }
212         close(fd);
213     }
214     
215     drv = NULL;
216     score_max = 0;
217     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
218         score = drv1->bdrv_probe(buf, ret, filename);
219         if (score > score_max) {
220             score_max = score;
221             drv = drv1;
222         }
223     }
224     qemu_free(buf);
225     return drv;
226 }
227
228 int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
229 {
230 #ifdef CONFIG_COCOA
231     if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
232         kern_return_t kernResult;
233         io_iterator_t mediaIterator;
234         char bsdPath[ MAXPATHLEN ];
235         int fd;
236  
237         kernResult = FindEjectableCDMedia( &mediaIterator );
238         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
239     
240         if ( bsdPath[ 0 ] != '\0' ) {
241             strcat(bsdPath,"s0");
242             /* some CDs don't have a partition 0 */
243             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
244             if (fd < 0) {
245                 bsdPath[strlen(bsdPath)-1] = '1';
246             } else {
247                 close(fd);
248             }
249             filename = bsdPath;
250         }
251         
252         if ( mediaIterator )
253             IOObjectRelease( mediaIterator );
254     }
255 #endif
256     return bdrv_open2(bs, filename, snapshot, NULL);
257 }
258
259 int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
260                BlockDriver *drv)
261 {
262     int ret;
263     char tmp_filename[1024];
264     
265     bs->read_only = 0;
266     bs->is_temporary = 0;
267     bs->encrypted = 0;
268
269     if (snapshot) {
270         BlockDriverState *bs1;
271         int64_t total_size;
272         
273         /* if snapshot, we create a temporary backing file and open it
274            instead of opening 'filename' directly */
275
276         /* if there is a backing file, use it */
277         bs1 = bdrv_new("");
278         if (!bs1) {
279             return -1;
280         }
281         if (bdrv_open(bs1, filename, 0) < 0) {
282             bdrv_delete(bs1);
283             return -1;
284         }
285         total_size = bs1->total_sectors;
286         bdrv_delete(bs1);
287         
288         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
289         /* XXX: use cow for linux as it is more efficient ? */
290         if (bdrv_create(&bdrv_qcow, tmp_filename, 
291                         total_size, filename, 0) < 0) {
292             return -1;
293         }
294         filename = tmp_filename;
295         bs->is_temporary = 1;
296     }
297
298     pstrcpy(bs->filename, sizeof(bs->filename), filename);
299     if (!drv) {
300         drv = find_image_format(filename);
301         if (!drv)
302             return -1;
303     }
304     bs->drv = drv;
305     bs->opaque = qemu_mallocz(drv->instance_size);
306     if (bs->opaque == NULL && drv->instance_size > 0)
307         return -1;
308     
309     ret = drv->bdrv_open(bs, filename);
310     if (ret < 0) {
311         qemu_free(bs->opaque);
312         return -1;
313     }
314 #ifndef _WIN32
315     if (bs->is_temporary) {
316         unlink(filename);
317     }
318 #endif
319     if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
320         /* if there is a backing file, use it */
321         bs->backing_hd = bdrv_new("");
322         if (!bs->backing_hd) {
323         fail:
324             bdrv_close(bs);
325             return -1;
326         }
327         if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
328             goto fail;
329     }
330
331     bs->inserted = 1;
332
333     /* call the change callback */
334     if (bs->change_cb)
335         bs->change_cb(bs->change_opaque);
336
337     return 0;
338 }
339
340 void bdrv_close(BlockDriverState *bs)
341 {
342     if (bs->inserted) {
343         if (bs->backing_hd)
344             bdrv_delete(bs->backing_hd);
345         bs->drv->bdrv_close(bs);
346         qemu_free(bs->opaque);
347 #ifdef _WIN32
348         if (bs->is_temporary) {
349             unlink(bs->filename);
350         }
351 #endif
352         bs->opaque = NULL;
353         bs->drv = NULL;
354         bs->inserted = 0;
355
356         /* call the change callback */
357         if (bs->change_cb)
358             bs->change_cb(bs->change_opaque);
359     }
360 }
361
362 void bdrv_delete(BlockDriverState *bs)
363 {
364     /* XXX: remove the driver list */
365     bdrv_close(bs);
366     qemu_free(bs);
367 }
368
369 /* commit COW file into the raw image */
370 int bdrv_commit(BlockDriverState *bs)
371 {
372     int64_t i;
373     int n, j;
374     unsigned char sector[512];
375
376     if (!bs->inserted)
377         return -ENOENT;
378
379     if (bs->read_only) {
380         return -EACCES;
381     }
382
383     if (!bs->backing_hd) {
384         return -ENOTSUP;
385     }
386
387     for (i = 0; i < bs->total_sectors;) {
388         if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
389             for(j = 0; j < n; j++) {
390                 if (bdrv_read(bs, i, sector, 1) != 0) {
391                     return -EIO;
392                 }
393
394                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
395                     return -EIO;
396                 }
397                 i++;
398             }
399         } else {
400             i += n;
401         }
402     }
403
404     if (bs->drv->bdrv_make_empty)
405         return bs->drv->bdrv_make_empty(bs);
406
407     return 0;
408 }
409
410 /* return -1 if error */
411 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
412               uint8_t *buf, int nb_sectors)
413 {
414     int ret, n;
415     BlockDriver *drv = bs->drv;
416
417     if (!bs->inserted)
418         return -1;
419
420     while (nb_sectors > 0) {
421         if (sector_num == 0 && bs->boot_sector_enabled) {
422             memcpy(buf, bs->boot_sector_data, 512);
423             n = 1;
424         } else if (bs->backing_hd) {
425             if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
426                 ret = drv->bdrv_read(bs, sector_num, buf, n);
427                 if (ret < 0)
428                     return -1;
429             } else {
430                 /* read from the base image */
431                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
432                 if (ret < 0)
433                     return -1;
434             }
435         } else {
436             ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
437             if (ret < 0)
438                 return -1;
439             /* no need to loop */
440             break;
441         }
442         nb_sectors -= n;
443         sector_num += n;
444         buf += n * 512;
445     }
446     return 0;
447 }
448
449 /* return -1 if error */
450 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
451                const uint8_t *buf, int nb_sectors)
452 {
453     if (!bs->inserted)
454         return -1;
455     if (bs->read_only)
456         return -1;
457     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
458         memcpy(bs->boot_sector_data, buf, 512);   
459     }
460     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
461 }
462
463 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
464 {
465     *nb_sectors_ptr = bs->total_sectors;
466 }
467
468 /* force a given boot sector. */
469 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
470 {
471     bs->boot_sector_enabled = 1;
472     if (size > 512)
473         size = 512;
474     memcpy(bs->boot_sector_data, data, size);
475     memset(bs->boot_sector_data + size, 0, 512 - size);
476 }
477
478 void bdrv_set_geometry_hint(BlockDriverState *bs, 
479                             int cyls, int heads, int secs)
480 {
481     bs->cyls = cyls;
482     bs->heads = heads;
483     bs->secs = secs;
484 }
485
486 void bdrv_set_type_hint(BlockDriverState *bs, int type)
487 {
488     bs->type = type;
489     bs->removable = ((type == BDRV_TYPE_CDROM ||
490                       type == BDRV_TYPE_FLOPPY));
491 }
492
493 void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
494 {
495     bs->translation = translation;
496 }
497
498 void bdrv_get_geometry_hint(BlockDriverState *bs, 
499                             int *pcyls, int *pheads, int *psecs)
500 {
501     *pcyls = bs->cyls;
502     *pheads = bs->heads;
503     *psecs = bs->secs;
504 }
505
506 int bdrv_get_type_hint(BlockDriverState *bs)
507 {
508     return bs->type;
509 }
510
511 int bdrv_get_translation_hint(BlockDriverState *bs)
512 {
513     return bs->translation;
514 }
515
516 int bdrv_is_removable(BlockDriverState *bs)
517 {
518     return bs->removable;
519 }
520
521 int bdrv_is_read_only(BlockDriverState *bs)
522 {
523     return bs->read_only;
524 }
525
526 int bdrv_is_inserted(BlockDriverState *bs)
527 {
528     return bs->inserted;
529 }
530
531 int bdrv_is_locked(BlockDriverState *bs)
532 {
533     return bs->locked;
534 }
535
536 void bdrv_set_locked(BlockDriverState *bs, int locked)
537 {
538     bs->locked = locked;
539 }
540
541 void bdrv_set_change_cb(BlockDriverState *bs, 
542                         void (*change_cb)(void *opaque), void *opaque)
543 {
544     bs->change_cb = change_cb;
545     bs->change_opaque = opaque;
546 }
547
548 int bdrv_is_encrypted(BlockDriverState *bs)
549 {
550     if (bs->backing_hd && bs->backing_hd->encrypted)
551         return 1;
552     return bs->encrypted;
553 }
554
555 int bdrv_set_key(BlockDriverState *bs, const char *key)
556 {
557     int ret;
558     if (bs->backing_hd && bs->backing_hd->encrypted) {
559         ret = bdrv_set_key(bs->backing_hd, key);
560         if (ret < 0)
561             return ret;
562         if (!bs->encrypted)
563             return 0;
564     }
565     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
566         return -1;
567     return bs->drv->bdrv_set_key(bs, key);
568 }
569
570 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
571 {
572     if (!bs->inserted || !bs->drv) {
573         buf[0] = '\0';
574     } else {
575         pstrcpy(buf, buf_size, bs->drv->format_name);
576     }
577 }
578
579 void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
580                          void *opaque)
581 {
582     BlockDriver *drv;
583
584     for (drv = first_drv; drv != NULL; drv = drv->next) {
585         it(opaque, drv->format_name);
586     }
587 }
588
589 BlockDriverState *bdrv_find(const char *name)
590 {
591     BlockDriverState *bs;
592
593     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
594         if (!strcmp(name, bs->device_name))
595             return bs;
596     }
597     return NULL;
598 }
599
600 void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
601 {
602     BlockDriverState *bs;
603
604     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
605         it(opaque, bs->device_name);
606     }
607 }
608
609 const char *bdrv_get_device_name(BlockDriverState *bs)
610 {
611     return bs->device_name;
612 }
613
614 void bdrv_info(void)
615 {
616     BlockDriverState *bs;
617
618     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
619         term_printf("%s:", bs->device_name);
620         term_printf(" type=");
621         switch(bs->type) {
622         case BDRV_TYPE_HD:
623             term_printf("hd");
624             break;
625         case BDRV_TYPE_CDROM:
626             term_printf("cdrom");
627             break;
628         case BDRV_TYPE_FLOPPY:
629             term_printf("floppy");
630             break;
631         }
632         term_printf(" removable=%d", bs->removable);
633         if (bs->removable) {
634             term_printf(" locked=%d", bs->locked);
635         }
636         if (bs->inserted) {
637             term_printf(" file=%s", bs->filename);
638             if (bs->backing_file[0] != '\0')
639                 term_printf(" backing_file=%s", bs->backing_file);
640             term_printf(" ro=%d", bs->read_only);
641             term_printf(" drv=%s", bs->drv->format_name);
642             if (bs->encrypted)
643                 term_printf(" encrypted");
644         } else {
645             term_printf(" [not inserted]");
646         }
647         term_printf("\n");
648     }
649 }
650
651
652 /**************************************************************/
653 /* RAW block driver */
654
655 typedef struct BDRVRawState {
656     int fd;
657 } BDRVRawState;
658
659 static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
660 {
661     return 1; /* maybe */
662 }
663
664 static int raw_open(BlockDriverState *bs, const char *filename)
665 {
666     BDRVRawState *s = bs->opaque;
667     int fd;
668     int64_t size;
669 #ifdef _BSD
670     struct stat sb;
671 #endif
672
673     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
674     if (fd < 0) {
675         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
676         if (fd < 0)
677             return -1;
678         bs->read_only = 1;
679     }
680 #ifdef _BSD
681     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
682 #ifdef DIOCGMEDIASIZE
683         if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
684 #endif
685 #ifdef CONFIG_COCOA
686         size = LONG_LONG_MAX;
687 #else
688         size = lseek(fd, 0LL, SEEK_END);
689 #endif
690     } else
691 #endif
692     {
693         size = lseek(fd, 0, SEEK_END);
694     }
695 #ifdef _WIN32
696     /* On Windows hosts it can happen that we're unable to get file size
697        for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
698     if (size == -1)
699         size = LONG_LONG_MAX;
700 #endif
701     bs->total_sectors = size / 512;
702     s->fd = fd;
703     return 0;
704 }
705
706 static int raw_read(BlockDriverState *bs, int64_t sector_num, 
707                     uint8_t *buf, int nb_sectors)
708 {
709     BDRVRawState *s = bs->opaque;
710     int ret;
711     
712     lseek(s->fd, sector_num * 512, SEEK_SET);
713     ret = read(s->fd, buf, nb_sectors * 512);
714     if (ret != nb_sectors * 512) 
715         return -1;
716     return 0;
717 }
718
719 static int raw_write(BlockDriverState *bs, int64_t sector_num, 
720                      const uint8_t *buf, int nb_sectors)
721 {
722     BDRVRawState *s = bs->opaque;
723     int ret;
724     
725     lseek(s->fd, sector_num * 512, SEEK_SET);
726     ret = write(s->fd, buf, nb_sectors * 512);
727     if (ret != nb_sectors * 512) 
728         return -1;
729     return 0;
730 }
731
732 static void raw_close(BlockDriverState *bs)
733 {
734     BDRVRawState *s = bs->opaque;
735     close(s->fd);
736 }
737
738 static int raw_create(const char *filename, int64_t total_size,
739                       const char *backing_file, int flags)
740 {
741     int fd;
742
743     if (flags || backing_file)
744         return -ENOTSUP;
745
746     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
747               0644);
748     if (fd < 0)
749         return -EIO;
750     ftruncate(fd, total_size * 512);
751     close(fd);
752     return 0;
753 }
754
755 BlockDriver bdrv_raw = {
756     "raw",
757     sizeof(BDRVRawState),
758     raw_probe,
759     raw_open,
760     raw_read,
761     raw_write,
762     raw_close,
763     raw_create,
764 };
765
766 void bdrv_init(void)
767 {
768     bdrv_register(&bdrv_raw);
769 #ifndef _WIN32
770     bdrv_register(&bdrv_cow);
771 #endif
772     bdrv_register(&bdrv_qcow);
773     bdrv_register(&bdrv_vmdk);
774     bdrv_register(&bdrv_cloop);
775     bdrv_register(&bdrv_dmg);
776     bdrv_register(&bdrv_bochs);
777     bdrv_register(&bdrv_vpc);
778     bdrv_register(&bdrv_vvfat);
779 }