Statistics
| Branch: | Revision:

root / block-raw-posix.c @ a76bab49

History | View | Annotate | Download (30.7 kB)

1
/*
2
 * Block driver for RAW files (posix)
3
 *
4
 * Copyright (c) 2006 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "qemu-common.h"
25
#include "qemu-timer.h"
26
#include "qemu-char.h"
27
#include "block_int.h"
28
#include "compatfd.h"
29
#include <assert.h>
30
#ifdef CONFIG_AIO
31
#include <aio.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
#define _POSIX_PTHREAD_SEMANTICS 1
48
#include <signal.h>
49
#include <sys/dkio.h>
50
#endif
51
#ifdef __linux__
52
#include <sys/ioctl.h>
53
#include <linux/cdrom.h>
54
#include <linux/fd.h>
55
#endif
56
#ifdef __FreeBSD__
57
#include <signal.h>
58
#include <sys/disk.h>
59
#endif
60

    
61
#ifdef __OpenBSD__
62
#include <sys/ioctl.h>
63
#include <sys/disklabel.h>
64
#include <sys/dkio.h>
65
#endif
66

    
67
//#define DEBUG_FLOPPY
68

    
69
//#define DEBUG_BLOCK
70
#if defined(DEBUG_BLOCK)
71
#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)        \
72
    { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
73
#else
74
#define DEBUG_BLOCK_PRINT(formatCstr, args...)
75
#endif
76

    
77
#define FTYPE_FILE   0
78
#define FTYPE_CD     1
79
#define FTYPE_FD     2
80

    
81
#define ALIGNED_BUFFER_SIZE (32 * 512)
82

    
83
/* if the FD is not accessed during that time (in ms), we try to
84
   reopen it to see if the disk has been changed */
85
#define FD_OPEN_TIMEOUT 1000
86

    
87
typedef struct BDRVRawState {
88
    int fd;
89
    int type;
90
    unsigned int lseek_err_cnt;
91
#if defined(__linux__)
92
    /* linux floppy specific */
93
    int fd_open_flags;
94
    int64_t fd_open_time;
95
    int64_t fd_error_time;
96
    int fd_got_error;
97
    int fd_media_changed;
98
#endif
99
#if defined(O_DIRECT)
100
    uint8_t* aligned_buf;
101
#endif
102
} BDRVRawState;
103

    
104
static int posix_aio_init(void);
105

    
106
static int fd_open(BlockDriverState *bs);
107

    
108
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
109
{
110
    BDRVRawState *s = bs->opaque;
111
    int fd, open_flags, ret;
112

    
113
    posix_aio_init();
114

    
115
    s->lseek_err_cnt = 0;
116

    
117
    open_flags = O_BINARY;
118
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
119
        open_flags |= O_RDWR;
120
    } else {
121
        open_flags |= O_RDONLY;
122
        bs->read_only = 1;
123
    }
124
    if (flags & BDRV_O_CREAT)
125
        open_flags |= O_CREAT | O_TRUNC;
126
#ifdef O_DIRECT
127
    if (flags & BDRV_O_DIRECT)
128
        open_flags |= O_DIRECT;
129
#endif
130

    
131
    s->type = FTYPE_FILE;
132

    
133
    fd = open(filename, open_flags, 0644);
134
    if (fd < 0) {
135
        ret = -errno;
136
        if (ret == -EROFS)
137
            ret = -EACCES;
138
        return ret;
139
    }
140
    s->fd = fd;
141
#if defined(O_DIRECT)
142
    s->aligned_buf = NULL;
143
    if (flags & BDRV_O_DIRECT) {
144
        s->aligned_buf = qemu_memalign(512, ALIGNED_BUFFER_SIZE);
145
        if (s->aligned_buf == NULL) {
146
            ret = -errno;
147
            close(fd);
148
            return ret;
149
        }
150
    }
151
#endif
152
    return 0;
153
}
154

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

    
172
/*
173
 * offset and count are in bytes, but must be multiples of 512 for files
174
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
175
 *
176
 * This function may be called without alignment if the caller ensures
177
 * that O_DIRECT is not in effect.
178
 */
179
static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
180
                     uint8_t *buf, int count)
