Statistics
| Branch: | Revision:

root / block-raw.c @ 83f64091

History | View | Annotate | Download (20.2 kB)

1
/*
2
 * Block driver for RAW files
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 "vl.h"
25
#include "block_int.h"
26
#include <assert.h>
27
#ifndef _WIN32
28
#include <aio.h>
29

    
30
#ifndef QEMU_TOOL
31
#include "exec-all.h"
32
#endif
33

    
34
#ifdef CONFIG_COCOA
35
#include <paths.h>
36
#include <sys/param.h>
37
#include <IOKit/IOKitLib.h>
38
#include <IOKit/IOBSD.h>
39
#include <IOKit/storage/IOMediaBSDClient.h>
40
#include <IOKit/storage/IOMedia.h>
41
#include <IOKit/storage/IOCDMedia.h>
42
//#include <IOKit/storage/IOCDTypes.h>
43
#include <CoreFoundation/CoreFoundation.h>
44
#endif
45

    
46
#ifdef __sun__
47
#include <sys/dkio.h>
48
#endif
49

    
50
typedef struct BDRVRawState {
51
    int fd;
52
} BDRVRawState;
53

    
54
#ifdef CONFIG_COCOA
55
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
56
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
57

    
58
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
59
{
60
    kern_return_t       kernResult; 
61
    mach_port_t     masterPort;
62
    CFMutableDictionaryRef  classesToMatch;
63

    
64
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
65
    if ( KERN_SUCCESS != kernResult ) {
66
        printf( "IOMasterPort returned %d\n", kernResult );
67
    }
68
    
69
    classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
70
    if ( classesToMatch == NULL ) {
71
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
72
    } else {
73
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
74
    }
75
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
76
    if ( KERN_SUCCESS != kernResult )
77
    {
78
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
79
    }
80
    
81
    return kernResult;
82
}
83

    
84
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
85
{
86
    io_object_t     nextMedia;
87
    kern_return_t   kernResult = KERN_FAILURE;
88
    *bsdPath = '\0';
89
    nextMedia = IOIteratorNext( mediaIterator );
90
    if ( nextMedia )
91
    {
92
        CFTypeRef   bsdPathAsCFString;
93
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
94
        if ( bsdPathAsCFString ) {
95
            size_t devPathLength;
96
            strcpy( bsdPath, _PATH_DEV );
97
            strcat( bsdPath, "r" );
98
            devPathLength = strlen( bsdPath );
99
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
100
                kernResult = KERN_SUCCESS;
101
            }
102
            CFRelease( bsdPathAsCFString );
103
        }
104
        IOObjectRelease( nextMedia );
105
    }
106
    
107
    return kernResult;
108
}
109

    
110
#endif
111

    
112
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
113
{
114
    BDRVRawState *s = bs->opaque;
115
    int fd, open_flags;
116

    
117
#ifdef CONFIG_COCOA
118
    if (strstart(filename, "/dev/cdrom", NULL)) {
119
        kern_return_t kernResult;
120
        io_iterator_t mediaIterator;
121
        char bsdPath[ MAXPATHLEN ];
122
        int fd;
123
 
124
        kernResult = FindEjectableCDMedia( &mediaIterator );
125
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
126
    
127
        if ( bsdPath[ 0 ] != '\0' ) {
128
            strcat(bsdPath,"s0");
129
            /* some CDs don't have a partition 0 */
130
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
131
            if (fd < 0) {
132
                bsdPath[strlen(bsdPath)-1] = '1';
133
            } else {
134
                close(fd);
135
            }
136
            filename = bsdPath;
137
        }
138
        
139
        if ( mediaIterator )
140
            IOObjectRelease( mediaIterator );
141
    }
142
#endif
143
    open_flags = O_BINARY;
144
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
145
        open_flags |= O_RDWR;
146
    } else {
147
        open_flags |= O_RDONLY;
148
        bs->read_only = 1;
149
    }
150
    if (flags & BDRV_O_CREAT)
151
        open_flags |= O_CREAT | O_TRUNC;
152

    
153
    fd = open(filename, open_flags, 0644);
154
    if (fd < 0)
155
        return -errno;
