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