181
{
182
    BDRVRawState *s = bs->opaque;
183
    int ret;
184

    
185
    ret = fd_open(bs);
186
    if (ret < 0)
187
        return ret;
188

    
189
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
190
        ++(s->lseek_err_cnt);
191
        if(s->lseek_err_cnt <= 10) {
192
            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
193
                              "] lseek failed : %d = %s\n",
194
                              s->fd, bs->filename, offset, buf, count,
195
                              bs->total_sectors, errno, strerror(errno));
196
        }
197
        return -1;
198
    }
199
    s->lseek_err_cnt=0;
200

    
201
    ret = read(s->fd, buf, count);
202
    if (ret == count)
203
        goto label__raw_read__success;
204

    
205
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
206
                      "] read failed %d : %d = %s\n",
207
                      s->fd, bs->filename, offset, buf, count,
208
                      bs->total_sectors, ret, errno, strerror(errno));
209

    
210
    /* Try harder for CDrom. */
211
    if (bs->type == BDRV_TYPE_CDROM) {
212
        lseek(s->fd, offset, SEEK_SET);
213
        ret = read(s->fd, buf, count);
214
        if (ret == count)
215
            goto label__raw_read__success;
216
        lseek(s->fd, offset, SEEK_SET);
217
        ret = read(s->fd, buf, count);
218
        if (ret == count)
219
            goto label__raw_read__success;
220

    
221
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
222
                          "] retry read failed %d : %d = %s\n",
223
                          s->fd, bs->filename, offset, buf, count,
224
                          bs->total_sectors, ret, errno, strerror(errno));
225
    }
226

    
227
label__raw_read__success:
228

    
229
    return ret;
230
}
231

    
232
/*
233
 * offset and count are in bytes, but must be multiples of 512 for files
234
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
235
 *
236
 * This function may be called without alignment if the caller ensures
237
 * that O_DIRECT is not in effect.
238
 */
239
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
240
                      const uint8_t *buf, int count)
241
{
242
    BDRVRawState *s = bs->opaque;
243
    int ret;
244

    
245
    ret = fd_open(bs);
246
    if (ret < 0)
247
        return ret;
248

    
249
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
250
        ++(s->lseek_err_cnt);
251
        if(s->lseek_err_cnt) {
252
            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
253
                              PRId64 "] lseek failed : %d = %s\n",
254
                              s->fd, bs->filename, offset, buf, count,
255
                              bs->total_sectors, errno, strerror(errno));
256
        }
257
        return -1;
258
    }
259
    s->lseek_err_cnt = 0;
260

    
261
    ret = write(s->fd, buf, count);
262
    if (ret == count)
263
        goto label__raw_write__success;
264

    
265
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
266
                      "] write failed %d : %d = %s\n",
267
                      s->fd, bs->filename, offset, buf, count,
268
                      bs->total_sectors, ret, errno, strerror(errno));
269

    
270
label__raw_write__success:
271

    
272
    return ret;
273
}
274

    
275

    
276
#if defined(O_DIRECT)
277
/*
278
 * offset and count are in bytes and possibly not aligned. For files opened
279
 * with O_DIRECT, necessary alignments are ensured before calling
280
 * raw_pread_aligned to do the actual read.
281
 */
282
static int raw_pread(BlockDriverState *bs, int64_t offset,
283
                     uint8_t *buf, int count)
284
{
285
    BDRVRawState *s = bs->opaque;
286
    int size, ret, shift, sum;
287

    
288
    sum = 0;
289

    
290
    if (s->aligned_buf != NULL)  {
291

    
292
        if (offset & 0x1ff) {
293
            /* align offset on a 512 bytes boundary */
294

    
295
            shift = offset & 0x1ff;
296
            size = (shift + count + 0x1ff) & ~0x1ff;
297
            if (size > ALIGNED_BUFFER_SIZE)
298
                size = ALIGNED_BUFFER_SIZE;
299
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
300
            if (ret < 0)
301
                return ret;
302

    
303
            size = 512 - shift;
304
            if (size > count)
305
                size = count;
306
            memcpy(buf, s->aligned_buf + shift, size);
307

    
308
            buf += size;
309
            offset += size;
310
            count -= size;
311
            sum += size;
312

    
313
            if (count == 0)
314
                return sum;
315
        }
316
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
317

    
318
            /* read on aligned buffer */
319

    
320
            while (count) {
321

    
322
                size = (count + 0x1ff) & ~0x1ff;
323
                if (size > ALIGNED_BUFFER_SIZE)
324
                    size = ALIGNED_BUFFER_SIZE;
325

    
326
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
327
                if (ret < 0)
328
                    return ret;
329

    
330
                size = ret;
331
                if (size > count)
332
                    size = count;
333

    
334
                memcpy(buf, s->aligned_buf, size);
335

    
336
                buf += size;
337
                offset += size;
338
                count -= size;
339
                sum += size;
340
            }
341

    
342
            return sum;
343
        }
344
    }