156
    s->fd = fd;
157
    return 0;
158
}
159

    
160
/* XXX: use host sector size if necessary with:
161
#ifdef DIOCGSECTORSIZE
162
        {
163
            unsigned int sectorsize = 512;
164
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
165
                sectorsize > bufsize)
166
                bufsize = sectorsize;
167
        }
168
#endif
169
#ifdef CONFIG_COCOA
170
        u_int32_t   blockSize = 512;
171
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
172
            bufsize = blockSize;
173
        }
174
#endif
175
*/
176

    
177
static int raw_pread(BlockDriverState *bs, int64_t offset, 
178
                     uint8_t *buf, int count)
179
{
180
    BDRVRawState *s = bs->opaque;
181
    int ret;
182
    
183
    lseek(s->fd, offset, SEEK_SET);
184
    ret = read(s->fd, buf, count);
185
    return ret;
186
}
187

    
188
static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
189
                      const uint8_t *buf, int count)
190
{
191
    BDRVRawState *s = bs->opaque;
192
    int ret;
193
    
194
    lseek(s->fd, offset, SEEK_SET);
195
    ret = write(s->fd, buf, count);
196
    return ret;
197
}
198

    
199
/***********************************************************/
200
/* Unix AOP using POSIX AIO */
201

    
202
typedef struct RawAIOCB {
203
    struct aiocb aiocb;
204
    int busy; /* only used for debugging */
205
    BlockDriverAIOCB *next;
206
} RawAIOCB;
207

    
208
static int aio_sig_num = SIGUSR2;
209
static BlockDriverAIOCB *first_aio; /* AIO issued */
210

    
211
#ifndef QEMU_TOOL
212
static void aio_signal_handler(int signum)
213
{
214
    CPUState *env = cpu_single_env;
215
    if (env) {
216
        /* stop the currently executing cpu because a timer occured */
217
        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
218
#ifdef USE_KQEMU
219
        if (env->kqemu_enabled) {
220
            kqemu_cpu_interrupt(env);
221
        }
222
#endif
223
    }
224
}
225

    
226
void qemu_aio_init(void)
227
{
228
    struct sigaction act;
229
    
230
    sigfillset(&act.sa_mask);
231
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
232
    act.sa_handler = aio_signal_handler;
233
    sigaction(aio_sig_num, &act, NULL);
234

    
235
    {
236
        /* XXX: aio thread exit seems to hang on RH 9 */
237
        struct aioinit ai;
238
        memset(&ai, 0, sizeof(ai));
239
        ai.aio_threads = 2;
240
        ai.aio_num = 1;
241
        ai.aio_idle_time = 365 * 100000;
242
        aio_init(&ai);
243
    }
244
}
245
#endif /* !QEMU_TOOL */
246

    
247
void qemu_aio_poll(void)
248
{
249
    BlockDriverAIOCB *acb, **pacb;
250
    RawAIOCB *acb1;
251
    int ret;
252

    
253
    for(;;) {
254
        pacb = &first_aio;
255
        for(;;) {
256
            acb = *pacb;
257
            if (!acb)
258
                goto the_end;
259
            acb1 = acb->opaque;
260
            ret = aio_error(&acb1->aiocb);
261
            if (ret == ECANCELED) {
262
                /* remove the request */
263
                acb1->busy = 0;
264
                *pacb = acb1->next;
265
            } else if (ret != EINPROGRESS) {
266
                /* end of aio */
267
                if (ret == 0) {
268
                    ret = aio_return(&acb1->aiocb);
269
                    if (ret == acb1->aiocb.aio_nbytes)
270
                        ret = 0;
271
                    else
272
                        ret = -1;
273
                } else {
274
                    ret = -ret;
275
                }
276
                /* remove the request */
277
                acb1->busy = 0;
278
                *pacb = acb1->next;
279
                /* call the callback */
280
                acb->cb(acb->cb_opaque, ret);
281
                break;
282
            } else {
283
                pacb = &acb1->next;
284
            }
285
        }
286
    }
287
 the_end: ;
288
}
289

    
290
/* wait until at least one AIO was handled */
291
static sigset_t wait_oset;
292

    
293
void qemu_aio_wait_start(void)
294
{
295
    sigset_t set;
296
    sigemptyset(&set);
297
    sigaddset(&set, aio_sig_num);
298
    sigprocmask(SIG_BLOCK, &set, &wait_oset);
299
}
300

    
301
void qemu_aio_wait(void)
302
{
303
    sigset_t set;
304
    int nb_sigs;
305
    sigemptyset(&set);
306
    sigaddset(&set, aio_sig_num);
307
    sigwait(&set, &nb_sigs);
308
    qemu_aio_poll();
309
}
310

    
311
void qemu_aio_wait_end(void)
312
{
313
    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
314
}
315

    
316
static int raw_aio_new(BlockDriverAIOCB *acb)
317
{
318
    RawAIOCB *acb1;
319
    BDRVRawState *s = acb->bs->opaque;
320

    
321
    acb1 = qemu_mallocz(sizeof(RawAIOCB));
322
    if (!acb1)
323
        return -1;
324
    acb->opaque = acb1;
325
    acb1->aiocb.aio_fildes = s->fd;
326
    acb1->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
327
    acb1->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
328
    return 0;
329
}
330

    
331
static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, 
332
                        uint8_t *buf, int nb_sectors)
