qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

file-win32.c (27060B)


      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 
     25 #include "qemu/osdep.h"
     26 #include "qapi/error.h"
     27 #include "qemu/cutils.h"
     28 #include "block/block_int.h"
     29 #include "qemu/module.h"
     30 #include "qemu/option.h"
     31 #include "block/raw-aio.h"
     32 #include "trace.h"
     33 #include "block/thread-pool.h"
     34 #include "qemu/iov.h"
     35 #include "qapi/qmp/qdict.h"
     36 #include "qapi/qmp/qstring.h"
     37 #include <windows.h>
     38 #include <winioctl.h>
     39 
     40 #define FTYPE_FILE 0
     41 #define FTYPE_CD     1
     42 #define FTYPE_HARDDISK 2
     43 
     44 typedef struct RawWin32AIOData {
     45     BlockDriverState *bs;
     46     HANDLE hfile;
     47     struct iovec *aio_iov;
     48     int aio_niov;
     49     size_t aio_nbytes;
     50     off64_t aio_offset;
     51     int aio_type;
     52 } RawWin32AIOData;
     53 
     54 typedef struct BDRVRawState {
     55     HANDLE hfile;
     56     int type;
     57     char drive_path[16]; /* format: "d:\" */
     58     QEMUWin32AIOState *aio;
     59 } BDRVRawState;
     60 
     61 typedef struct BDRVRawReopenState {
     62     HANDLE hfile;
     63 } BDRVRawReopenState;
     64 
     65 /*
     66  * Read/writes the data to/from a given linear buffer.
     67  *
     68  * Returns the number of bytes handles or -errno in case of an error. Short
     69  * reads are only returned if the end of the file is reached.
     70  */
     71 static size_t handle_aiocb_rw(RawWin32AIOData *aiocb)
     72 {
     73     size_t offset = 0;
     74     int i;
     75 
     76     for (i = 0; i < aiocb->aio_niov; i++) {
     77         OVERLAPPED ov;
     78         DWORD ret, ret_count, len;
     79 
     80         memset(&ov, 0, sizeof(ov));
     81         ov.Offset = (aiocb->aio_offset + offset);
     82         ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32;
     83         len = aiocb->aio_iov[i].iov_len;
     84         if (aiocb->aio_type & QEMU_AIO_WRITE) {
     85             ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
     86                             len, &ret_count, &ov);
     87         } else {
     88             ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
     89                            len, &ret_count, &ov);
     90         }
     91         if (!ret) {
     92             ret_count = 0;
     93         }
     94         if (ret_count != len) {
     95             offset += ret_count;
     96             break;
     97         }
     98         offset += len;
     99     }
    100 
    101     return offset;
    102 }
    103 
    104 static int aio_worker(void *arg)
    105 {
    106     RawWin32AIOData *aiocb = arg;
    107     ssize_t ret = 0;
    108     size_t count;
    109 
    110     switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
    111     case QEMU_AIO_READ:
    112         count = handle_aiocb_rw(aiocb);
    113         if (count < aiocb->aio_nbytes) {
    114             /* A short read means that we have reached EOF. Pad the buffer
    115              * with zeros for bytes after EOF. */
    116             iov_memset(aiocb->aio_iov, aiocb->aio_niov, count,
    117                       0, aiocb->aio_nbytes - count);
    118 
    119             count = aiocb->aio_nbytes;
    120         }
    121         if (count == aiocb->aio_nbytes) {
    122             ret = 0;
    123         } else {
    124             ret = -EINVAL;
    125         }
    126         break;
    127     case QEMU_AIO_WRITE:
    128         count = handle_aiocb_rw(aiocb);
    129         if (count == aiocb->aio_nbytes) {
    130             ret = 0;
    131         } else {
    132             ret = -EINVAL;
    133         }
    134         break;
    135     case QEMU_AIO_FLUSH:
    136         if (!FlushFileBuffers(aiocb->hfile)) {
    137             return -EIO;
    138         }
    139         break;
    140     default:
    141         fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
    142         ret = -EINVAL;
    143         break;
    144     }
    145 
    146     g_free(aiocb);
    147     return ret;
    148 }
    149 
    150 static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
    151         int64_t offset, QEMUIOVector *qiov, int count,
    152         BlockCompletionFunc *cb, void *opaque, int type)
    153 {
    154     RawWin32AIOData *acb = g_new(RawWin32AIOData, 1);
    155     ThreadPool *pool;
    156 
    157     acb->bs = bs;
    158     acb->hfile = hfile;
    159     acb->aio_type = type;
    160 
    161     if (qiov) {
    162         acb->aio_iov = qiov->iov;
    163         acb->aio_niov = qiov->niov;
    164         assert(qiov->size == count);
    165     }
    166     acb->aio_nbytes = count;
    167     acb->aio_offset = offset;
    168 
    169     trace_file_paio_submit(acb, opaque, offset, count, type);
    170     pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
    171     return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
    172 }
    173 
    174 int qemu_ftruncate64(int fd, int64_t length)
    175 {
    176     LARGE_INTEGER li;
    177     DWORD dw;
    178     LONG high;
    179     HANDLE h;
    180     BOOL res;
    181 
    182     if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
    183         return -1;
    184 
    185     h = (HANDLE)_get_osfhandle(fd);
    186 
    187     /* get current position, ftruncate do not change position */
    188     li.HighPart = 0;
    189     li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
    190     if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
    191         return -1;
    192     }
    193 
    194     high = length >> 32;
    195     dw = SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN);
    196     if (dw == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
    197         return -1;
    198     }
    199     res = SetEndOfFile(h);
    200 
    201     /* back to old position */
    202     SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
    203     return res ? 0 : -1;
    204 }
    205 
    206 static int set_sparse(int fd)
    207 {
    208     DWORD returned;
    209     return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
    210                                  NULL, 0, NULL, 0, &returned, NULL);
    211 }
    212 
    213 static void raw_detach_aio_context(BlockDriverState *bs)
    214 {
    215     BDRVRawState *s = bs->opaque;
    216 
    217     if (s->aio) {
    218         win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
    219     }
    220 }
    221 
    222 static void raw_attach_aio_context(BlockDriverState *bs,
    223                                    AioContext *new_context)
    224 {
    225     BDRVRawState *s = bs->opaque;
    226 
    227     if (s->aio) {
    228         win32_aio_attach_aio_context(s->aio, new_context);
    229     }
    230 }
    231 
    232 static void raw_probe_alignment(BlockDriverState *bs, Error **errp)
    233 {
    234     BDRVRawState *s = bs->opaque;
    235     DWORD sectorsPerCluster, freeClusters, totalClusters, count;
    236     DISK_GEOMETRY_EX dg;
    237     BOOL status;
    238 
    239     if (s->type == FTYPE_CD) {
    240         bs->bl.request_alignment = 2048;
    241         return;
    242     }
    243     if (s->type == FTYPE_HARDDISK) {
    244         status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
    245                                  NULL, 0, &dg, sizeof(dg), &count, NULL);
    246         if (status != 0) {
    247             bs->bl.request_alignment = dg.Geometry.BytesPerSector;
    248             return;
    249         }
    250         /* try GetDiskFreeSpace too */
    251     }
    252 
    253     if (s->drive_path[0]) {
    254         GetDiskFreeSpace(s->drive_path, &sectorsPerCluster,
    255                          &dg.Geometry.BytesPerSector,
    256                          &freeClusters, &totalClusters);
    257         bs->bl.request_alignment = dg.Geometry.BytesPerSector;
    258         return;
    259     }
    260 
    261     /* XXX Does Windows support AIO on less than 512-byte alignment? */
    262     bs->bl.request_alignment = 512;
    263 }
    264 
    265 static void raw_parse_flags(int flags, bool use_aio, int *access_flags,
    266                             DWORD *overlapped)
    267 {
    268     assert(access_flags != NULL);
    269     assert(overlapped != NULL);
    270 
    271     if (flags & BDRV_O_RDWR) {
    272         *access_flags = GENERIC_READ | GENERIC_WRITE;
    273     } else {
    274         *access_flags = GENERIC_READ;
    275     }
    276 
    277     *overlapped = FILE_ATTRIBUTE_NORMAL;
    278     if (use_aio) {
    279         *overlapped |= FILE_FLAG_OVERLAPPED;
    280     }
    281     if (flags & BDRV_O_NOCACHE) {
    282         *overlapped |= FILE_FLAG_NO_BUFFERING;
    283     }
    284 }
    285 
    286 static void raw_parse_filename(const char *filename, QDict *options,
    287                                Error **errp)
    288 {
    289     bdrv_parse_filename_strip_prefix(filename, "file:", options);
    290 }
    291 
    292 static QemuOptsList raw_runtime_opts = {
    293     .name = "raw",
    294     .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
    295     .desc = {
    296         {
    297             .name = "filename",
    298             .type = QEMU_OPT_STRING,
    299             .help = "File name of the image",
    300         },
    301         {
    302             .name = "aio",
    303             .type = QEMU_OPT_STRING,
    304             .help = "host AIO implementation (threads, native)",
    305         },
    306         {
    307             .name = "locking",
    308             .type = QEMU_OPT_STRING,
    309             .help = "file locking mode (on/off/auto, default: auto)",
    310         },
    311         { /* end of list */ }
    312     },
    313 };
    314 
    315 static bool get_aio_option(QemuOpts *opts, int flags, Error **errp)
    316 {
    317     BlockdevAioOptions aio, aio_default;
    318 
    319     aio_default = (flags & BDRV_O_NATIVE_AIO) ? BLOCKDEV_AIO_OPTIONS_NATIVE
    320                                               : BLOCKDEV_AIO_OPTIONS_THREADS;
    321     aio = qapi_enum_parse(&BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
    322                           aio_default, errp);
    323 
    324     switch (aio) {
    325     case BLOCKDEV_AIO_OPTIONS_NATIVE:
    326         return true;
    327     case BLOCKDEV_AIO_OPTIONS_THREADS:
    328         return false;
    329     default:
    330         error_setg(errp, "Invalid AIO option");
    331     }
    332     return false;
    333 }
    334 
    335 static int raw_open(BlockDriverState *bs, QDict *options, int flags,
    336                     Error **errp)
    337 {
    338     BDRVRawState *s = bs->opaque;
    339     int access_flags;
    340     DWORD overlapped;
    341     QemuOpts *opts;
    342     Error *local_err = NULL;
    343     const char *filename;
    344     bool use_aio;
    345     OnOffAuto locking;
    346     int ret;
    347 
    348     s->type = FTYPE_FILE;
    349 
    350     opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
    351     if (!qemu_opts_absorb_qdict(opts, options, errp)) {
    352         ret = -EINVAL;
    353         goto fail;
    354     }
    355 
    356     locking = qapi_enum_parse(&OnOffAuto_lookup,
    357                               qemu_opt_get(opts, "locking"),
    358                               ON_OFF_AUTO_AUTO, &local_err);
    359     if (local_err) {
    360         error_propagate(errp, local_err);
    361         ret = -EINVAL;
    362         goto fail;
    363     }
    364     switch (locking) {
    365     case ON_OFF_AUTO_ON:
    366         error_setg(errp, "locking=on is not supported on Windows");
    367         ret = -EINVAL;
    368         goto fail;
    369     case ON_OFF_AUTO_OFF:
    370     case ON_OFF_AUTO_AUTO:
    371         break;
    372     default:
    373         g_assert_not_reached();
    374     }
    375 
    376     filename = qemu_opt_get(opts, "filename");
    377 
    378     use_aio = get_aio_option(opts, flags, &local_err);
    379     if (local_err) {
    380         error_propagate(errp, local_err);
    381         ret = -EINVAL;
    382         goto fail;
    383     }
    384 
    385     raw_parse_flags(flags, use_aio, &access_flags, &overlapped);
    386 
    387     if (filename[0] && filename[1] == ':') {
    388         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
    389     } else if (filename[0] == '\\' && filename[1] == '\\') {
    390         s->drive_path[0] = 0;
    391     } else {
    392         /* Relative path.  */
    393         char buf[MAX_PATH];
    394         GetCurrentDirectory(MAX_PATH, buf);
    395         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", buf[0]);
    396     }
    397 
    398     s->hfile = CreateFile(filename, access_flags,
    399                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    400                           OPEN_EXISTING, overlapped, NULL);
    401     if (s->hfile == INVALID_HANDLE_VALUE) {
    402         int err = GetLastError();
    403 
    404         error_setg_win32(errp, err, "Could not open '%s'", filename);
    405         if (err == ERROR_ACCESS_DENIED) {
    406             ret = -EACCES;
    407         } else {
    408             ret = -EINVAL;
    409         }
    410         goto fail;
    411     }
    412 
    413     if (use_aio) {
    414         s->aio = win32_aio_init();
    415         if (s->aio == NULL) {
    416             CloseHandle(s->hfile);
    417             error_setg(errp, "Could not initialize AIO");
    418             ret = -EINVAL;
    419             goto fail;
    420         }
    421 
    422         ret = win32_aio_attach(s->aio, s->hfile);
    423         if (ret < 0) {
    424             win32_aio_cleanup(s->aio);
    425             CloseHandle(s->hfile);
    426             error_setg_errno(errp, -ret, "Could not enable AIO");
    427             goto fail;
    428         }
    429 
    430         win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
    431     }
    432 
    433     /* When extending regular files, we get zeros from the OS */
    434     bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
    435 
    436     ret = 0;
    437 fail:
    438     qemu_opts_del(opts);
    439     return ret;
    440 }
    441 
    442 static BlockAIOCB *raw_aio_preadv(BlockDriverState *bs,
    443                                   int64_t offset, int64_t bytes,
    444                                   QEMUIOVector *qiov, BdrvRequestFlags flags,
    445                                   BlockCompletionFunc *cb, void *opaque)
    446 {
    447     BDRVRawState *s = bs->opaque;
    448     if (s->aio) {
    449         return win32_aio_submit(bs, s->aio, s->hfile, offset, bytes, qiov,
    450                                 cb, opaque, QEMU_AIO_READ);
    451     } else {
    452         return paio_submit(bs, s->hfile, offset, qiov, bytes,
    453                            cb, opaque, QEMU_AIO_READ);
    454     }
    455 }
    456 
    457 static BlockAIOCB *raw_aio_pwritev(BlockDriverState *bs,
    458                                    int64_t offset, int64_t bytes,
    459                                    QEMUIOVector *qiov, BdrvRequestFlags flags,
    460                                    BlockCompletionFunc *cb, void *opaque)
    461 {
    462     BDRVRawState *s = bs->opaque;
    463     if (s->aio) {
    464         return win32_aio_submit(bs, s->aio, s->hfile, offset, bytes, qiov,
    465                                 cb, opaque, QEMU_AIO_WRITE);
    466     } else {
    467         return paio_submit(bs, s->hfile, offset, qiov, bytes,
    468                            cb, opaque, QEMU_AIO_WRITE);
    469     }
    470 }
    471 
    472 static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
    473                          BlockCompletionFunc *cb, void *opaque)
    474 {
    475     BDRVRawState *s = bs->opaque;
    476     return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
    477 }
    478 
    479 static void raw_close(BlockDriverState *bs)
    480 {
    481     BDRVRawState *s = bs->opaque;
    482 
    483     if (s->aio) {
    484         win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
    485         win32_aio_cleanup(s->aio);
    486         s->aio = NULL;
    487     }
    488 
    489     CloseHandle(s->hfile);
    490     if (bs->open_flags & BDRV_O_TEMPORARY) {
    491         unlink(bs->filename);
    492     }
    493 }
    494 
    495 static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
    496                                         bool exact, PreallocMode prealloc,
    497                                         BdrvRequestFlags flags, Error **errp)
    498 {
    499     BDRVRawState *s = bs->opaque;
    500     LONG low, high;
    501     DWORD dwPtrLow;
    502 
    503     if (prealloc != PREALLOC_MODE_OFF) {
    504         error_setg(errp, "Unsupported preallocation mode '%s'",
    505                    PreallocMode_str(prealloc));
    506         return -ENOTSUP;
    507     }
    508 
    509     low = offset;
    510     high = offset >> 32;
    511 
    512     /*
    513      * An error has occurred if the return value is INVALID_SET_FILE_POINTER
    514      * and GetLastError doesn't return NO_ERROR.
    515      */
    516     dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
    517     if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
    518         error_setg_win32(errp, GetLastError(), "SetFilePointer error");
    519         return -EIO;
    520     }
    521     if (SetEndOfFile(s->hfile) == 0) {
    522         error_setg_win32(errp, GetLastError(), "SetEndOfFile error");
    523         return -EIO;
    524     }
    525     return 0;
    526 }
    527 
    528 static int64_t raw_getlength(BlockDriverState *bs)
    529 {
    530     BDRVRawState *s = bs->opaque;
    531     LARGE_INTEGER l;
    532     ULARGE_INTEGER available, total, total_free;
    533     DISK_GEOMETRY_EX dg;
    534     DWORD count;
    535     BOOL status;
    536 
    537     switch(s->type) {
    538     case FTYPE_FILE:
    539         l.LowPart = GetFileSize(s->hfile, (PDWORD)&l.HighPart);
    540         if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
    541             return -EIO;
    542         break;
    543     case FTYPE_CD:
    544         if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
    545             return -EIO;
    546         l.QuadPart = total.QuadPart;
    547         break;
    548     case FTYPE_HARDDISK:
    549         status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
    550                                  NULL, 0, &dg, sizeof(dg), &count, NULL);
    551         if (status != 0) {
    552             l = dg.DiskSize;
    553         }
    554         break;
    555     default:
    556         return -EIO;
    557     }
    558     return l.QuadPart;
    559 }
    560 
    561 static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
    562 {
    563     typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
    564                                               DWORD * high);
    565     get_compressed_t get_compressed;
    566     struct _stati64 st;
    567     const char *filename = bs->filename;
    568     /* WinNT support GetCompressedFileSize to determine allocate size */
    569     get_compressed =
    570         (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
    571                                             "GetCompressedFileSizeA");
    572     if (get_compressed) {
    573         DWORD high, low;
    574         low = get_compressed(filename, &high);
    575         if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
    576             return (((int64_t) high) << 32) + low;
    577         }
    578     }
    579 
    580     if (_stati64(filename, &st) < 0) {
    581         return -1;
    582     }
    583     return st.st_size;
    584 }
    585 
    586 static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
    587 {
    588     BlockdevCreateOptionsFile *file_opts;
    589     int fd;
    590 
    591     assert(options->driver == BLOCKDEV_DRIVER_FILE);
    592     file_opts = &options->u.file;
    593 
    594     if (file_opts->has_preallocation) {
    595         error_setg(errp, "Preallocation is not supported on Windows");
    596         return -EINVAL;
    597     }
    598     if (file_opts->has_nocow) {
    599         error_setg(errp, "nocow is not supported on Windows");
    600         return -EINVAL;
    601     }
    602 
    603     fd = qemu_create(file_opts->filename, O_WRONLY | O_TRUNC | O_BINARY,
    604                      0644, errp);
    605     if (fd < 0) {
    606         return -EIO;
    607     }
    608     set_sparse(fd);
    609     ftruncate(fd, file_opts->size);
    610     qemu_close(fd);
    611 
    612     return 0;
    613 }
    614 
    615 static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
    616                                            const char *filename,
    617                                            QemuOpts *opts,
    618                                            Error **errp)
    619 {
    620     BlockdevCreateOptions options;
    621     int64_t total_size = 0;
    622 
    623     strstart(filename, "file:", &filename);
    624 
    625     /* Read out options */
    626     total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
    627                           BDRV_SECTOR_SIZE);
    628 
    629     options = (BlockdevCreateOptions) {
    630         .driver     = BLOCKDEV_DRIVER_FILE,
    631         .u.file     = {
    632             .filename           = (char *) filename,
    633             .size               = total_size,
    634             .has_preallocation  = false,
    635             .has_nocow          = false,
    636         },
    637     };
    638     return raw_co_create(&options, errp);
    639 }
    640 
    641 static int raw_reopen_prepare(BDRVReopenState *state,
    642                               BlockReopenQueue *queue, Error **errp)
    643 {
    644     BDRVRawState *s = state->bs->opaque;
    645     BDRVRawReopenState *rs;
    646     int access_flags;
    647     DWORD overlapped;
    648     int ret = 0;
    649 
    650     if (s->type != FTYPE_FILE) {
    651         error_setg(errp, "Can only reopen files");
    652         return -EINVAL;
    653     }
    654 
    655     rs = g_new0(BDRVRawReopenState, 1);
    656 
    657     /*
    658      * We do not support changing any options (only flags). By leaving
    659      * all options in state->options, we tell the generic reopen code
    660      * that we do not support changing any of them, so it will verify
    661      * that their values did not change.
    662      */
    663 
    664     raw_parse_flags(state->flags, s->aio != NULL, &access_flags, &overlapped);
    665     rs->hfile = CreateFile(state->bs->filename, access_flags,
    666                            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    667                            OPEN_EXISTING, overlapped, NULL);
    668 
    669     if (rs->hfile == INVALID_HANDLE_VALUE) {
    670         int err = GetLastError();
    671 
    672         error_setg_win32(errp, err, "Could not reopen '%s'",
    673                          state->bs->filename);
    674         if (err == ERROR_ACCESS_DENIED) {
    675             ret = -EACCES;
    676         } else {
    677             ret = -EINVAL;
    678         }
    679         goto fail;
    680     }
    681 
    682     if (s->aio) {
    683         ret = win32_aio_attach(s->aio, rs->hfile);
    684         if (ret < 0) {
    685             error_setg_errno(errp, -ret, "Could not enable AIO");
    686             CloseHandle(rs->hfile);
    687             goto fail;
    688         }
    689     }
    690 
    691     state->opaque = rs;
    692 
    693     return 0;
    694 
    695 fail:
    696     g_free(rs);
    697     state->opaque = NULL;
    698 
    699     return ret;
    700 }
    701 
    702 static void raw_reopen_commit(BDRVReopenState *state)
    703 {
    704     BDRVRawState *s = state->bs->opaque;
    705     BDRVRawReopenState *rs = state->opaque;
    706 
    707     assert(rs != NULL);
    708 
    709     CloseHandle(s->hfile);
    710     s->hfile = rs->hfile;
    711 
    712     g_free(rs);
    713     state->opaque = NULL;
    714 }
    715 
    716 static void raw_reopen_abort(BDRVReopenState *state)
    717 {
    718     BDRVRawReopenState *rs = state->opaque;
    719 
    720     if (!rs) {
    721         return;
    722     }
    723 
    724     if (rs->hfile != INVALID_HANDLE_VALUE) {
    725         CloseHandle(rs->hfile);
    726     }
    727 
    728     g_free(rs);
    729     state->opaque = NULL;
    730 }
    731 
    732 static QemuOptsList raw_create_opts = {
    733     .name = "raw-create-opts",
    734     .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
    735     .desc = {
    736         {
    737             .name = BLOCK_OPT_SIZE,
    738             .type = QEMU_OPT_SIZE,
    739             .help = "Virtual disk size"
    740         },
    741         { /* end of list */ }
    742     }
    743 };
    744 
    745 BlockDriver bdrv_file = {
    746     .format_name	= "file",
    747     .protocol_name	= "file",
    748     .instance_size	= sizeof(BDRVRawState),
    749     .bdrv_needs_filename = true,
    750     .bdrv_parse_filename = raw_parse_filename,
    751     .bdrv_file_open     = raw_open,
    752     .bdrv_refresh_limits = raw_probe_alignment,
    753     .bdrv_close         = raw_close,
    754     .bdrv_co_create_opts = raw_co_create_opts,
    755     .bdrv_has_zero_init = bdrv_has_zero_init_1,
    756 
    757     .bdrv_reopen_prepare = raw_reopen_prepare,
    758     .bdrv_reopen_commit  = raw_reopen_commit,
    759     .bdrv_reopen_abort   = raw_reopen_abort,
    760 
    761     .bdrv_aio_preadv    = raw_aio_preadv,
    762     .bdrv_aio_pwritev   = raw_aio_pwritev,
    763     .bdrv_aio_flush     = raw_aio_flush,
    764 
    765     .bdrv_co_truncate   = raw_co_truncate,
    766     .bdrv_getlength	= raw_getlength,
    767     .bdrv_get_allocated_file_size
    768                         = raw_get_allocated_file_size,
    769 
    770     .create_opts        = &raw_create_opts,
    771 };
    772 
    773 /***********************************************/
    774 /* host device */
    775 
    776 static int find_cdrom(char *cdrom_name, int cdrom_name_size)
    777 {
    778     char drives[256], *pdrv = drives;
    779     UINT type;
    780 
    781     memset(drives, 0, sizeof(drives));
    782     GetLogicalDriveStrings(sizeof(drives), drives);
    783     while(pdrv[0] != '\0') {
    784         type = GetDriveType(pdrv);
    785         switch(type) {
    786         case DRIVE_CDROM:
    787             snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
    788             return 0;
    789             break;
    790         }
    791         pdrv += lstrlen(pdrv) + 1;
    792     }
    793     return -1;
    794 }
    795 
    796 static int find_device_type(BlockDriverState *bs, const char *filename)
    797 {
    798     BDRVRawState *s = bs->opaque;
    799     UINT type;
    800     const char *p;
    801 
    802     if (strstart(filename, "\\\\.\\", &p) ||
    803         strstart(filename, "//./", &p)) {
    804         if (stristart(p, "PhysicalDrive", NULL))
    805             return FTYPE_HARDDISK;
    806         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
    807         type = GetDriveType(s->drive_path);
    808         switch (type) {
    809         case DRIVE_REMOVABLE:
    810         case DRIVE_FIXED:
    811             return FTYPE_HARDDISK;
    812         case DRIVE_CDROM:
    813             return FTYPE_CD;
    814         default:
    815             return FTYPE_FILE;
    816         }
    817     } else {
    818         return FTYPE_FILE;
    819     }
    820 }
    821 
    822 static int hdev_probe_device(const char *filename)
    823 {
    824     if (strstart(filename, "/dev/cdrom", NULL))
    825         return 100;
    826     if (is_windows_drive(filename))
    827         return 100;
    828     return 0;
    829 }
    830 
    831 static void hdev_parse_filename(const char *filename, QDict *options,
    832                                 Error **errp)
    833 {
    834     bdrv_parse_filename_strip_prefix(filename, "host_device:", options);
    835 }
    836 
    837 static void hdev_refresh_limits(BlockDriverState *bs, Error **errp)
    838 {
    839     /* XXX Does Windows support AIO on less than 512-byte alignment? */
    840     bs->bl.request_alignment = 512;
    841 }
    842 
    843 static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
    844                      Error **errp)
    845 {
    846     BDRVRawState *s = bs->opaque;
    847     int access_flags, create_flags;
    848     int ret = 0;
    849     DWORD overlapped;
    850     char device_name[64];
    851 
    852     Error *local_err = NULL;
    853     const char *filename;
    854     bool use_aio;
    855 
    856     QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0,
    857                                       &error_abort);
    858     if (!qemu_opts_absorb_qdict(opts, options, errp)) {
    859         ret = -EINVAL;
    860         goto done;
    861     }
    862 
    863     filename = qemu_opt_get(opts, "filename");
    864 
    865     use_aio = get_aio_option(opts, flags, &local_err);
    866     if (!local_err && use_aio) {
    867         error_setg(&local_err, "AIO is not supported on Windows host devices");
    868     }
    869     if (local_err) {
    870         error_propagate(errp, local_err);
    871         ret = -EINVAL;
    872         goto done;
    873     }
    874 
    875     if (strstart(filename, "/dev/cdrom", NULL)) {
    876         if (find_cdrom(device_name, sizeof(device_name)) < 0) {
    877             error_setg(errp, "Could not open CD-ROM drive");
    878             ret = -ENOENT;
    879             goto done;
    880         }
    881         filename = device_name;
    882     } else {
    883         /* transform drive letters into device name */
    884         if (((filename[0] >= 'a' && filename[0] <= 'z') ||
    885              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
    886             filename[1] == ':' && filename[2] == '\0') {
    887             snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
    888             filename = device_name;
    889         }
    890     }
    891     s->type = find_device_type(bs, filename);
    892 
    893     raw_parse_flags(flags, use_aio, &access_flags, &overlapped);
    894 
    895     create_flags = OPEN_EXISTING;
    896 
    897     s->hfile = CreateFile(filename, access_flags,
    898                           FILE_SHARE_READ, NULL,
    899                           create_flags, overlapped, NULL);
    900     if (s->hfile == INVALID_HANDLE_VALUE) {
    901         int err = GetLastError();
    902 
    903         if (err == ERROR_ACCESS_DENIED) {
    904             ret = -EACCES;
    905         } else {
    906             ret = -EINVAL;
    907         }
    908         error_setg_errno(errp, -ret, "Could not open device");
    909         goto done;
    910     }
    911 
    912 done:
    913     qemu_opts_del(opts);
    914     return ret;
    915 }
    916 
    917 static BlockDriver bdrv_host_device = {
    918     .format_name	= "host_device",
    919     .protocol_name	= "host_device",
    920     .instance_size	= sizeof(BDRVRawState),
    921     .bdrv_needs_filename = true,
    922     .bdrv_parse_filename = hdev_parse_filename,
    923     .bdrv_probe_device	= hdev_probe_device,
    924     .bdrv_file_open	= hdev_open,
    925     .bdrv_close		= raw_close,
    926     .bdrv_refresh_limits = hdev_refresh_limits,
    927 
    928     .bdrv_aio_preadv    = raw_aio_preadv,
    929     .bdrv_aio_pwritev   = raw_aio_pwritev,
    930     .bdrv_aio_flush     = raw_aio_flush,
    931 
    932     .bdrv_detach_aio_context = raw_detach_aio_context,
    933     .bdrv_attach_aio_context = raw_attach_aio_context,
    934 
    935     .bdrv_getlength      = raw_getlength,
    936     .has_variable_length = true,
    937 
    938     .bdrv_get_allocated_file_size
    939                         = raw_get_allocated_file_size,
    940 };
    941 
    942 static void bdrv_file_init(void)
    943 {
    944     bdrv_register(&bdrv_file);
    945     bdrv_register(&bdrv_host_device);
    946 }
    947 
    948 block_init(bdrv_file_init);