345

    
346
    return raw_pread_aligned(bs, offset, buf, count) + sum;
347
}
348

    
349
/*
350
 * offset and count are in bytes and possibly not aligned. For files opened
351
 * with O_DIRECT, necessary alignments are ensured before calling
352
 * raw_pwrite_aligned to do the actual write.
353
 */
354
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
355
                      const uint8_t *buf, int count)
356
{
357
    BDRVRawState *s = bs->opaque;
358
    int size, ret, shift, sum;
359

    
360
    sum = 0;
361

    
362
    if (s->aligned_buf != NULL) {
363

    
364
        if (offset & 0x1ff) {
365
            /* align offset on a 512 bytes boundary */
366
            shift = offset & 0x1ff;
367
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
368
            if (ret < 0)
369
                return ret;
370

    
371
            size = 512 - shift;
372
            if (size > count)
373
                size = count;
374
            memcpy(s->aligned_buf + shift, buf, size);
375

    
376
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
377
            if (ret < 0)
378
                return ret;
379

    
380
            buf += size;
381
            offset += size;
382
            count -= size;
383
            sum += size;
384

    
385
            if (count == 0)
386
                return sum;
387
        }
388
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
389

    
390
            while ((size = (count & ~0x1ff)) != 0) {
391

    
392
                if (size > ALIGNED_BUFFER_SIZE)
393
                    size = ALIGNED_BUFFER_SIZE;
394

    
395
                memcpy(s->aligned_buf, buf, size);
396

    
397
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
398
                if (ret < 0)
399
                    return ret;
400

    
401
                buf += ret;
402
                offset += ret;
403
                count -= ret;
404
                sum += ret;
405
            }
406
            /* here, count < 512 because (count & ~0x1ff) == 0 */
407
            if (count) {
408
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
409
                if (ret < 0)
410
                    return ret;
411
                 memcpy(s->aligned_buf, buf, count);
412

    
413
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
414
                 if (ret < 0)
415
                     return ret;
416
                 if (count < ret)
417
                     ret = count;
418

    
419
                 sum += ret;
420
            }
421
            return sum;
422
        }
423
    }