333
{
334
    RawAIOCB *acb1 = acb->opaque;
335

    
336
    assert(acb1->busy == 0);
337
    acb1->busy = 1;
338
    acb1->aiocb.aio_buf = buf;
339
    acb1->aiocb.aio_nbytes = nb_sectors * 512;
340
    acb1->aiocb.aio_offset = sector_num * 512;
341
    acb1->next = first_aio;
342
    first_aio = acb;
343
    if (aio_read(&acb1->aiocb) < 0) {
344
        acb1->busy = 0;
345
        return -errno;
346
    } 
347
    return 0;
348
}
349

    
350
static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, 
351
                         const uint8_t *buf, int nb_sectors)
352
{
353
    RawAIOCB *acb1 = acb->opaque;
354

    
355
    assert(acb1->busy == 0);
356
    acb1->busy = 1;
357
    acb1->aiocb.aio_buf = (uint8_t *)buf;
358
    acb1->aiocb.aio_nbytes = nb_sectors * 512;
359
    acb1->aiocb.aio_offset = sector_num * 512;
360
    acb1->next = first_aio;
361
    first_aio = acb;
362
    if (aio_write(&acb1->aiocb) < 0) {
363
        acb1->busy = 0;
364
        return -errno;
365
    } 
366
    return 0;
367
}
368

    
369
static void raw_aio_cancel(BlockDriverAIOCB *acb)
370
{
371
    RawAIOCB *acb1 = acb->opaque;
372
    int ret;
373
    BlockDriverAIOCB **pacb;
374

    
375
    ret = aio_cancel(acb1->aiocb.aio_fildes, &acb1->aiocb);
376
    if (ret == AIO_NOTCANCELED) {
377
        /* fail safe: if the aio could not be canceled, we wait for
378
           it */
379
        while (aio_error(&acb1->aiocb) == EINPROGRESS);
380
    }
381

    
382
    /* remove the callback from the queue */
383
    pacb = &first_aio;
384
    for(;;) {
385
        if (*pacb == NULL) {
386
            break;
387
        } else if (*pacb == acb) {
388
            acb1->busy = 0;
389
            *pacb = acb1->next;
390
            break;
391
        }
392
        acb1 = (*pacb)->opaque;
393
        pacb = &acb1->next;
394
    }
395
}
396

    
397
static void raw_aio_delete(BlockDriverAIOCB *acb)
398
{
399
    RawAIOCB *acb1 = acb->opaque;
400
    raw_aio_cancel(acb);
401
    qemu_free(acb1);
402
}
403

    
404
static void raw_close(BlockDriverState *bs)
405
{
406
    BDRVRawState *s = bs->opaque;
407
    close(s->fd);
408
}
409

    
410
static int raw_truncate(BlockDriverState *bs, int64_t offset)
411
{
412
    BDRVRawState *s = bs->opaque;
413
    if (ftruncate(s->fd, offset) < 0)
414
        return -errno;
415
    return 0;
416
}
417

    
418
static int64_t  raw_getlength(BlockDriverState *bs)
419
{
420
    BDRVRawState *s = bs->opaque;
421
    int fd = s->fd;
422
    int64_t size;
423
#ifdef _BSD
424
    struct stat sb;
425
#endif
426
#ifdef __sun__
427
    struct dk_minfo minfo;
428
    int rv;
429
#endif
430

    
431
#ifdef _BSD
432
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
433
#ifdef DIOCGMEDIASIZE
434
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
435
#endif
436
#ifdef CONFIG_COCOA
437
        size = LONG_LONG_MAX;
438
#else
439
        size = lseek(fd, 0LL, SEEK_END);
440
#endif
441
    } else
