Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
[sdk/emulator/qemu.git] / block / raw-win32.c
1 /*
2  * Block driver for RAW files (win32)
3  *
4  * Copyright (c) 2006 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 "qemu/osdep.h"
25 #include "qemu-common.h"
26 #include "qemu/timer.h"
27 #include "block/block_int.h"
28 #include "qemu/module.h"
29 #include "raw-aio.h"
30 #include "trace.h"
31 #include "block/thread-pool.h"
32 #include "qemu/iov.h"
33 #include "qapi/qmp/qstring.h"
34 #include <windows.h>
35 #include <winioctl.h>
36
37 #define FTYPE_FILE 0
38 #define FTYPE_CD     1
39 #define FTYPE_HARDDISK 2
40
41 typedef struct RawWin32AIOData {
42     BlockDriverState *bs;
43     HANDLE hfile;
44     struct iovec *aio_iov;
45     int aio_niov;
46     size_t aio_nbytes;
47     off64_t aio_offset;
48     int aio_type;
49 } RawWin32AIOData;
50
51 typedef struct BDRVRawState {
52     HANDLE hfile;
53     int type;
54     char drive_path[16]; /* format: "d:\" */
55     QEMUWin32AIOState *aio;
56 } BDRVRawState;
57
58 /*
59  * Read/writes the data to/from a given linear buffer.
60  *
61  * Returns the number of bytes handles or -errno in case of an error. Short
62  * reads are only returned if the end of the file is reached.
63  */
64 static size_t handle_aiocb_rw(RawWin32AIOData *aiocb)
65 {
66     size_t offset = 0;
67     int i;
68
69     for (i = 0; i < aiocb->aio_niov; i++) {
70         OVERLAPPED ov;
71         DWORD ret, ret_count, len;
72
73         memset(&ov, 0, sizeof(ov));
74         ov.Offset = (aiocb->aio_offset + offset);
75         ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32;
76         len = aiocb->aio_iov[i].iov_len;
77         if (aiocb->aio_type & QEMU_AIO_WRITE) {
78             ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
79                             len, &ret_count, &ov);
80         } else {
81             ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
82                            len, &ret_count, &ov);
83         }
84         if (!ret) {
85             ret_count = 0;
86         }
87         if (ret_count != len) {
88             offset += ret_count;
89             break;
90         }
91         offset += len;
92     }
93
94     return offset;
95 }
96
97 static int aio_worker(void *arg)
98 {
99     RawWin32AIOData *aiocb = arg;
100     ssize_t ret = 0;
101     size_t count;
102
103     switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
104     case QEMU_AIO_READ:
105         count = handle_aiocb_rw(aiocb);
106         if (count < aiocb->aio_nbytes) {
107             /* A short read means that we have reached EOF. Pad the buffer
108              * with zeros for bytes after EOF. */
109             iov_memset(aiocb->aio_iov, aiocb->aio_niov, count,
110                       0, aiocb->aio_nbytes - count);
111
112             count = aiocb->aio_nbytes;
113         }
114         if (count == aiocb->aio_nbytes) {
115             ret = 0;
116         } else {
117             ret = -EINVAL;
118         }
119         break;
120     case QEMU_AIO_WRITE:
121         count = handle_aiocb_rw(aiocb);
122         if (count == aiocb->aio_nbytes) {
123             ret = 0;
124         } else {
125             ret = -EINVAL;
126         }
127         break;
128     case QEMU_AIO_FLUSH:
129         if (!FlushFileBuffers(aiocb->hfile)) {
130             return -EIO;
131         }
132         break;
133     default:
134         fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
135         ret = -EINVAL;
136         break;
137     }
138
139     g_free(aiocb);
140     return ret;
141 }
142
143 static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
144         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
145         BlockCompletionFunc *cb, void *opaque, int type)
146 {
147     RawWin32AIOData *acb = g_new(RawWin32AIOData, 1);
148     ThreadPool *pool;
149
150     acb->bs = bs;
151     acb->hfile = hfile;
152     acb->aio_type = type;
153
154     if (qiov) {
155         acb->aio_iov = qiov->iov;
156         acb->aio_niov = qiov->niov;
157     }
158     acb->aio_nbytes = nb_sectors * 512;
159     acb->aio_offset = sector_num * 512;
160
161     trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
162     pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
163     return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
164 }
165
166 int qemu_ftruncate64(int fd, int64_t length)
167 {
168     LARGE_INTEGER li;
169     DWORD dw;
170     LONG high;
171     HANDLE h;
172     BOOL res;
173
174     if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
175         return -1;
176
177     h = (HANDLE)_get_osfhandle(fd);
178
179     /* get current position, ftruncate do not change position */
180     li.HighPart = 0;
181     li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
182     if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
183         return -1;
184     }
185
186     high = length >> 32;
187     dw = SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN);
188     if (dw == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
189         return -1;
190     }
191     res = SetEndOfFile(h);
192
193     /* back to old position */
194     SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
195     return res ? 0 : -1;
196 }
197
198 static int set_sparse(int fd)
199 {
200     DWORD returned;
201     return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
202                                  NULL, 0, NULL, 0, &returned, NULL);
203 }
204
205 static void raw_detach_aio_context(BlockDriverState *bs)
206 {
207     BDRVRawState *s = bs->opaque;
208
209     if (s->aio) {
210         win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
211     }
212 }
213
214 static void raw_attach_aio_context(BlockDriverState *bs,
215                                    AioContext *new_context)
216 {
217     BDRVRawState *s = bs->opaque;
218
219     if (s->aio) {
220         win32_aio_attach_aio_context(s->aio, new_context);
221     }
222 }
223
224 static void raw_probe_alignment(BlockDriverState *bs)
225 {
226     BDRVRawState *s = bs->opaque;
227     DWORD sectorsPerCluster, freeClusters, totalClusters, count;
228     DISK_GEOMETRY_EX dg;
229     BOOL status;
230
231     if (s->type == FTYPE_CD) {
232         bs->request_alignment = 2048;
233         return;
234     }
235     if (s->type == FTYPE_HARDDISK) {
236         status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
237                                  NULL, 0, &dg, sizeof(dg), &count, NULL);
238         if (status != 0) {
239             bs->request_alignment = dg.Geometry.BytesPerSector;
240             return;
241         }
242         /* try GetDiskFreeSpace too */
243     }
244
245     if (s->drive_path[0]) {
246         GetDiskFreeSpace(s->drive_path, &sectorsPerCluster,
247                          &dg.Geometry.BytesPerSector,
248                          &freeClusters, &totalClusters);
249         bs->request_alignment = dg.Geometry.BytesPerSector;
250     }
251 }
252
253 static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
254 {
255     assert(access_flags != NULL);
256     assert(overlapped != NULL);
257
258     if (flags & BDRV_O_RDWR) {
259         *access_flags = GENERIC_READ | GENERIC_WRITE;
260     } else {
261         *access_flags = GENERIC_READ;
262     }
263
264     *overlapped = FILE_ATTRIBUTE_NORMAL;
265     if (flags & BDRV_O_NATIVE_AIO) {
266         *overlapped |= FILE_FLAG_OVERLAPPED;
267     }
268     if (flags & BDRV_O_NOCACHE) {
269         *overlapped |= FILE_FLAG_NO_BUFFERING;
270     }
271 }
272
273 static void raw_parse_filename(const char *filename, QDict *options,
274                                Error **errp)
275 {
276     /* The filename does not have to be prefixed by the protocol name, since
277      * "file" is the default protocol; therefore, the return value of this
278      * function call can be ignored. */
279     strstart(filename, "file:", &filename);
280
281     qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
282 }
283
284 static QemuOptsList raw_runtime_opts = {
285     .name = "raw",
286     .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
287     .desc = {
288         {
289             .name = "filename",
290             .type = QEMU_OPT_STRING,
291             .help = "File name of the image",
292         },
293         { /* end of list */ }
294     },
295 };
296
297 static int raw_open(BlockDriverState *bs, QDict *options, int flags,
298                     Error **errp)
299 {
300     BDRVRawState *s = bs->opaque;
301     int access_flags;
302     DWORD overlapped;
303     QemuOpts *opts;
304     Error *local_err = NULL;
305     const char *filename;
306     int ret;
307
308     s->type = FTYPE_FILE;
309
310     opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
311     qemu_opts_absorb_qdict(opts, options, &local_err);
312     if (local_err) {
313         error_propagate(errp, local_err);
314         ret = -EINVAL;
315         goto fail;
316     }
317
318     filename = qemu_opt_get(opts, "filename");
319
320     raw_parse_flags(flags, &access_flags, &overlapped);
321
322     if (filename[0] && filename[1] == ':') {
323         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
324     } else if (filename[0] == '\\' && filename[1] == '\\') {
325         s->drive_path[0] = 0;
326     } else {
327         /* Relative path.  */
328         char buf[MAX_PATH];
329         GetCurrentDirectory(MAX_PATH, buf);
330         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", buf[0]);
331     }
332
333     s->hfile = CreateFile(filename, access_flags,
334                           FILE_SHARE_READ, NULL,
335                           OPEN_EXISTING, overlapped, NULL);
336     if (s->hfile == INVALID_HANDLE_VALUE) {
337         int err = GetLastError();
338
339         if (err == ERROR_ACCESS_DENIED) {
340             ret = -EACCES;
341         } else {
342             ret = -EINVAL;
343         }
344         goto fail;
345     }
346
347     if (flags & BDRV_O_NATIVE_AIO) {
348         s->aio = win32_aio_init();
349         if (s->aio == NULL) {
350             CloseHandle(s->hfile);
351             error_setg(errp, "Could not initialize AIO");
352             ret = -EINVAL;
353             goto fail;
354         }
355
356         ret = win32_aio_attach(s->aio, s->hfile);
357         if (ret < 0) {
358             win32_aio_cleanup(s->aio);
359             CloseHandle(s->hfile);
360             error_setg_errno(errp, -ret, "Could not enable AIO");
361             goto fail;
362         }
363
364         win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
365     }
366
367     raw_probe_alignment(bs);
368     ret = 0;
369 fail:
370     qemu_opts_del(opts);
371     return ret;
372 }
373
374 static BlockAIOCB *raw_aio_readv(BlockDriverState *bs,
375                          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
376                          BlockCompletionFunc *cb, void *opaque)
377 {
378     BDRVRawState *s = bs->opaque;
379     if (s->aio) {
380         return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
381                                 nb_sectors, cb, opaque, QEMU_AIO_READ); 
382     } else {
383         return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
384                            cb, opaque, QEMU_AIO_READ);
385     }
386 }
387
388 static BlockAIOCB *raw_aio_writev(BlockDriverState *bs,
389                           int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
390                           BlockCompletionFunc *cb, void *opaque)
391 {
392     BDRVRawState *s = bs->opaque;
393     if (s->aio) {
394         return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
395                                 nb_sectors, cb, opaque, QEMU_AIO_WRITE); 
396     } else {
397         return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
398                            cb, opaque, QEMU_AIO_WRITE);
399     }
400 }
401
402 static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
403                          BlockCompletionFunc *cb, void *opaque)
404 {
405     BDRVRawState *s = bs->opaque;
406     return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
407 }
408
409 static void raw_close(BlockDriverState *bs)
410 {
411     BDRVRawState *s = bs->opaque;
412
413     if (s->aio) {
414         win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
415         win32_aio_cleanup(s->aio);
416         s->aio = NULL;
417     }
418
419     CloseHandle(s->hfile);
420     if (bs->open_flags & BDRV_O_TEMPORARY) {
421         unlink(bs->filename);
422     }
423 }
424
425 static int raw_truncate(BlockDriverState *bs, int64_t offset)
426 {
427     BDRVRawState *s = bs->opaque;
428     LONG low, high;
429     DWORD dwPtrLow;
430
431     low = offset;
432     high = offset >> 32;
433
434     /*
435      * An error has occurred if the return value is INVALID_SET_FILE_POINTER
436      * and GetLastError doesn't return NO_ERROR.
437      */
438     dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
439     if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
440         fprintf(stderr, "SetFilePointer error: %lu\n", GetLastError());
441         return -EIO;
442     }
443     if (SetEndOfFile(s->hfile) == 0) {
444         fprintf(stderr, "SetEndOfFile error: %lu\n", GetLastError());
445         return -EIO;
446     }
447     return 0;
448 }
449
450 static int64_t raw_getlength(BlockDriverState *bs)
451 {
452     BDRVRawState *s = bs->opaque;
453     LARGE_INTEGER l;
454     ULARGE_INTEGER available, total, total_free;
455     DISK_GEOMETRY_EX dg;
456     DWORD count;
457     BOOL status;
458
459     switch(s->type) {
460     case FTYPE_FILE:
461         l.LowPart = GetFileSize(s->hfile, (PDWORD)&l.HighPart);
462         if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
463             return -EIO;
464         break;
465     case FTYPE_CD:
466         if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
467             return -EIO;
468         l.QuadPart = total.QuadPart;
469         break;
470     case FTYPE_HARDDISK:
471         status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
472                                  NULL, 0, &dg, sizeof(dg), &count, NULL);
473         if (status != 0) {
474             l = dg.DiskSize;
475         }
476         break;
477     default:
478         return -EIO;
479     }
480     return l.QuadPart;
481 }
482
483 static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
484 {
485     typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
486                                               DWORD * high);
487     get_compressed_t get_compressed;
488     struct _stati64 st;
489     const char *filename = bs->filename;
490     /* WinNT support GetCompressedFileSize to determine allocate size */
491     get_compressed =
492         (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
493                                             "GetCompressedFileSizeA");
494     if (get_compressed) {
495         DWORD high, low;
496         low = get_compressed(filename, &high);
497         if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
498             return (((int64_t) high) << 32) + low;
499         }
500     }
501
502     if (_stati64(filename, &st) < 0) {
503         return -1;
504     }
505     return st.st_size;
506 }
507
508 static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
509 {
510     int fd;
511     int64_t total_size = 0;
512
513     strstart(filename, "file:", &filename);
514
515     /* Read out options */
516     total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
517                           BDRV_SECTOR_SIZE);
518
519     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
520                    0644);
521     if (fd < 0) {
522         error_setg_errno(errp, errno, "Could not create file");
523         return -EIO;
524     }
525     set_sparse(fd);
526     ftruncate(fd, total_size);
527     qemu_close(fd);
528     return 0;
529 }
530
531
532 static QemuOptsList raw_create_opts = {
533     .name = "raw-create-opts",
534     .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
535     .desc = {
536         {
537             .name = BLOCK_OPT_SIZE,
538             .type = QEMU_OPT_SIZE,
539             .help = "Virtual disk size"
540         },
541         { /* end of list */ }
542     }
543 };
544
545 BlockDriver bdrv_file = {
546     .format_name        = "file",
547     .protocol_name      = "file",
548     .instance_size      = sizeof(BDRVRawState),
549     .bdrv_needs_filename = true,
550     .bdrv_parse_filename = raw_parse_filename,
551     .bdrv_file_open     = raw_open,
552     .bdrv_close         = raw_close,
553     .bdrv_create        = raw_create,
554     .bdrv_has_zero_init = bdrv_has_zero_init_1,
555
556     .bdrv_aio_readv     = raw_aio_readv,
557     .bdrv_aio_writev    = raw_aio_writev,
558     .bdrv_aio_flush     = raw_aio_flush,
559
560     .bdrv_truncate      = raw_truncate,
561     .bdrv_getlength     = raw_getlength,
562     .bdrv_get_allocated_file_size
563                         = raw_get_allocated_file_size,
564
565     .create_opts        = &raw_create_opts,
566 };
567
568 /***********************************************/
569 /* host device */
570
571 static int find_cdrom(char *cdrom_name, int cdrom_name_size)
572 {
573     char drives[256], *pdrv = drives;
574     UINT type;
575
576     memset(drives, 0, sizeof(drives));
577     GetLogicalDriveStrings(sizeof(drives), drives);
578     while(pdrv[0] != '\0') {
579         type = GetDriveType(pdrv);
580         switch(type) {
581         case DRIVE_CDROM:
582             snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
583             return 0;
584             break;
585         }
586         pdrv += lstrlen(pdrv) + 1;
587     }
588     return -1;
589 }
590
591 static int find_device_type(BlockDriverState *bs, const char *filename)
592 {
593     BDRVRawState *s = bs->opaque;
594     UINT type;
595     const char *p;
596
597     if (strstart(filename, "\\\\.\\", &p) ||
598         strstart(filename, "//./", &p)) {
599         if (stristart(p, "PhysicalDrive", NULL))
600             return FTYPE_HARDDISK;
601         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
602         type = GetDriveType(s->drive_path);
603         switch (type) {
604         case DRIVE_REMOVABLE:
605         case DRIVE_FIXED:
606             return FTYPE_HARDDISK;
607         case DRIVE_CDROM:
608             return FTYPE_CD;
609         default:
610             return FTYPE_FILE;
611         }
612     } else {
613         return FTYPE_FILE;
614     }
615 }
616
617 static int hdev_probe_device(const char *filename)
618 {
619     if (strstart(filename, "/dev/cdrom", NULL))
620         return 100;
621     if (is_windows_drive(filename))
622         return 100;
623     return 0;
624 }
625
626 static void hdev_parse_filename(const char *filename, QDict *options,
627                                 Error **errp)
628 {
629     /* The prefix is optional, just as for "file". */
630     strstart(filename, "host_device:", &filename);
631
632     qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
633 }
634
635 static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
636                      Error **errp)
637 {
638     BDRVRawState *s = bs->opaque;
639     int access_flags, create_flags;
640     int ret = 0;
641     DWORD overlapped;
642     char device_name[64];
643
644     Error *local_err = NULL;
645     const char *filename;
646
647     QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0,
648                                       &error_abort);
649     qemu_opts_absorb_qdict(opts, options, &local_err);
650     if (local_err) {
651         error_propagate(errp, local_err);
652         ret = -EINVAL;
653         goto done;
654     }
655
656     filename = qemu_opt_get(opts, "filename");
657
658     if (strstart(filename, "/dev/cdrom", NULL)) {
659         if (find_cdrom(device_name, sizeof(device_name)) < 0) {
660             error_setg(errp, "Could not open CD-ROM drive");
661             ret = -ENOENT;
662             goto done;
663         }
664         filename = device_name;
665     } else {
666         /* transform drive letters into device name */
667         if (((filename[0] >= 'a' && filename[0] <= 'z') ||
668              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
669             filename[1] == ':' && filename[2] == '\0') {
670             snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
671             filename = device_name;
672         }
673     }
674     s->type = find_device_type(bs, filename);
675
676     raw_parse_flags(flags, &access_flags, &overlapped);
677
678     create_flags = OPEN_EXISTING;
679
680     s->hfile = CreateFile(filename, access_flags,
681                           FILE_SHARE_READ, NULL,
682                           create_flags, overlapped, NULL);
683     if (s->hfile == INVALID_HANDLE_VALUE) {
684         int err = GetLastError();
685
686         if (err == ERROR_ACCESS_DENIED) {
687             ret = -EACCES;
688         } else {
689             ret = -EINVAL;
690         }
691         error_setg_errno(errp, -ret, "Could not open device");
692         goto done;
693     }
694
695 done:
696     qemu_opts_del(opts);
697     return ret;
698 }
699
700 static BlockDriver bdrv_host_device = {
701     .format_name        = "host_device",
702     .protocol_name      = "host_device",
703     .instance_size      = sizeof(BDRVRawState),
704     .bdrv_needs_filename = true,
705     .bdrv_parse_filename = hdev_parse_filename,
706     .bdrv_probe_device  = hdev_probe_device,
707     .bdrv_file_open     = hdev_open,
708     .bdrv_close         = raw_close,
709
710     .bdrv_aio_readv     = raw_aio_readv,
711     .bdrv_aio_writev    = raw_aio_writev,
712     .bdrv_aio_flush     = raw_aio_flush,
713
714     .bdrv_detach_aio_context = raw_detach_aio_context,
715     .bdrv_attach_aio_context = raw_attach_aio_context,
716
717     .bdrv_getlength      = raw_getlength,
718     .has_variable_length = true,
719
720     .bdrv_get_allocated_file_size
721                         = raw_get_allocated_file_size,
722 };
723
724 static void bdrv_file_init(void)
725 {
726     bdrv_register(&bdrv_file);
727     bdrv_register(&bdrv_host_device);
728 }
729
730 block_init(bdrv_file_init);