424
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
425
}
426

    
427
#else
428
#define raw_pread raw_pread_aligned
429
#define raw_pwrite raw_pwrite_aligned
430
#endif
431

    
432

    
433
#ifdef CONFIG_AIO
434
/***********************************************************/
435
/* Unix AIO using POSIX AIO */
436

    
437
typedef struct RawAIOCB {
438
    BlockDriverAIOCB common;
439
    struct aiocb aiocb;
440
    struct RawAIOCB *next;
441
    int ret;
442
} RawAIOCB;
443

    
444
typedef struct PosixAioState
445
{
446
    int fd;
447
    RawAIOCB *first_aio;
448
} PosixAioState;
449

    
450
static void posix_aio_read(void *opaque)
451
{
452
    PosixAioState *s = opaque;
453
    RawAIOCB *acb, **pacb;
454
    int ret;
455
    size_t offset;
456
    union {
457
        struct qemu_signalfd_siginfo siginfo;
458
        char buf[128];
459
    } sig;
460

    
461
    /* try to read from signalfd, don't freak out if we can't read anything */
462
    offset = 0;
463
    while (offset < 128) {
464
        ssize_t len;
465

    
466
        len = read(s->fd, sig.buf + offset, 128 - offset);
467
        if (len == -1 && errno == EINTR)
468
            continue;
469
        if (len == -1 && errno == EAGAIN) {
470
            /* there is no natural reason for this to happen,
471
             * so we'll spin hard until we get everything just
472
             * to be on the safe side. */
473
            if (offset > 0)
474
                continue;
475
        }
476

    
477
        offset += len;
478
    }
479

    
480
    for(;;) {
481
        pacb = &s->first_aio;
482
        for(;;) {
483
            acb = *pacb;
484
            if (!acb)
485
                goto the_end;
486
            ret = aio_error(&acb->aiocb);
487
            if (ret == ECANCELED) {
488
                /* remove the request */
489
                *pacb = acb->next;
490
                qemu_aio_release(acb);
491
            } else if (ret != EINPROGRESS) {
492
                /* end of aio */
493
                if (ret == 0) {
494
                    ret = aio_return(&acb->aiocb);
495
                    if (ret == acb->aiocb.aio_nbytes)
496
                        ret = 0;
497
                    else
498
                        ret = -EINVAL;
499
                } else {
500
                    ret = -ret;
501
                }
502
                /* remove the request */
503
                *pacb = acb->next;
504
                /* call the callback */
505
                acb->common.cb(acb->common.opaque, ret);
506
                qemu_aio_release(acb);
507
                break;
508
            } else {
509
                pacb = &acb->next;
510
            }
511
        }
512
    }
513
 the_end: ;
514
}
515

    
516
static int posix_aio_flush(void *opaque)
517
{
518
    PosixAioState *s = opaque;
519
    return !!s->first_aio;
520
}
521

    
522
static PosixAioState *posix_aio_state;
523

    
524
static int posix_aio_init(void)
525
{
526
    sigset_t mask;
527
    PosixAioState *s;
528
  
529
    if (posix_aio_state)
530
        return 0;
531

    
532
    s = qemu_malloc(sizeof(PosixAioState));
533
    if (s == NULL)
534
        return -ENOMEM;
535

    
536
    /* Make sure to block AIO signal */
537
    sigemptyset(&mask);
538
    sigaddset(&mask, SIGUSR2);
539
    sigprocmask(SIG_BLOCK, &mask, NULL);
540
    
541
    s->first_aio = NULL;
542
    s->fd = qemu_signalfd(&mask);
543

    
544
    fcntl(s->fd, F_SETFL, O_NONBLOCK);
545

    
546
    qemu_aio_set_fd_handler(s->fd, posix_aio_read, NULL, posix_aio_flush, s);
547

    
548
#if defined(__GLIBC__) && defined(__linux__)
549
    {
550
        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
551
           seems to fix the problem. */
552
        struct aioinit ai;
553
        memset(&ai, 0, sizeof(ai));
554
        ai.aio_threads = 1;
555
        ai.aio_num = 1;
556
        ai.aio_idle_time = 365 * 100000;
557
        aio_init(&ai);
558
    }
559
#endif
560
    posix_aio_state = s;
561

    
562
    return 0;
563
}
564

    
565
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
566
        int64_t sector_num, uint8_t *buf, int nb_sectors,
567
        BlockDriverCompletionFunc *cb, void *opaque)
568
{
569
    BDRVRawState *s = bs->opaque;
570
    RawAIOCB *acb;
571

    
572
    if (fd_open(bs) < 0)
573
        return NULL;
574

    
575
    acb = qemu_aio_get(bs, cb, opaque);
576
    if (!acb)
577
        return NULL;
578
    acb->aiocb.aio_fildes = s->fd;
579
    acb->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
580
    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
581
    acb->aiocb.aio_buf = buf;
582
    if (nb_sectors < 0)
583
        acb->aiocb.aio_nbytes = -nb_sectors;
584
    else
585
        acb->aiocb.aio_nbytes = nb_sectors * 512;
586
    acb->aiocb.aio_offset = sector_num * 512;
587
    acb->next = posix_aio_state->first_aio;
588
    posix_aio_state->first_aio = acb;
589
    return acb;
590
}
591

    
592
static void raw_aio_em_cb(void* opaque)
593
{
594
    RawAIOCB *acb = opaque;
595
    acb->common.cb(acb->common.opaque, acb->ret);
596
    qemu_aio_release(acb);
597
}
598

    
599
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
600
        int64_t sector_num, uint8_t *buf, int nb_sectors,
601
        BlockDriverCompletionFunc *cb, void *opaque)
602
{
603
    RawAIOCB *acb;
604

    
605
    /*
606
     * If O_DIRECT is used and the buffer is not aligned fall back
607
     * to synchronous IO.
608
     */
609
#if defined(O_DIRECT)
610
    BDRVRawState *s = bs->opaque;
611

    
612
    if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
613
        QEMUBH *bh;
614
        acb = qemu_aio_get(bs, cb, opaque);
615
        acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors);
616
        bh = qemu_bh_new(raw_aio_em_cb, acb);
617
        qemu_bh_schedule(bh);
618
        return &acb->common;
619
    }