442
#endif
443
#ifdef __sun__
444
    /*
445
     * use the DKIOCGMEDIAINFO ioctl to read the size.
446
     */
447
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
448
    if ( rv != -1 ) {
449
        size = minfo.dki_lbsize * minfo.dki_capacity;
450
    } else /* there are reports that lseek on some devices
451
              fails, but irc discussion said that contingency
452
              on contingency was overkill */
453
#endif
454
    {
455
        size = lseek(fd, 0, SEEK_END);
456
    }
457
#ifdef _WIN32
458
    /* On Windows hosts it can happen that we're unable to get file size
459
       for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
460
    if (size == -1)
461
        size = LONG_LONG_MAX;
462
#endif
463
    return size;
464
}
465

    
466
static int raw_create(const char *filename, int64_t total_size,
467
                      const char *backing_file, int flags)
468
{
469
    int fd;
470

    
471
    if (flags || backing_file)
472
        return -ENOTSUP;
473

    
474
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
475
              0644);
476
    if (fd < 0)
477
        return -EIO;
478
    ftruncate(fd, total_size * 512);
479
    close(fd);
480
    return 0;
481
}
482

    
483
static void raw_flush(BlockDriverState *bs)
484
{
485
    BDRVRawState *s = bs->opaque;
486
    fsync(s->fd);
487
}
488

    
489
BlockDriver bdrv_raw = {
490
    "raw",
491
    sizeof(BDRVRawState),
492
    NULL, /* no probe for protocols */
493
    raw_open,
494
    NULL,
495
    NULL,
496
    raw_close,
497
    raw_create,
498
    raw_flush,
499
    
500
    .bdrv_aio_new = raw_aio_new,
501
    .bdrv_aio_read = raw_aio_read,
502
    .bdrv_aio_write = raw_aio_write,
503
    .bdrv_aio_cancel = raw_aio_cancel,
504
    .bdrv_aio_delete = raw_aio_delete,
505
    .protocol_name = "file",
506
    .bdrv_pread = raw_pread,
507
    .bdrv_pwrite = raw_pwrite,
508
    .bdrv_truncate = raw_truncate,
509
    .bdrv_getlength = raw_getlength,
510
};
511

    
512
#else /* _WIN32 */
513

    
514
/* XXX: use another file ? */
515
#include <windows.h>
516
#include <winioctl.h>
517

    
518
typedef struct BDRVRawState {
519
    HANDLE hfile;
520
} BDRVRawState;
521

    
522
typedef struct RawAIOCB {
523
    HANDLE hEvent;
524
    OVERLAPPED ov;
525
    int count;
526
} RawAIOCB;
527

    
528
int qemu_ftruncate64(int fd, int64_t length)
529
{
530
    LARGE_INTEGER li;
531
    LONG high;
532
    HANDLE h;
533
    BOOL res;
534

    
535
    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
536
        return -1;
537

    
538
    h = (HANDLE)_get_osfhandle(fd);
539

    
540
    /* get current position, ftruncate do not change position */
541
    li.HighPart = 0;
542
    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
543
    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
544
        return -1;
545

    
546
    high = length >> 32;
547
    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
548
        return -1;
549
    res = SetEndOfFile(h);
550

    
551
    /* back to old position */
552
    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
553
    return res ? 0 : -1;
554
}
555

    
556
static int set_sparse(int fd)
557
{
558
    DWORD returned;
559
    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
560
                                 NULL, 0, NULL, 0, &returned, NULL);
