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