620
#endif
621

    
622
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
623
    if (!acb)
624
        return NULL;
625
    if (aio_read(&acb->aiocb) < 0) {
626
        qemu_aio_release(acb);
627
        return NULL;
628
    }
629
    return &acb->common;
630
}
631

    
632
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
633
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
634
        BlockDriverCompletionFunc *cb, void *opaque)
635
{
636
    RawAIOCB *acb;
637

    
638
    /*
639
     * If O_DIRECT is used and the buffer is not aligned fall back
640
     * to synchronous IO.
641
     */
642
#if defined(O_DIRECT)
643
    BDRVRawState *s = bs->opaque;
644

    
645
    if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
646
        QEMUBH *bh;
647
        acb = qemu_aio_get(bs, cb, opaque);
648
        acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors);
649
        bh = qemu_bh_new(raw_aio_em_cb, acb);
650
        qemu_bh_schedule(bh);
651
        return &acb->common;
652
    }
653
#endif
654

    
655
    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
656
    if (!acb)
657
        return NULL;
658
    if (aio_write(&acb->aiocb) < 0) {
659
        qemu_aio_release(acb);
660
        return NULL;
661
    }
662
    return &acb->common;
663
}
664

    
665
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
666
{
667
    int ret;
668
    RawAIOCB *acb = (RawAIOCB *)blockacb;
669
    RawAIOCB **pacb;
670

    
671
    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
672
    if (ret == AIO_NOTCANCELED) {
673
        /* fail safe: if the aio could not be canceled, we wait for
674
           it */
675
        while (aio_error(&acb->aiocb) == EINPROGRESS);
676
    }
677

    
678
    /* remove the callback from the queue */
679
    pacb = &posix_aio_state->first_aio;
680
    for(;;) {
681
        if (*pacb == NULL) {
682
            break;
683
        } else if (*pacb == acb) {
684
            *pacb = acb->next;
685
            qemu_aio_release(acb);
686
            break;
687
        }
688
        pacb = &acb->next;
689
    }
690
}
691

    
692
#else /* CONFIG_AIO */
693
static int posix_aio_init(void)
694
{
695
}
696
#endif /* CONFIG_AIO */
697

    
698
static void raw_close(BlockDriverState *bs)
699
{
700
    BDRVRawState *s = bs->opaque;
701
    if (s->fd >= 0) {
702
        close(s->fd);
703
        s->fd = -1;
704
#if defined(O_DIRECT)
705
        if (s->aligned_buf != NULL)
706
            qemu_free(s->aligned_buf);
707
#endif
708
    }
709
}
710

    
711
static int raw_truncate(BlockDriverState *bs, int64_t offset)
712
{
713
    BDRVRawState *s = bs->opaque;
714
    if (s->type != FTYPE_FILE)
715
        return -ENOTSUP;
716
    if (ftruncate(s->fd, offset) < 0)
717
        return -errno;
718
    return 0;
719
}
720

    
721
#ifdef __OpenBSD__
722
static int64_t raw_getlength(BlockDriverState *bs)
723
{
724
    BDRVRawState *s = bs->opaque;
725
    int fd = s->fd;
726
    struct stat st;
727

    
728
    if (fstat(fd, &st))
729
        return -1;
730
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
731
        struct disklabel dl;
732

    
733
        if (ioctl(fd, DIOCGDINFO, &dl))
734
            return -1;
735
        return (uint64_t)dl.d_secsize *
736
            dl.d_partitions[DISKPART(st.st_rdev)].p_size;
737
    } else
738
        return st.st_size;
739
}
740
#else /* !__OpenBSD__ */
741
static int64_t  raw_getlength(BlockDriverState *bs)
742
{
743
    BDRVRawState *s = bs->opaque;
744
    int fd = s->fd;
745
    int64_t size;
746
#ifdef _BSD
747
    struct stat sb;
748
#endif
749
#ifdef __sun__
750
    struct dk_minfo minfo;
751
    int rv;
752
#endif
753
    int ret;
754

    
755
    ret = fd_open(bs);
756
    if (ret < 0)
757
        return ret;
758

    
759
#ifdef _BSD
760
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
761
#ifdef DIOCGMEDIASIZE
762
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
763
#endif
764
#ifdef CONFIG_COCOA
765
        size = LONG_LONG_MAX;
766
#else
767
        size = lseek(fd, 0LL, SEEK_END);
768
#endif
769
    } else