561
}
562

    
563
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
564
{
565
    BDRVRawState *s = bs->opaque;
566
    int access_flags, create_flags;
567

    
568
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
569
        access_flags = GENERIC_READ | GENERIC_WRITE;
570
    } else {
571
        access_flags = GENERIC_READ;
572
    }
573
    if (flags & BDRV_O_CREATE) {
574
        create_flags = CREATE_ALWAYS;
575
    } else {
576
        create_flags = OPEN_EXISTING;
577
    }
578
    s->hfile = CreateFile(filename, access_flags, 
579
                          FILE_SHARE_READ, NULL,
580
                          create_flags, FILE_FLAG_OVERLAPPED, 0);
581
    if (s->hfile == INVALID_HANDLE_VALUE) 
582
        return -1;
583
    return 0;
584
}
585

    
586
static int raw_pread(BlockDriverState *bs, int64_t offset, 
587
                     uint8_t *buf, int count)
588
{
589
    BDRVRawState *s = bs->opaque;
590
    OVERLAPPED ov;
591
    DWORD ret_count;
592
    int ret;
593
    
594
    memset(&ov, 0, sizeof(ov));
595
    ov.Offset = offset;
596
    ov.OffsetHigh = offset >> 32;
597
    ret = ReadFile(s->hfile, buf, count, NULL, &ov);
598
    if (!ret)
599
        return -EIO;
600
    ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
601
    if (!ret)
602
        return -EIO;
603
    return ret_count;
604
}
605

    
606
static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
607
                      const uint8_t *buf, int count)
608
{
609
    BDRVRawState *s = bs->opaque;
610
    OVERLAPPED ov;
611
    DWORD ret_count;
612
    int ret;
613
    
614
    memset(&ov, 0, sizeof(ov));
615
    ov.Offset = offset;
616
    ov.OffsetHigh = offset >> 32;
617
    ret = WriteFile(s->hfile, buf, count, NULL, &ov);
618
    if (!ret)
619
        return -EIO;
620
    ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
621
    if (!ret)
622
        return -EIO;
623
    return ret_count;
624
}
625

    
626
static int raw_aio_new(BlockDriverAIOCB *acb)
627
{
628
    RawAIOCB *acb1;
629
    BDRVRawState *s = acb->bs->opaque;
630

    
631
    acb1 = qemu_mallocz(sizeof(RawAIOCB));
632
    if (!acb1)
633
        return -ENOMEM;
634
    acb->opaque = acb1;
635
    s->hevent = CreateEvent(NULL, TRUE, FALSE, NULL);
636
    if (!s->hevent)
637
        return -ENOMEM;
638
    return 0;
639
}
640

    
641
static void raw_aio_cb(void *opaque)
642
{
643
    BlockDriverAIOCB *acb = acb1;
644
    RawAIOCB *acb1 = acb->opaque;
645
    DWORD ret_count;
646
    int ret;
647

    
648
    ret = GetOverlappedResult(s->hfile, &acb1->ov, &ret_count, TRUE);
649
    if (!ret || ret_count != acb1->count) {
650
        acb->cb(acb->cb_opaque, -EIO);
651
    } else {
652
        acb->cb(acb->cb_opaque, 0);
653
    }
654
}
655

    
656
static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, 
657
                        uint8_t *buf, int nb_sectors)
658
{
659
    BlockDriverState *bs = acb->bs;
660
    BDRVRawState *s = bs->opaque;
661
    RawAIOCB *acb1 = acb->opaque;
662
    DWORD ret_count;
663
    int ret;
664
    int64_t offset;
665

    
666
    memset(&acb1->ov, 0, sizeof(acb1->ov));
667
    offset = sector_num * 512;
668
    acb1->ov.Offset = offset;
669
    acb1->ov.OffsetHigh = offset >> 32;
670
    acb1->ov.hEvent = acb1->hEvent;
671
    acb1->count = nb_sectors * 512;
672
    qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
673
    ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
674
    if (!ret)
675
        return -EIO;
676
    return 0;
677
}
678

    
679
static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, 
680
                         uint8_t *buf, int nb_sectors)