770
#endif
771
#ifdef __sun__
772
    /*
773
     * use the DKIOCGMEDIAINFO ioctl to read the size.
774
     */
775
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
776
    if ( rv != -1 ) {
777
        size = minfo.dki_lbsize * minfo.dki_capacity;
778
    } else /* there are reports that lseek on some devices
779
              fails, but irc discussion said that contingency
780
              on contingency was overkill */
781
#endif
782
    {
783
        size = lseek(fd, 0, SEEK_END);
784
    }
785
    return size;
786
}
787
#endif
788

    
789
static int raw_create(const char *filename, int64_t total_size,
790
                      const char *backing_file, int flags)
791
{
792
    int fd;
793

    
794
    if (flags || backing_file)
795
        return -ENOTSUP;
796

    
797
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
798
              0644);
799
    if (fd < 0)
800
        return -EIO;
801
    ftruncate(fd, total_size * 512);
802
    close(fd);
803
    return 0;
804
}
805

    
806
static void raw_flush(BlockDriverState *bs)
807
{
808
    BDRVRawState *s = bs->opaque;
809
    fsync(s->fd);
810
}
811

    
812
BlockDriver bdrv_raw = {
813
    "raw",
814
    sizeof(BDRVRawState),
815
    NULL, /* no probe for protocols */
816
    raw_open,
817
    NULL,
818
    NULL,
819
    raw_close,
820
    raw_create,
821
    raw_flush,
822

    
823
#ifdef CONFIG_AIO
824
    .bdrv_aio_read = raw_aio_read,
825
    .bdrv_aio_write = raw_aio_write,
826
    .bdrv_aio_cancel = raw_aio_cancel,
827
    .aiocb_size = sizeof(RawAIOCB),
828
#endif
829
    .bdrv_pread = raw_pread,
830
    .bdrv_pwrite = raw_pwrite,
831
    .bdrv_truncate = raw_truncate,
832
    .bdrv_getlength = raw_getlength,
833
};
834

    
835
/***********************************************/
836
/* host device */
837

    
838
#ifdef CONFIG_COCOA
839
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
840
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
841

    
842
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
843
{
844
    kern_return_t       kernResult;
845
    mach_port_t     masterPort;
846
    CFMutableDictionaryRef  classesToMatch;
847

    
848
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
849
    if ( KERN_SUCCESS != kernResult ) {
850
        printf( "IOMasterPort returned %d\n", kernResult );
851
    }
852

    
853
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
854
    if ( classesToMatch == NULL ) {
855
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
856
    } else {
857
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
858
    }
859
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
860
    if ( KERN_SUCCESS != kernResult )
861
    {
862
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
863
    }
864

    
865
    return kernResult;
866
}
867

    
868
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
869
{
870
    io_object_t     nextMedia;
871
    kern_return_t   kernResult = KERN_FAILURE;
872
    *bsdPath = '\0';
873
    nextMedia = IOIteratorNext( mediaIterator );
874
    if ( nextMedia )
875
    {
876
        CFTypeRef   bsdPathAsCFString;
877
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
878
        if ( bsdPathAsCFString ) {
879
            size_t devPathLength;
880
            strcpy( bsdPath, _PATH_DEV );
881
            strcat( bsdPath, "r" );
882
            devPathLength = strlen( bsdPath );
883
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
884
                kernResult = KERN_SUCCESS;
885
            }
886
            CFRelease( bsdPathAsCFString );
887
        }
888
        IOObjectRelease( nextMedia );
889
    }
890

    
891
    return kernResult;
892
}
893

    
894
#endif
895

    
896
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
897
{
898
    BDRVRawState *s = bs->opaque;
899
    int fd, open_flags, ret;
900

    
901
    posix_aio_init();
902

    
903
#ifdef CONFIG_COCOA
904
    if (strstart(filename, "/dev/cdrom", NULL)) {
905
        kern_return_t kernResult;
906
        io_iterator_t mediaIterator;
907
        char bsdPath[ MAXPATHLEN ];
908
        int fd;
909

    
910
        kernResult = FindEjectableCDMedia( &mediaIterator );
911
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
912

    
913
        if ( bsdPath[ 0 ] != '\0' ) {
914
            strcat(bsdPath,"s0");
915
            /* some CDs don't have a partition 0 */
916
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
917
            if (fd < 0) {
918
                bsdPath[strlen(bsdPath)-1] = '1';
919
            } else {
920
                close(fd);
921
            }
922
            filename = bsdPath;
923
        }
924

    
925
        if ( mediaIterator )
926
            IOObjectRelease( mediaIterator );
927
    }
928
#endif
929
    open_flags = O_BINARY;
930
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
931
        open_flags |= O_RDWR;
932
    } else {
933
        open_flags |= O_RDONLY;
934
        bs->read_only = 1;
935
    }
936
#ifdef O_DIRECT
937
    if (flags & BDRV_O_DIRECT)
938
        open_flags |= O_DIRECT;
939
#endif
940

    
941
    s->type = FTYPE_FILE;
942
#if defined(__linux__)
943
    if (strstart(filename, "/dev/cd", NULL)) {
944
        /* open will not fail even if no CD is inserted */
945
        open_flags |= O_NONBLOCK;
946
        s->type = FTYPE_CD;
947
    } else if (strstart(filename, "/dev/fd", NULL)) {
948
        s->type = FTYPE_FD;
949
        s->fd_open_flags = open_flags;
950
        /* open will not fail even if no floppy is inserted */
951
        open_flags |= O_NONBLOCK;
952
    } else if (strstart(filename, "/dev/sg", NULL)) {
953
        bs->sg = 1;
954
    }
955
#endif
956
    fd = open(filename, open_flags, 0644);
957
    if (fd < 0) {
958
        ret = -errno;
959
        if (ret == -EROFS)
960
            ret = -EACCES;
961
        return ret;
962
    }
963
    s->fd = fd;
964
#if defined(__linux__)
965
    /* close fd so that we can reopen it as needed */
966
    if (s->type == FTYPE_FD) {
967
        close(s->fd);
968
        s->fd = -1;
969
        s->fd_media_changed = 1;
970
    }
971
#endif
972
    return 0;
973
}
974

    
975
#if defined(__linux__)
976

    
977
/* Note: we do not have a reliable method to detect if the floppy is
978
   present. The current method is to try to open the floppy at every
979
   I/O and to keep it opened during a few hundreds of ms. */
980
static int fd_open(BlockDriverState *bs)
981
{
982
    BDRVRawState *s = bs->opaque;
983
    int last_media_present;
984

    
985
    if (s->type != FTYPE_FD)
986
        return 0;
987
    last_media_present = (s->fd >= 0);
988
    if (s->fd >= 0 &&
989
        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
990
        close(s->fd);
991
        s->fd = -1;
992
#ifdef DEBUG_FLOPPY
993
        printf("Floppy closed\n");
994
#endif
995
    }
996
    if (s->fd < 0) {
997
        if (s->fd_got_error &&
998
            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
999
#ifdef DEBUG_FLOPPY
1000
            printf("No floppy (open delayed)\n");
1001
#endif
1002
            return -EIO;
1003
        }
1004
        s->fd = open(bs->filename, s->fd_open_flags);
1005
        if (s->fd < 0) {
1006
            s->fd_error_time = qemu_get_clock(rt_clock);
1007
            s->fd_got_error = 1;
1008
            if (last_media_present)
1009
                s->fd_media_changed = 1;
1010
#ifdef DEBUG_FLOPPY
1011
            printf("No floppy\n");
1012
#endif
1013
            return -EIO;
1014
        }
1015
#ifdef DEBUG_FLOPPY
1016
        printf("Floppy opened\n");
1017
#endif
1018
    }
1019
    if (!last_media_present)
1020
        s->fd_media_changed = 1;
1021
    s->fd_open_time = qemu_get_clock(rt_clock);
1022
    s->fd_got_error = 0;
1023
    return 0;
1024
}
1025

    
1026
static int raw_is_inserted(BlockDriverState *bs)
1027
{
1028
    BDRVRawState *s = bs->opaque;
1029
    int ret;
1030

    
1031
    switch(s->type) {
1032
    case FTYPE_CD:
1033
        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1034
        if (ret == CDS_DISC_OK)
1035
            return 1;
1036
        else
1037
            return 0;
1038
        break;
1039
    case FTYPE_FD:
1040
        ret = fd_open(bs);
1041
        return (ret >= 0);
1042
    default:
1043
        return 1;
1044
    }
1045
}
1046

    
1047
/* currently only used by fdc.c, but a CD version would be good too */
1048
static int raw_media_changed(BlockDriverState *bs)
1049
{
1050
    BDRVRawState *s = bs->opaque;
1051

    
1052
    switch(s->type) {
1053
    case FTYPE_FD:
1054
        {
1055
            int ret;
1056
            /* XXX: we do not have a true media changed indication. It
1057
               does not work if the floppy is changed without trying
1058
               to read it */
1059
            fd_open(bs);
1060
            ret = s->fd_media_changed;
1061
            s->fd_media_changed = 0;
1062
#ifdef DEBUG_FLOPPY
1063
            printf("Floppy changed=%d\n", ret);
1064
#endif
1065
            return ret;
1066
        }
1067
    default:
1068
        return -ENOTSUP;
1069
    }
1070
}
1071

    
1072
static int raw_eject(BlockDriverState *bs, int eject_flag)
1073
{
1074
    BDRVRawState *s = bs->opaque;
1075

    
1076
    switch(s->type) {
1077
    case FTYPE_CD:
1078
        if (eject_flag) {
1079
            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
1080
                perror("CDROMEJECT");
1081
        } else {
1082
            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
1083
                perror("CDROMEJECT");
1084
        }
1085
        break;
1086
    case FTYPE_FD:
1087
        {
1088
            int fd;
1089
            if (s->fd >= 0) {
1090
                close(s->fd);
1091
                s->fd = -1;
1092
            }
1093
            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
1094
            if (fd >= 0) {
1095
                if (ioctl(fd, FDEJECT, 0) < 0)
1096
                    perror("FDEJECT");
1097
                close(fd);
1098
            }
1099
        }
1100
        break;
1101
    default:
1102
        return -ENOTSUP;
1103
    }
1104
    return 0;
1105
}
1106

    
1107
static int raw_set_locked(BlockDriverState *bs, int locked)
1108
{
1109
    BDRVRawState *s = bs->opaque;
1110

    
1111
    switch(s->type) {
1112
    case FTYPE_CD:
1113
        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
1114
            /* Note: an error can happen if the distribution automatically
1115
               mounts the CD-ROM */
1116
            //        perror("CDROM_LOCKDOOR");
1117
        }
1118
        break;
1119
    default:
1120
        return -ENOTSUP;
1121
    }