681
{
682
    BlockDriverState *bs = acb->bs;
683
    BDRVRawState *s = bs->opaque;
684
    RawAIOCB *acb1 = acb->opaque;
685
    DWORD ret_count;
686
    int ret;
687
    int64_t offset;
688

    
689
    memset(&acb1->ov, 0, sizeof(acb1->ov));
690
    offset = sector_num * 512;
691
    acb1->ov.Offset = offset;
692
    acb1->ov.OffsetHigh = offset >> 32;
693
    acb1->ov.hEvent = acb1->hEvent;
694
    acb1->count = nb_sectors * 512;
695
    qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
696
    ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
697
    if (!ret)
698
        return -EIO;
699
    return 0;
700
}
701

    
702
static void raw_aio_cancel(BlockDriverAIOCB *acb)
703
{
704
    BlockDriverState *bs = acb->bs;
705
    BDRVRawState *s = bs->opaque;
706
    RawAIOCB *acb1 = acb->opaque;
707

    
708
    qemu_del_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
709
    /* XXX: if more than one async I/O it is not correct */
710
    CancelIo(s->hfile);
711
}
712

    
713
static void raw_aio_delete(BlockDriverAIOCB *acb)
714
{
715
    RawAIOCB *acb1 = acb->opaque;
716
    raw_aio_cancel(acb);
717
    CloseHandle(acb1->hEvent);
718
    qemu_free(acb1);
719
}
720

    
721
static void raw_flush(BlockDriverState *bs)
722
{
723
    /* XXX: add it */
724
}
725

    
726
static void raw_close(BlockDriverState *bs)
727
{
728
    BDRVRawState *s = bs->opaque;
729
    CloseHandle(s->hfile);
730
}
731

    
732
static int raw_truncate(BlockDriverState *bs, int64_t offset)
733
{
734
    BDRVRawState *s = bs->opaque;
735
    DWORD low, high;
736

    
737
    low = length;
738
    high = length >> 32;
739
    if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
740
        return -EIO;
741
    if (!SetEndOfFile(s->hfile))
742
        return -EIO;
743
    return 0;
744
}
745

    
746
static int64_t  raw_getlength(BlockDriverState *bs)
747
{
748
    BDRVRawState *s = bs->opaque;
749
    LARGE_INTEGER l;
750
    if (!GetFileSizeEx(s->hfile, &l))
751
        return -EIO;
752
    return l.QuadPart;
753
}
754

    
755
static int raw_create(const char *filename, int64_t total_size,
756
                      const char *backing_file, int flags)
757
{
758
    int fd;
759

    
760
    if (flags || backing_file)
761
        return -ENOTSUP;
762

    
763
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
764
              0644);
765
    if (fd < 0)
766
        return -EIO;
767
    set_sparse(fd);
768
    ftruncate(fd, total_size * 512);
769
    close(fd);
770
    return 0;
771
}
772

    
773
void qemu_aio_init(void)
774
{
775
}
776

    
777
void qemu_aio_poll(void)
778
{
779
}
780

    
781
void qemu_aio_wait_start(void)
782
{
783
}
784

    
785
void qemu_aio_wait(void)
786
{
787
}
788

    
789
void qemu_aio_wait_end(void)
790
{
791
}
792

    
793
BlockDriver bdrv_raw = {
794
    "raw",
795
    sizeof(BDRVRawState),
796
    NULL, /* no probe for protocols */
797
    raw_open,
798
    NULL,
799
    NULL,
800
    raw_close,
801
    raw_create,
802
    raw_flush,
803
    
804
#if 0
805
    .bdrv_aio_new = raw_aio_new,
806
    .bdrv_aio_read = raw_aio_read,
807
    .bdrv_aio_write = raw_aio_write,
808
    .bdrv_aio_cancel = raw_aio_cancel,
809
    .bdrv_aio_delete = raw_aio_delete,
810
#endif
811
    .protocol_name = "file",
812
    .bdrv_pread = raw_pread,
813
    .bdrv_pwrite = raw_pwrite,
814
    .bdrv_truncate = raw_truncate,
815
    .bdrv_getlength = raw_getlength,
816
};
817
#endif /* _WIN32 */