1122
    return 0;
1123
}
1124

    
1125
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1126
{
1127
    BDRVRawState *s = bs->opaque;
1128

    
1129
    return ioctl(s->fd, req, buf);
1130
}
1131
#else
1132

    
1133
static int fd_open(BlockDriverState *bs)
1134
{
1135
    return 0;
1136
}
1137

    
1138
static int raw_is_inserted(BlockDriverState *bs)
1139
{
1140
    return 1;
1141
}
1142

    
1143
static int raw_media_changed(BlockDriverState *bs)
1144
{
1145
    return -ENOTSUP;
1146
}
1147

    
1148
static int raw_eject(BlockDriverState *bs, int eject_flag)
1149
{
1150
    return -ENOTSUP;
1151
}
1152

    
1153
static int raw_set_locked(BlockDriverState *bs, int locked)
1154
{
1155
    return -ENOTSUP;
1156
}
1157

    
1158
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1159
{
1160
    return -ENOTSUP;
1161
}
1162
#endif /* !linux */
1163

    
1164
BlockDriver bdrv_host_device = {
1165
    "host_device",
1166
    sizeof(BDRVRawState),
1167
    NULL, /* no probe for protocols */
1168
    hdev_open,
1169
    NULL,
1170
    NULL,
1171
    raw_close,
1172
    NULL,
1173
    raw_flush,
1174

    
1175
#ifdef CONFIG_AIO
1176
    .bdrv_aio_read = raw_aio_read,
1177
    .bdrv_aio_write = raw_aio_write,
1178
    .bdrv_aio_cancel = raw_aio_cancel,
1179
    .aiocb_size = sizeof(RawAIOCB),
1180
#endif
1181
    .bdrv_pread = raw_pread,
1182
    .bdrv_pwrite = raw_pwrite,
1183
    .bdrv_getlength = raw_getlength,
1184

    
1185
    /* removable device support */
1186
    .bdrv_is_inserted = raw_is_inserted,
1187
    .bdrv_media_changed = raw_media_changed,
1188
    .bdrv_eject = raw_eject,
1189
    .bdrv_set_locked = raw_set_locked,
1190
    /* generic scsi device */
1191
    .bdrv_ioctl = raw_ioctl,
1192
};