Statistics
| Branch: | Revision:

root / block-raw-posix.c @ 9b32d5a5

History | View | Annotate | Download (32.6 kB)

1 83f64091 bellard
/*
2 223d4670 ths
 * Block driver for RAW files (posix)
3 5fafdf24 ths
 *
4 83f64091 bellard
 * Copyright (c) 2006 Fabrice Bellard
5 5fafdf24 ths
 *
6 83f64091 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 83f64091 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 83f64091 bellard
 * in the Software without restriction, including without limitation the rights
9 83f64091 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 83f64091 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 83f64091 bellard
 * furnished to do so, subject to the following conditions:
12 83f64091 bellard
 *
13 83f64091 bellard
 * The above copyright notice and this permission notice shall be included in
14 83f64091 bellard
 * all copies or substantial portions of the Software.
15 83f64091 bellard
 *
16 83f64091 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 83f64091 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 83f64091 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 83f64091 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 83f64091 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 83f64091 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 83f64091 bellard
 * THE SOFTWARE.
23 83f64091 bellard
 */
24 faf07963 pbrook
#include "qemu-common.h"
25 87ecb68b pbrook
#include "qemu-timer.h"
26 baf35cb9 aliguori
#include "qemu-char.h"
27 83f64091 bellard
#include "block_int.h"
28 83f64091 bellard
#include <assert.h>
29 414f0dab blueswir1
#ifdef CONFIG_AIO
30 83f64091 bellard
#include <aio.h>
31 414f0dab blueswir1
#endif
32 83f64091 bellard
33 83f64091 bellard
#ifdef CONFIG_COCOA
34 83f64091 bellard
#include <paths.h>
35 83f64091 bellard
#include <sys/param.h>
36 83f64091 bellard
#include <IOKit/IOKitLib.h>
37 83f64091 bellard
#include <IOKit/IOBSD.h>
38 83f64091 bellard
#include <IOKit/storage/IOMediaBSDClient.h>
39 83f64091 bellard
#include <IOKit/storage/IOMedia.h>
40 83f64091 bellard
#include <IOKit/storage/IOCDMedia.h>
41 83f64091 bellard
//#include <IOKit/storage/IOCDTypes.h>
42 83f64091 bellard
#include <CoreFoundation/CoreFoundation.h>
43 83f64091 bellard
#endif
44 83f64091 bellard
45 83f64091 bellard
#ifdef __sun__
46 2e9671da ths
#define _POSIX_PTHREAD_SEMANTICS 1
47 2e9671da ths
#include <signal.h>
48 83f64091 bellard
#include <sys/dkio.h>
49 83f64091 bellard
#endif
50 19cb3738 bellard
#ifdef __linux__
51 19cb3738 bellard
#include <sys/ioctl.h>
52 19cb3738 bellard
#include <linux/cdrom.h>
53 19cb3738 bellard
#include <linux/fd.h>
54 19cb3738 bellard
#endif
55 1cb6c3fd ths
#ifdef __FreeBSD__
56 543952ca blueswir1
#include <signal.h>
57 1cb6c3fd ths
#include <sys/disk.h>
58 1cb6c3fd ths
#endif
59 83f64091 bellard
60 128ab2ff blueswir1
#ifdef __OpenBSD__
61 128ab2ff blueswir1
#include <sys/ioctl.h>
62 128ab2ff blueswir1
#include <sys/disklabel.h>
63 128ab2ff blueswir1
#include <sys/dkio.h>
64 128ab2ff blueswir1
#endif
65 128ab2ff blueswir1
66 19cb3738 bellard
//#define DEBUG_FLOPPY
67 83f64091 bellard
68 faf07963 pbrook
//#define DEBUG_BLOCK
69 03ff3ca3 aliguori
#if defined(DEBUG_BLOCK)
70 a50a6282 balrog
#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)        \
71 2e03286b balrog
    { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
72 8c05dbf9 ths
#else
73 8c05dbf9 ths
#define DEBUG_BLOCK_PRINT(formatCstr, args...)
74 8c05dbf9 ths
#endif
75 8c05dbf9 ths
76 f6465578 aliguori
/* OS X does not have O_DSYNC */
77 f6465578 aliguori
#ifndef O_DSYNC
78 7ab064d2 aliguori
#define O_DSYNC O_SYNC
79 f6465578 aliguori
#endif
80 f6465578 aliguori
81 9f7965c7 aliguori
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
82 9f7965c7 aliguori
#ifndef O_DIRECT
83 9f7965c7 aliguori
#define O_DIRECT O_DSYNC
84 9f7965c7 aliguori
#endif
85 9f7965c7 aliguori
86 19cb3738 bellard
#define FTYPE_FILE   0
87 19cb3738 bellard
#define FTYPE_CD     1
88 19cb3738 bellard
#define FTYPE_FD     2
89 83f64091 bellard
90 bed5cc52 bellard
#define ALIGNED_BUFFER_SIZE (32 * 512)
91 bed5cc52 bellard
92 19cb3738 bellard
/* if the FD is not accessed during that time (in ms), we try to
93 19cb3738 bellard
   reopen it to see if the disk has been changed */
94 19cb3738 bellard
#define FD_OPEN_TIMEOUT 1000
95 83f64091 bellard
96 53538725 aliguori
/* posix-aio doesn't allow multiple outstanding requests to a single file
97 53538725 aliguori
 * descriptor.  we implement a pool of dup()'d file descriptors to work
98 53538725 aliguori
 * around this */
99 53538725 aliguori
#define RAW_FD_POOL_SIZE        64
100 53538725 aliguori
101 19cb3738 bellard
typedef struct BDRVRawState {
102 19cb3738 bellard
    int fd;
103 19cb3738 bellard
    int type;
104 8c05dbf9 ths
    unsigned int lseek_err_cnt;
105 53538725 aliguori
    int fd_pool[RAW_FD_POOL_SIZE];
106 19cb3738 bellard
#if defined(__linux__)
107 19cb3738 bellard
    /* linux floppy specific */
108 6dd2db52 blueswir1
    int fd_open_flags;
109 19cb3738 bellard
    int64_t fd_open_time;
110 19cb3738 bellard
    int64_t fd_error_time;
111 19cb3738 bellard
    int fd_got_error;
112 19cb3738 bellard
    int fd_media_changed;
113 83f64091 bellard
#endif
114 bed5cc52 bellard
    uint8_t* aligned_buf;
115 19cb3738 bellard
} BDRVRawState;
116 19cb3738 bellard
117 a76bab49 aliguori
static int posix_aio_init(void);
118 a76bab49 aliguori
119 19cb3738 bellard
static int fd_open(BlockDriverState *bs);
120 83f64091 bellard
121 83f64091 bellard
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
122 83f64091 bellard
{
123 83f64091 bellard
    BDRVRawState *s = bs->opaque;
124 19cb3738 bellard
    int fd, open_flags, ret;
125 53538725 aliguori
    int i;
126 83f64091 bellard
127 a76bab49 aliguori
    posix_aio_init();
128 a76bab49 aliguori
129 8c05dbf9 ths
    s->lseek_err_cnt = 0;
130 8c05dbf9 ths
131 83f64091 bellard
    open_flags = O_BINARY;
132 83f64091 bellard
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
133 83f64091 bellard
        open_flags |= O_RDWR;
134 83f64091 bellard
    } else {
135 83f64091 bellard
        open_flags |= O_RDONLY;
136 83f64091 bellard
        bs->read_only = 1;
137 83f64091 bellard
    }
138 83f64091 bellard
    if (flags & BDRV_O_CREAT)
139 83f64091 bellard
        open_flags |= O_CREAT | O_TRUNC;
140 9f7965c7 aliguori
141 9f7965c7 aliguori
    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
142 9f7965c7 aliguori
     * and O_DIRECT for no caching. */
143 9f7965c7 aliguori
    if ((flags & BDRV_O_NOCACHE))
144 33f00271 balrog
        open_flags |= O_DIRECT;
145 9f7965c7 aliguori
    else if (!(flags & BDRV_O_CACHE_WB))
146 9f7965c7 aliguori
        open_flags |= O_DSYNC;
147 83f64091 bellard
148 19cb3738 bellard
    s->type = FTYPE_FILE;
149 19cb3738 bellard
150 83f64091 bellard
    fd = open(filename, open_flags, 0644);
151 19cb3738 bellard
    if (fd < 0) {
152 19cb3738 bellard
        ret = -errno;
153 19cb3738 bellard
        if (ret == -EROFS)
154 19cb3738 bellard
            ret = -EACCES;
155 19cb3738 bellard
        return ret;
156 19cb3738 bellard
    }
157 83f64091 bellard
    s->fd = fd;
158 53538725 aliguori
    for (i = 0; i < RAW_FD_POOL_SIZE; i++)
159 53538725 aliguori
        s->fd_pool[i] = -1;
160 bed5cc52 bellard
    s->aligned_buf = NULL;
161 9f7965c7 aliguori
    if ((flags & BDRV_O_NOCACHE)) {
162 bed5cc52 bellard
        s->aligned_buf = qemu_memalign(512, ALIGNED_BUFFER_SIZE);
163 bed5cc52 bellard
        if (s->aligned_buf == NULL) {
164 bed5cc52 bellard
            ret = -errno;
165 bed5cc52 bellard
            close(fd);
166 bed5cc52 bellard
            return ret;
167 bed5cc52 bellard
        }
168 bed5cc52 bellard
    }
169 83f64091 bellard
    return 0;
170 83f64091 bellard
}
171 83f64091 bellard
172 83f64091 bellard
/* XXX: use host sector size if necessary with:
173 83f64091 bellard
#ifdef DIOCGSECTORSIZE
174 83f64091 bellard
        {
175 83f64091 bellard
            unsigned int sectorsize = 512;
176 83f64091 bellard
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
177 83f64091 bellard
                sectorsize > bufsize)
178 83f64091 bellard
                bufsize = sectorsize;
179 83f64091 bellard
        }
180 83f64091 bellard
#endif
181 83f64091 bellard
#ifdef CONFIG_COCOA
182 83f64091 bellard
        u_int32_t   blockSize = 512;
183 83f64091 bellard
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
184 83f64091 bellard
            bufsize = blockSize;
185 83f64091 bellard
        }
186 83f64091 bellard
#endif
187 83f64091 bellard
*/
188 83f64091 bellard
189 bed5cc52 bellard
/*
190 bed5cc52 bellard
 * offset and count are in bytes, but must be multiples of 512 for files
191 bed5cc52 bellard
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
192 bed5cc52 bellard
 *
193 bed5cc52 bellard
 * This function may be called without alignment if the caller ensures
194 bed5cc52 bellard
 * that O_DIRECT is not in effect.
195 bed5cc52 bellard
 */
196 bed5cc52 bellard
static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
197 83f64091 bellard
                     uint8_t *buf, int count)
198 83f64091 bellard
{
199 83f64091 bellard
    BDRVRawState *s = bs->opaque;
200 83f64091 bellard
    int ret;
201 3b46e624 ths
202 19cb3738 bellard
    ret = fd_open(bs);
203 19cb3738 bellard
    if (ret < 0)
204 19cb3738 bellard
        return ret;
205 19cb3738 bellard
206 985a03b0 ths
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
207 8c05dbf9 ths
        ++(s->lseek_err_cnt);
208 8c05dbf9 ths
        if(s->lseek_err_cnt <= 10) {
209 92868412 j_mayer
            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
210 92868412 j_mayer
                              "] lseek failed : %d = %s\n",
211 8c05dbf9 ths
                              s->fd, bs->filename, offset, buf, count,
212 8c05dbf9 ths
                              bs->total_sectors, errno, strerror(errno));
213 8c05dbf9 ths
        }
214 8c05dbf9 ths
        return -1;
215 8c05dbf9 ths
    }
216 8c05dbf9 ths
    s->lseek_err_cnt=0;
217 8c05dbf9 ths
218 83f64091 bellard
    ret = read(s->fd, buf, count);
219 8c05dbf9 ths
    if (ret == count)
220 8c05dbf9 ths
        goto label__raw_read__success;
221 8c05dbf9 ths
222 92868412 j_mayer
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
223 92868412 j_mayer
                      "] read failed %d : %d = %s\n",
224 8c05dbf9 ths
                      s->fd, bs->filename, offset, buf, count,
225 8c05dbf9 ths
                      bs->total_sectors, ret, errno, strerror(errno));
226 8c05dbf9 ths
227 8c05dbf9 ths
    /* Try harder for CDrom. */
228 8c05dbf9 ths
    if (bs->type == BDRV_TYPE_CDROM) {
229 8c05dbf9 ths
        lseek(s->fd, offset, SEEK_SET);
230 8c05dbf9 ths
        ret = read(s->fd, buf, count);
231 8c05dbf9 ths
        if (ret == count)
232 8c05dbf9 ths
            goto label__raw_read__success;
233 8c05dbf9 ths
        lseek(s->fd, offset, SEEK_SET);
234 8c05dbf9 ths
        ret = read(s->fd, buf, count);
235 8c05dbf9 ths
        if (ret == count)
236 8c05dbf9 ths
            goto label__raw_read__success;
237 8c05dbf9 ths
238 92868412 j_mayer
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
239 92868412 j_mayer
                          "] retry read failed %d : %d = %s\n",
240 8c05dbf9 ths
                          s->fd, bs->filename, offset, buf, count,
241 8c05dbf9 ths
                          bs->total_sectors, ret, errno, strerror(errno));
242 8c05dbf9 ths
    }
243 8c05dbf9 ths
244 8c05dbf9 ths
label__raw_read__success:
245 8c05dbf9 ths
246 83f64091 bellard
    return ret;
247 83f64091 bellard
}
248 83f64091 bellard
249 bed5cc52 bellard
/*
250 bed5cc52 bellard
 * offset and count are in bytes, but must be multiples of 512 for files
251 bed5cc52 bellard
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
252 bed5cc52 bellard
 *
253 bed5cc52 bellard
 * This function may be called without alignment if the caller ensures
254 bed5cc52 bellard
 * that O_DIRECT is not in effect.
255 bed5cc52 bellard
 */
256 bed5cc52 bellard
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
257 83f64091 bellard
                      const uint8_t *buf, int count)
258 83f64091 bellard
{
259 83f64091 bellard
    BDRVRawState *s = bs->opaque;
260 83f64091 bellard
    int ret;
261 3b46e624 ths
262 19cb3738 bellard
    ret = fd_open(bs);
263 19cb3738 bellard
    if (ret < 0)
264 19cb3738 bellard
        return ret;
265 19cb3738 bellard
266 985a03b0 ths
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
267 8c05dbf9 ths
        ++(s->lseek_err_cnt);
268 8c05dbf9 ths
        if(s->lseek_err_cnt) {
269 92868412 j_mayer
            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
270 92868412 j_mayer
                              PRId64 "] lseek failed : %d = %s\n",
271 8c05dbf9 ths
                              s->fd, bs->filename, offset, buf, count,
272 8c05dbf9 ths
                              bs->total_sectors, errno, strerror(errno));
273 8c05dbf9 ths
        }
274 8c05dbf9 ths
        return -1;
275 8c05dbf9 ths
    }
276 8c05dbf9 ths
    s->lseek_err_cnt = 0;
277 8c05dbf9 ths
278 83f64091 bellard
    ret = write(s->fd, buf, count);
279 8c05dbf9 ths
    if (ret == count)
280 8c05dbf9 ths
        goto label__raw_write__success;
281 8c05dbf9 ths
282 92868412 j_mayer
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
283 92868412 j_mayer
                      "] write failed %d : %d = %s\n",
284 8c05dbf9 ths
                      s->fd, bs->filename, offset, buf, count,
285 8c05dbf9 ths
                      bs->total_sectors, ret, errno, strerror(errno));
286 8c05dbf9 ths
287 8c05dbf9 ths
label__raw_write__success:
288 8c05dbf9 ths
289 83f64091 bellard
    return ret;
290 83f64091 bellard
}
291 83f64091 bellard
292 bed5cc52 bellard
293 bed5cc52 bellard
/*
294 bed5cc52 bellard
 * offset and count are in bytes and possibly not aligned. For files opened
295 bed5cc52 bellard
 * with O_DIRECT, necessary alignments are ensured before calling
296 bed5cc52 bellard
 * raw_pread_aligned to do the actual read.
297 bed5cc52 bellard
 */
298 bed5cc52 bellard
static int raw_pread(BlockDriverState *bs, int64_t offset,
299 bed5cc52 bellard
                     uint8_t *buf, int count)
300 bed5cc52 bellard
{
301 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
302 bed5cc52 bellard
    int size, ret, shift, sum;
303 bed5cc52 bellard
304 bed5cc52 bellard
    sum = 0;
305 bed5cc52 bellard
306 bed5cc52 bellard
    if (s->aligned_buf != NULL)  {
307 bed5cc52 bellard
308 bed5cc52 bellard
        if (offset & 0x1ff) {
309 bed5cc52 bellard
            /* align offset on a 512 bytes boundary */
310 bed5cc52 bellard
311 bed5cc52 bellard
            shift = offset & 0x1ff;
312 bed5cc52 bellard
            size = (shift + count + 0x1ff) & ~0x1ff;
313 bed5cc52 bellard
            if (size > ALIGNED_BUFFER_SIZE)
314 bed5cc52 bellard
                size = ALIGNED_BUFFER_SIZE;
315 bed5cc52 bellard
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
316 bed5cc52 bellard
            if (ret < 0)
317 bed5cc52 bellard
                return ret;
318 bed5cc52 bellard
319 bed5cc52 bellard
            size = 512 - shift;
320 bed5cc52 bellard
            if (size > count)
321 bed5cc52 bellard
                size = count;
322 bed5cc52 bellard
            memcpy(buf, s->aligned_buf + shift, size);
323 bed5cc52 bellard
324 bed5cc52 bellard
            buf += size;
325 bed5cc52 bellard
            offset += size;
326 bed5cc52 bellard
            count -= size;
327 bed5cc52 bellard
            sum += size;
328 bed5cc52 bellard
329 bed5cc52 bellard
            if (count == 0)
330 bed5cc52 bellard
                return sum;
331 bed5cc52 bellard
        }
332 bed5cc52 bellard
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
333 bed5cc52 bellard
334 bed5cc52 bellard
            /* read on aligned buffer */
335 bed5cc52 bellard
336 bed5cc52 bellard
            while (count) {
337 bed5cc52 bellard
338 bed5cc52 bellard
                size = (count + 0x1ff) & ~0x1ff;
339 bed5cc52 bellard
                if (size > ALIGNED_BUFFER_SIZE)
340 bed5cc52 bellard
                    size = ALIGNED_BUFFER_SIZE;
341 bed5cc52 bellard
342 bed5cc52 bellard
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
343 bed5cc52 bellard
                if (ret < 0)
344 bed5cc52 bellard
                    return ret;
345 bed5cc52 bellard
346 bed5cc52 bellard
                size = ret;
347 bed5cc52 bellard
                if (size > count)
348 bed5cc52 bellard
                    size = count;
349 bed5cc52 bellard
350 bed5cc52 bellard
                memcpy(buf, s->aligned_buf, size);
351 bed5cc52 bellard
352 bed5cc52 bellard
                buf += size;
353 bed5cc52 bellard
                offset += size;
354 bed5cc52 bellard
                count -= size;
355 bed5cc52 bellard
                sum += size;
356 bed5cc52 bellard
            }
357 bed5cc52 bellard
358 bed5cc52 bellard
            return sum;
359 bed5cc52 bellard
        }
360 bed5cc52 bellard
    }
361 bed5cc52 bellard
362 bed5cc52 bellard
    return raw_pread_aligned(bs, offset, buf, count) + sum;
363 bed5cc52 bellard
}
364 bed5cc52 bellard
365 bed5cc52 bellard
/*
366 bed5cc52 bellard
 * offset and count are in bytes and possibly not aligned. For files opened
367 bed5cc52 bellard
 * with O_DIRECT, necessary alignments are ensured before calling
368 bed5cc52 bellard
 * raw_pwrite_aligned to do the actual write.
369 bed5cc52 bellard
 */
370 bed5cc52 bellard
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
371 bed5cc52 bellard
                      const uint8_t *buf, int count)
372 bed5cc52 bellard
{
373 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
374 bed5cc52 bellard
    int size, ret, shift, sum;
375 bed5cc52 bellard
376 bed5cc52 bellard
    sum = 0;
377 bed5cc52 bellard
378 bed5cc52 bellard
    if (s->aligned_buf != NULL) {
379 bed5cc52 bellard
380 bed5cc52 bellard
        if (offset & 0x1ff) {
381 bed5cc52 bellard
            /* align offset on a 512 bytes boundary */
382 bed5cc52 bellard
            shift = offset & 0x1ff;
383 bed5cc52 bellard
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
384 bed5cc52 bellard
            if (ret < 0)
385 bed5cc52 bellard
                return ret;
386 bed5cc52 bellard
387 bed5cc52 bellard
            size = 512 - shift;
388 bed5cc52 bellard
            if (size > count)
389 bed5cc52 bellard
                size = count;
390 bed5cc52 bellard
            memcpy(s->aligned_buf + shift, buf, size);
391 bed5cc52 bellard
392 bed5cc52 bellard
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
393 bed5cc52 bellard
            if (ret < 0)
394 bed5cc52 bellard
                return ret;
395 bed5cc52 bellard
396 bed5cc52 bellard
            buf += size;
397 bed5cc52 bellard
            offset += size;
398 bed5cc52 bellard
            count -= size;
399 bed5cc52 bellard
            sum += size;
400 bed5cc52 bellard
401 bed5cc52 bellard
            if (count == 0)
402 bed5cc52 bellard
                return sum;
403 bed5cc52 bellard
        }
404 bed5cc52 bellard
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
405 bed5cc52 bellard
406 bed5cc52 bellard
            while ((size = (count & ~0x1ff)) != 0) {
407 bed5cc52 bellard
408 bed5cc52 bellard
                if (size > ALIGNED_BUFFER_SIZE)
409 bed5cc52 bellard
                    size = ALIGNED_BUFFER_SIZE;
410 bed5cc52 bellard
411 bed5cc52 bellard
                memcpy(s->aligned_buf, buf, size);
412 bed5cc52 bellard
413 bed5cc52 bellard
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
414 bed5cc52 bellard
                if (ret < 0)
415 bed5cc52 bellard
                    return ret;
416 bed5cc52 bellard
417 bed5cc52 bellard
                buf += ret;
418 bed5cc52 bellard
                offset += ret;
419 bed5cc52 bellard
                count -= ret;
420 bed5cc52 bellard
                sum += ret;
421 bed5cc52 bellard
            }
422 bed5cc52 bellard
            /* here, count < 512 because (count & ~0x1ff) == 0 */
423 bed5cc52 bellard
            if (count) {
424 bed5cc52 bellard
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
425 bed5cc52 bellard
                if (ret < 0)
426 bed5cc52 bellard
                    return ret;
427 bed5cc52 bellard
                 memcpy(s->aligned_buf, buf, count);
428 bed5cc52 bellard
429 bed5cc52 bellard
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
430 bed5cc52 bellard
                 if (ret < 0)
431 bed5cc52 bellard
                     return ret;
432 bed5cc52 bellard
                 if (count < ret)
433 bed5cc52 bellard
                     ret = count;
434 bed5cc52 bellard
435 bed5cc52 bellard
                 sum += ret;
436 bed5cc52 bellard
            }
437 bed5cc52 bellard
            return sum;
438 bed5cc52 bellard
        }
439 bed5cc52 bellard
    }
440 bed5cc52 bellard
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
441 bed5cc52 bellard
}
442 bed5cc52 bellard
443 414f0dab blueswir1
#ifdef CONFIG_AIO
444 83f64091 bellard
/***********************************************************/
445 19cb3738 bellard
/* Unix AIO using POSIX AIO */
446 83f64091 bellard
447 83f64091 bellard
typedef struct RawAIOCB {
448 ce1a14dc pbrook
    BlockDriverAIOCB common;
449 53538725 aliguori
    int fd;
450 83f64091 bellard
    struct aiocb aiocb;
451 ce1a14dc pbrook
    struct RawAIOCB *next;
452 bed5cc52 bellard
    int ret;
453 83f64091 bellard
} RawAIOCB;
454 83f64091 bellard
455 a76bab49 aliguori
typedef struct PosixAioState
456 a76bab49 aliguori
{
457 9e472e10 aliguori
    int rfd, wfd;
458 a76bab49 aliguori
    RawAIOCB *first_aio;
459 a76bab49 aliguori
} PosixAioState;
460 83f64091 bellard
461 53538725 aliguori
static int raw_fd_pool_get(BDRVRawState *s)
462 53538725 aliguori
{
463 53538725 aliguori
    int i;
464 53538725 aliguori
465 53538725 aliguori
    for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
466 53538725 aliguori
        /* already in use */
467 53538725 aliguori
        if (s->fd_pool[i] != -1)
468 53538725 aliguori
            continue;
469 53538725 aliguori
470 53538725 aliguori
        /* try to dup file descriptor */
471 53538725 aliguori
        s->fd_pool[i] = dup(s->fd);
472 53538725 aliguori
        if (s->fd_pool[i] != -1)
473 53538725 aliguori
            return s->fd_pool[i];
474 53538725 aliguori
    }
475 53538725 aliguori
476 53538725 aliguori
    /* we couldn't dup the file descriptor so just use the main one */
477 53538725 aliguori
    return s->fd;
478 53538725 aliguori
}
479 53538725 aliguori
480 53538725 aliguori
static void raw_fd_pool_put(RawAIOCB *acb)
481 53538725 aliguori
{
482 53538725 aliguori
    BDRVRawState *s = acb->common.bs->opaque;
483 53538725 aliguori
    int i;
484 53538725 aliguori
485 53538725 aliguori
    for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
486 53538725 aliguori
        if (s->fd_pool[i] == acb->fd) {
487 53538725 aliguori
            close(s->fd_pool[i]);
488 53538725 aliguori
            s->fd_pool[i] = -1;
489 53538725 aliguori
        }
490 53538725 aliguori
    }
491 53538725 aliguori
}
492 53538725 aliguori
493 a76bab49 aliguori
static void posix_aio_read(void *opaque)
494 83f64091 bellard
{
495 a76bab49 aliguori
    PosixAioState *s = opaque;
496 ce1a14dc pbrook
    RawAIOCB *acb, **pacb;
497 83f64091 bellard
    int ret;
498 9e472e10 aliguori
    ssize_t len;
499 9e472e10 aliguori
500 e20e830b aliguori
    /* read all bytes from signal pipe */
501 e20e830b aliguori
    for (;;) {
502 e20e830b aliguori
        char bytes[16];
503 9e472e10 aliguori
504 e20e830b aliguori
        len = read(s->rfd, bytes, sizeof(bytes));
505 2c41a5f9 aliguori
        if (len == -1 && errno == EINTR)
506 e20e830b aliguori
            continue; /* try again */
507 e20e830b aliguori
        if (len == sizeof(bytes))
508 e20e830b aliguori
            continue; /* more to read */
509 e20e830b aliguori
        break;
510 e20e830b aliguori
    }
511 83f64091 bellard
512 83f64091 bellard
    for(;;) {
513 a76bab49 aliguori
        pacb = &s->first_aio;
514 83f64091 bellard
        for(;;) {
515 83f64091 bellard
            acb = *pacb;
516 83f64091 bellard
            if (!acb)
517 83f64091 bellard
                goto the_end;
518 ce1a14dc pbrook
            ret = aio_error(&acb->aiocb);
519 83f64091 bellard
            if (ret == ECANCELED) {
520 83f64091 bellard
                /* remove the request */
521 ce1a14dc pbrook
                *pacb = acb->next;
522 53538725 aliguori
                raw_fd_pool_put(acb);
523 ce1a14dc pbrook
                qemu_aio_release(acb);
524 83f64091 bellard
            } else if (ret != EINPROGRESS) {
525 83f64091 bellard
                /* end of aio */
526 83f64091 bellard
                if (ret == 0) {
527 ce1a14dc pbrook
                    ret = aio_return(&acb->aiocb);
528 ce1a14dc pbrook
                    if (ret == acb->aiocb.aio_nbytes)
529 83f64091 bellard
                        ret = 0;
530 83f64091 bellard
                    else
531 19cb3738 bellard
                        ret = -EINVAL;
532 83f64091 bellard
                } else {
533 83f64091 bellard
                    ret = -ret;
534 83f64091 bellard
                }
535 83f64091 bellard
                /* remove the request */
536 ce1a14dc pbrook
                *pacb = acb->next;
537 83f64091 bellard
                /* call the callback */
538 ce1a14dc pbrook
                acb->common.cb(acb->common.opaque, ret);
539 53538725 aliguori
                raw_fd_pool_put(acb);
540 ce1a14dc pbrook
                qemu_aio_release(acb);
541 83f64091 bellard
                break;
542 83f64091 bellard
            } else {
543 ce1a14dc pbrook
                pacb = &acb->next;
544 83f64091 bellard
            }
545 83f64091 bellard
        }
546 83f64091 bellard
    }
547 83f64091 bellard
 the_end: ;
548 83f64091 bellard
}
549 83f64091 bellard
550 a76bab49 aliguori
static int posix_aio_flush(void *opaque)
551 baf35cb9 aliguori
{
552 a76bab49 aliguori
    PosixAioState *s = opaque;
553 a76bab49 aliguori
    return !!s->first_aio;
554 a76bab49 aliguori
}
555 a76bab49 aliguori
556 a76bab49 aliguori
static PosixAioState *posix_aio_state;
557 baf35cb9 aliguori
558 9e472e10 aliguori
static void aio_signal_handler(int signum)
559 9e472e10 aliguori
{
560 9e472e10 aliguori
    if (posix_aio_state) {
561 9e472e10 aliguori
        char byte = 0;
562 9e472e10 aliguori
563 9e472e10 aliguori
        write(posix_aio_state->wfd, &byte, sizeof(byte));
564 9e472e10 aliguori
    }
565 9e472e10 aliguori
566 9e472e10 aliguori
    qemu_service_io();
567 9e472e10 aliguori
}
568 9e472e10 aliguori
569 a76bab49 aliguori
static int posix_aio_init(void)
570 a76bab49 aliguori
{
571 9e472e10 aliguori
    struct sigaction act;
572 a76bab49 aliguori
    PosixAioState *s;
573 9e472e10 aliguori
    int fds[2];
574 a76bab49 aliguori
  
575 a76bab49 aliguori
    if (posix_aio_state)
576 a76bab49 aliguori
        return 0;
577 ad02ad6f aliguori
578 a76bab49 aliguori
    s = qemu_malloc(sizeof(PosixAioState));
579 a76bab49 aliguori
    if (s == NULL)
580 a76bab49 aliguori
        return -ENOMEM;
581 baf35cb9 aliguori
582 9e472e10 aliguori
    sigfillset(&act.sa_mask);
583 9e472e10 aliguori
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
584 9e472e10 aliguori
    act.sa_handler = aio_signal_handler;
585 9e472e10 aliguori
    sigaction(SIGUSR2, &act, NULL);
586 9e472e10 aliguori
587 a76bab49 aliguori
    s->first_aio = NULL;
588 9e472e10 aliguori
    if (pipe(fds) == -1) {
589 9e472e10 aliguori
        fprintf(stderr, "failed to create pipe\n");
590 27463101 aliguori
        return -errno;
591 27463101 aliguori
    }
592 2c41a5f9 aliguori
593 9e472e10 aliguori
    s->rfd = fds[0];
594 9e472e10 aliguori
    s->wfd = fds[1];
595 9e472e10 aliguori
596 e20e830b aliguori
    fcntl(s->rfd, F_SETFL, O_NONBLOCK);
597 9e472e10 aliguori
    fcntl(s->wfd, F_SETFL, O_NONBLOCK);
598 2c41a5f9 aliguori
599 9e472e10 aliguori
    qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
600 baf35cb9 aliguori
601 acce87f9 aliguori
#if defined(__linux__)
602 acce87f9 aliguori
    {
603 acce87f9 aliguori
        struct aioinit ai;
604 acce87f9 aliguori
605 acce87f9 aliguori
        memset(&ai, 0, sizeof(ai));
606 acce87f9 aliguori
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 4)
607 acce87f9 aliguori
        ai.aio_threads = 64;
608 acce87f9 aliguori
        ai.aio_num = 64;
609 997306fc aliguori
#else
610 acce87f9 aliguori
        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
611 acce87f9 aliguori
           seems to fix the problem. */
612 acce87f9 aliguori
        ai.aio_threads = 1;
613 acce87f9 aliguori
        ai.aio_num = 1;
614 acce87f9 aliguori
        ai.aio_idle_time = 365 * 100000;
615 acce87f9 aliguori
#endif
616 acce87f9 aliguori
        aio_init(&ai);
617 acce87f9 aliguori
    }
618 baf35cb9 aliguori
#endif
619 a76bab49 aliguori
    posix_aio_state = s;
620 6eb5733a bellard
621 a76bab49 aliguori
    return 0;
622 83f64091 bellard
}
623 83f64091 bellard
624 ce1a14dc pbrook
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
625 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
626 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
627 83f64091 bellard
{
628 ce1a14dc pbrook
    BDRVRawState *s = bs->opaque;
629 ce1a14dc pbrook
    RawAIOCB *acb;
630 ce1a14dc pbrook
631 19cb3738 bellard
    if (fd_open(bs) < 0)
632 19cb3738 bellard
        return NULL;
633 19cb3738 bellard
634 ce1a14dc pbrook
    acb = qemu_aio_get(bs, cb, opaque);
635 ce1a14dc pbrook
    if (!acb)
636 ce1a14dc pbrook
        return NULL;
637 53538725 aliguori
    acb->fd = raw_fd_pool_get(s);
638 53538725 aliguori
    acb->aiocb.aio_fildes = acb->fd;
639 a76bab49 aliguori
    acb->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
640 ce1a14dc pbrook
    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
641 ce1a14dc pbrook
    acb->aiocb.aio_buf = buf;
642 985a03b0 ths
    if (nb_sectors < 0)
643 985a03b0 ths
        acb->aiocb.aio_nbytes = -nb_sectors;
644 985a03b0 ths
    else
645 985a03b0 ths
        acb->aiocb.aio_nbytes = nb_sectors * 512;
646 ce1a14dc pbrook
    acb->aiocb.aio_offset = sector_num * 512;
647 a76bab49 aliguori
    acb->next = posix_aio_state->first_aio;
648 a76bab49 aliguori
    posix_aio_state->first_aio = acb;
649 ce1a14dc pbrook
    return acb;
650 83f64091 bellard
}
651 83f64091 bellard
652 bed5cc52 bellard
static void raw_aio_em_cb(void* opaque)
653 bed5cc52 bellard
{
654 bed5cc52 bellard
    RawAIOCB *acb = opaque;
655 bed5cc52 bellard
    acb->common.cb(acb->common.opaque, acb->ret);
656 bed5cc52 bellard
    qemu_aio_release(acb);
657 bed5cc52 bellard
}
658 bed5cc52 bellard
659 ce1a14dc pbrook
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
660 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
661 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
662 83f64091 bellard
{
663 ce1a14dc pbrook
    RawAIOCB *acb;
664 83f64091 bellard
665 bed5cc52 bellard
    /*
666 bed5cc52 bellard
     * If O_DIRECT is used and the buffer is not aligned fall back
667 bed5cc52 bellard
     * to synchronous IO.
668 bed5cc52 bellard
     */
669 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
670 bed5cc52 bellard
671 bed5cc52 bellard
    if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
672 bed5cc52 bellard
        QEMUBH *bh;
673 bed5cc52 bellard
        acb = qemu_aio_get(bs, cb, opaque);
674 bed5cc52 bellard
        acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors);
675 bed5cc52 bellard
        bh = qemu_bh_new(raw_aio_em_cb, acb);
676 bed5cc52 bellard
        qemu_bh_schedule(bh);
677 bed5cc52 bellard
        return &acb->common;
678 bed5cc52 bellard
    }
679 bed5cc52 bellard
680 ce1a14dc pbrook
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
681 ce1a14dc pbrook
    if (!acb)
682 ce1a14dc pbrook
        return NULL;
683 ce1a14dc pbrook
    if (aio_read(&acb->aiocb) < 0) {
684 ce1a14dc pbrook
        qemu_aio_release(acb);
685 ce1a14dc pbrook
        return NULL;
686 5fafdf24 ths
    }
687 ce1a14dc pbrook
    return &acb->common;
688 83f64091 bellard
}
689 83f64091 bellard
690 ce1a14dc pbrook
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
691 ce1a14dc pbrook
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
692 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
693 83f64091 bellard
{
694 ce1a14dc pbrook
    RawAIOCB *acb;
695 83f64091 bellard
696 bed5cc52 bellard
    /*
697 bed5cc52 bellard
     * If O_DIRECT is used and the buffer is not aligned fall back
698 bed5cc52 bellard
     * to synchronous IO.
699 bed5cc52 bellard
     */
700 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
701 bed5cc52 bellard
702 bed5cc52 bellard
    if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
703 bed5cc52 bellard
        QEMUBH *bh;
704 bed5cc52 bellard
        acb = qemu_aio_get(bs, cb, opaque);
705 bed5cc52 bellard
        acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors);
706 bed5cc52 bellard
        bh = qemu_bh_new(raw_aio_em_cb, acb);
707 bed5cc52 bellard
        qemu_bh_schedule(bh);
708 bed5cc52 bellard
        return &acb->common;
709 bed5cc52 bellard
    }
710 bed5cc52 bellard
711 ce1a14dc pbrook
    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
712 ce1a14dc pbrook
    if (!acb)
713 ce1a14dc pbrook
        return NULL;
714 ce1a14dc pbrook
    if (aio_write(&acb->aiocb) < 0) {
715 ce1a14dc pbrook
        qemu_aio_release(acb);
716 ce1a14dc pbrook
        return NULL;
717 5fafdf24 ths
    }
718 ce1a14dc pbrook
    return &acb->common;
719 83f64091 bellard
}
720 83f64091 bellard
721 ce1a14dc pbrook
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
722 83f64091 bellard
{
723 83f64091 bellard
    int ret;
724 ce1a14dc pbrook
    RawAIOCB *acb = (RawAIOCB *)blockacb;
725 ce1a14dc pbrook
    RawAIOCB **pacb;
726 83f64091 bellard
727 ce1a14dc pbrook
    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
728 83f64091 bellard
    if (ret == AIO_NOTCANCELED) {
729 83f64091 bellard
        /* fail safe: if the aio could not be canceled, we wait for
730 83f64091 bellard
           it */
731 ce1a14dc pbrook
        while (aio_error(&acb->aiocb) == EINPROGRESS);
732 83f64091 bellard
    }
733 83f64091 bellard
734 83f64091 bellard
    /* remove the callback from the queue */
735 a76bab49 aliguori
    pacb = &posix_aio_state->first_aio;
736 83f64091 bellard
    for(;;) {
737 83f64091 bellard
        if (*pacb == NULL) {
738 83f64091 bellard
            break;
739 83f64091 bellard
        } else if (*pacb == acb) {
740 ce1a14dc pbrook
            *pacb = acb->next;
741 53538725 aliguori
            raw_fd_pool_put(acb);
742 ce1a14dc pbrook
            qemu_aio_release(acb);
743 83f64091 bellard
            break;
744 83f64091 bellard
        }
745 ce1a14dc pbrook
        pacb = &acb->next;
746 83f64091 bellard
    }
747 83f64091 bellard
}
748 83f64091 bellard
749 a76bab49 aliguori
#else /* CONFIG_AIO */
750 a76bab49 aliguori
static int posix_aio_init(void)
751 414f0dab blueswir1
{
752 674a24ac blueswir1
    return 0;
753 414f0dab blueswir1
}
754 414f0dab blueswir1
#endif /* CONFIG_AIO */
755 414f0dab blueswir1
756 53538725 aliguori
static void raw_close_fd_pool(BDRVRawState *s)
757 53538725 aliguori
{
758 53538725 aliguori
    int i;
759 53538725 aliguori
760 53538725 aliguori
    for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
761 53538725 aliguori
        if (s->fd_pool[i] != -1) {
762 53538725 aliguori
            close(s->fd_pool[i]);
763 53538725 aliguori
            s->fd_pool[i] = -1;
764 53538725 aliguori
        }
765 53538725 aliguori
    }
766 53538725 aliguori
}
767 53538725 aliguori
768 83f64091 bellard
static void raw_close(BlockDriverState *bs)
769 83f64091 bellard
{
770 83f64091 bellard
    BDRVRawState *s = bs->opaque;
771 19cb3738 bellard
    if (s->fd >= 0) {
772 19cb3738 bellard
        close(s->fd);
773 19cb3738 bellard
        s->fd = -1;
774 bed5cc52 bellard
        if (s->aligned_buf != NULL)
775 bed5cc52 bellard
            qemu_free(s->aligned_buf);
776 19cb3738 bellard
    }
777 53538725 aliguori
    raw_close_fd_pool(s);
778 83f64091 bellard
}
779 83f64091 bellard
780 83f64091 bellard
static int raw_truncate(BlockDriverState *bs, int64_t offset)
781 83f64091 bellard
{
782 83f64091 bellard
    BDRVRawState *s = bs->opaque;
783 19cb3738 bellard
    if (s->type != FTYPE_FILE)
784 19cb3738 bellard
        return -ENOTSUP;
785 83f64091 bellard
    if (ftruncate(s->fd, offset) < 0)
786 83f64091 bellard
        return -errno;
787 83f64091 bellard
    return 0;
788 83f64091 bellard
}
789 83f64091 bellard
790 128ab2ff blueswir1
#ifdef __OpenBSD__
791 128ab2ff blueswir1
static int64_t raw_getlength(BlockDriverState *bs)
792 128ab2ff blueswir1
{
793 128ab2ff blueswir1
    BDRVRawState *s = bs->opaque;
794 128ab2ff blueswir1
    int fd = s->fd;
795 128ab2ff blueswir1
    struct stat st;
796 128ab2ff blueswir1
797 128ab2ff blueswir1
    if (fstat(fd, &st))
798 128ab2ff blueswir1
        return -1;
799 128ab2ff blueswir1
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
800 128ab2ff blueswir1
        struct disklabel dl;
801 128ab2ff blueswir1
802 128ab2ff blueswir1
        if (ioctl(fd, DIOCGDINFO, &dl))
803 128ab2ff blueswir1
            return -1;
804 128ab2ff blueswir1
        return (uint64_t)dl.d_secsize *
805 128ab2ff blueswir1
            dl.d_partitions[DISKPART(st.st_rdev)].p_size;
806 128ab2ff blueswir1
    } else
807 128ab2ff blueswir1
        return st.st_size;
808 128ab2ff blueswir1
}
809 128ab2ff blueswir1
#else /* !__OpenBSD__ */
810 83f64091 bellard
static int64_t  raw_getlength(BlockDriverState *bs)
811 83f64091 bellard
{
812 83f64091 bellard
    BDRVRawState *s = bs->opaque;
813 83f64091 bellard
    int fd = s->fd;
814 83f64091 bellard
    int64_t size;
815 83f64091 bellard
#ifdef _BSD
816 83f64091 bellard
    struct stat sb;
817 83f64091 bellard
#endif
818 83f64091 bellard
#ifdef __sun__
819 83f64091 bellard
    struct dk_minfo minfo;
820 83f64091 bellard
    int rv;
821 83f64091 bellard
#endif
822 19cb3738 bellard
    int ret;
823 19cb3738 bellard
824 19cb3738 bellard
    ret = fd_open(bs);
825 19cb3738 bellard
    if (ret < 0)
826 19cb3738 bellard
        return ret;
827 83f64091 bellard
828 83f64091 bellard
#ifdef _BSD
829 83f64091 bellard
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
830 83f64091 bellard
#ifdef DIOCGMEDIASIZE
831 83f64091 bellard
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
832 83f64091 bellard
#endif
833 83f64091 bellard
#ifdef CONFIG_COCOA
834 83f64091 bellard
        size = LONG_LONG_MAX;
835 83f64091 bellard
#else
836 83f64091 bellard
        size = lseek(fd, 0LL, SEEK_END);
837 83f64091 bellard
#endif
838 83f64091 bellard
    } else
839 83f64091 bellard
#endif
840 83f64091 bellard
#ifdef __sun__
841 83f64091 bellard
    /*
842 83f64091 bellard
     * use the DKIOCGMEDIAINFO ioctl to read the size.
843 83f64091 bellard
     */
844 83f64091 bellard
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
845 83f64091 bellard
    if ( rv != -1 ) {
846 83f64091 bellard
        size = minfo.dki_lbsize * minfo.dki_capacity;
847 83f64091 bellard
    } else /* there are reports that lseek on some devices
848 83f64091 bellard
              fails, but irc discussion said that contingency
849 83f64091 bellard
              on contingency was overkill */
850 83f64091 bellard
#endif
851 83f64091 bellard
    {
852 83f64091 bellard
        size = lseek(fd, 0, SEEK_END);
853 83f64091 bellard
    }
854 83f64091 bellard
    return size;
855 83f64091 bellard
}
856 128ab2ff blueswir1
#endif
857 83f64091 bellard
858 83f64091 bellard
static int raw_create(const char *filename, int64_t total_size,
859 83f64091 bellard
                      const char *backing_file, int flags)
860 83f64091 bellard
{
861 83f64091 bellard
    int fd;
862 83f64091 bellard
863 83f64091 bellard
    if (flags || backing_file)
864 83f64091 bellard
        return -ENOTSUP;
865 83f64091 bellard
866 5fafdf24 ths
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
867 83f64091 bellard
              0644);
868 83f64091 bellard
    if (fd < 0)
869 83f64091 bellard
        return -EIO;
870 83f64091 bellard
    ftruncate(fd, total_size * 512);
871 83f64091 bellard
    close(fd);
872 83f64091 bellard
    return 0;
873 83f64091 bellard
}
874 83f64091 bellard
875 83f64091 bellard
static void raw_flush(BlockDriverState *bs)
876 83f64091 bellard
{
877 83f64091 bellard
    BDRVRawState *s = bs->opaque;
878 83f64091 bellard
    fsync(s->fd);
879 83f64091 bellard
}
880 83f64091 bellard
881 83f64091 bellard
BlockDriver bdrv_raw = {
882 83f64091 bellard
    "raw",
883 83f64091 bellard
    sizeof(BDRVRawState),
884 83f64091 bellard
    NULL, /* no probe for protocols */
885 83f64091 bellard
    raw_open,
886 83f64091 bellard
    NULL,
887 83f64091 bellard
    NULL,
888 83f64091 bellard
    raw_close,
889 83f64091 bellard
    raw_create,
890 83f64091 bellard
    raw_flush,
891 3b46e624 ths
892 414f0dab blueswir1
#ifdef CONFIG_AIO
893 83f64091 bellard
    .bdrv_aio_read = raw_aio_read,
894 83f64091 bellard
    .bdrv_aio_write = raw_aio_write,
895 83f64091 bellard
    .bdrv_aio_cancel = raw_aio_cancel,
896 ce1a14dc pbrook
    .aiocb_size = sizeof(RawAIOCB),
897 414f0dab blueswir1
#endif
898 83f64091 bellard
    .bdrv_pread = raw_pread,
899 83f64091 bellard
    .bdrv_pwrite = raw_pwrite,
900 83f64091 bellard
    .bdrv_truncate = raw_truncate,
901 83f64091 bellard
    .bdrv_getlength = raw_getlength,
902 83f64091 bellard
};
903 83f64091 bellard
904 19cb3738 bellard
/***********************************************/
905 19cb3738 bellard
/* host device */
906 19cb3738 bellard
907 19cb3738 bellard
#ifdef CONFIG_COCOA
908 19cb3738 bellard
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
909 19cb3738 bellard
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
910 19cb3738 bellard
911 19cb3738 bellard
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
912 19cb3738 bellard
{
913 5fafdf24 ths
    kern_return_t       kernResult;
914 19cb3738 bellard
    mach_port_t     masterPort;
915 19cb3738 bellard
    CFMutableDictionaryRef  classesToMatch;
916 19cb3738 bellard
917 19cb3738 bellard
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
918 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult ) {
919 19cb3738 bellard
        printf( "IOMasterPort returned %d\n", kernResult );
920 19cb3738 bellard
    }
921 3b46e624 ths
922 5fafdf24 ths
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
923 19cb3738 bellard
    if ( classesToMatch == NULL ) {
924 19cb3738 bellard
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
925 19cb3738 bellard
    } else {
926 19cb3738 bellard
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
927 19cb3738 bellard
    }
928 19cb3738 bellard
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
929 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult )
930 19cb3738 bellard
    {
931 19cb3738 bellard
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
932 19cb3738 bellard
    }
933 3b46e624 ths
934 19cb3738 bellard
    return kernResult;
935 19cb3738 bellard
}
936 19cb3738 bellard
937 19cb3738 bellard
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
938 19cb3738 bellard
{
939 19cb3738 bellard
    io_object_t     nextMedia;
940 19cb3738 bellard
    kern_return_t   kernResult = KERN_FAILURE;
941 19cb3738 bellard
    *bsdPath = '\0';
942 19cb3738 bellard
    nextMedia = IOIteratorNext( mediaIterator );
943 19cb3738 bellard
    if ( nextMedia )
944 19cb3738 bellard
    {
945 19cb3738 bellard
        CFTypeRef   bsdPathAsCFString;
946 19cb3738 bellard
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
947 19cb3738 bellard
        if ( bsdPathAsCFString ) {
948 19cb3738 bellard
            size_t devPathLength;
949 19cb3738 bellard
            strcpy( bsdPath, _PATH_DEV );
950 19cb3738 bellard
            strcat( bsdPath, "r" );
951 19cb3738 bellard
            devPathLength = strlen( bsdPath );
952 19cb3738 bellard
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
953 19cb3738 bellard
                kernResult = KERN_SUCCESS;
954 19cb3738 bellard
            }
955 19cb3738 bellard
            CFRelease( bsdPathAsCFString );
956 19cb3738 bellard
        }
957 19cb3738 bellard
        IOObjectRelease( nextMedia );
958 19cb3738 bellard
    }
959 3b46e624 ths
960 19cb3738 bellard
    return kernResult;
961 19cb3738 bellard
}
962 19cb3738 bellard
963 19cb3738 bellard
#endif
964 19cb3738 bellard
965 19cb3738 bellard
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
966 19cb3738 bellard
{
967 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
968 53538725 aliguori
    int fd, open_flags, ret, i;
969 19cb3738 bellard
970 a76bab49 aliguori
    posix_aio_init();
971 a76bab49 aliguori
972 19cb3738 bellard
#ifdef CONFIG_COCOA
973 19cb3738 bellard
    if (strstart(filename, "/dev/cdrom", NULL)) {
974 19cb3738 bellard
        kern_return_t kernResult;
975 19cb3738 bellard
        io_iterator_t mediaIterator;
976 19cb3738 bellard
        char bsdPath[ MAXPATHLEN ];
977 19cb3738 bellard
        int fd;
978 5fafdf24 ths
979 19cb3738 bellard
        kernResult = FindEjectableCDMedia( &mediaIterator );
980 19cb3738 bellard
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
981 3b46e624 ths
982 19cb3738 bellard
        if ( bsdPath[ 0 ] != '\0' ) {
983 19cb3738 bellard
            strcat(bsdPath,"s0");
984 19cb3738 bellard
            /* some CDs don't have a partition 0 */
985 19cb3738 bellard
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
986 19cb3738 bellard
            if (fd < 0) {
987 19cb3738 bellard
                bsdPath[strlen(bsdPath)-1] = '1';
988 19cb3738 bellard
            } else {
989 19cb3738 bellard
                close(fd);
990 19cb3738 bellard
            }
991 19cb3738 bellard
            filename = bsdPath;
992 19cb3738 bellard
        }
993 3b46e624 ths
994 19cb3738 bellard
        if ( mediaIterator )
995 19cb3738 bellard
            IOObjectRelease( mediaIterator );
996 19cb3738 bellard
    }
997 19cb3738 bellard
#endif
998 19cb3738 bellard
    open_flags = O_BINARY;
999 19cb3738 bellard
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
1000 19cb3738 bellard
        open_flags |= O_RDWR;
1001 19cb3738 bellard
    } else {
1002 19cb3738 bellard
        open_flags |= O_RDONLY;
1003 19cb3738 bellard
        bs->read_only = 1;
1004 19cb3738 bellard
    }
1005 9f7965c7 aliguori
    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
1006 9f7965c7 aliguori
     * and O_DIRECT for no caching. */
1007 9f7965c7 aliguori
    if ((flags & BDRV_O_NOCACHE))
1008 33f00271 balrog
        open_flags |= O_DIRECT;
1009 9f7965c7 aliguori
    else if (!(flags & BDRV_O_CACHE_WB))
1010 9f7965c7 aliguori
        open_flags |= O_DSYNC;
1011 19cb3738 bellard
1012 19cb3738 bellard
    s->type = FTYPE_FILE;
1013 19cb3738 bellard
#if defined(__linux__)
1014 19cb3738 bellard
    if (strstart(filename, "/dev/cd", NULL)) {
1015 19cb3738 bellard
        /* open will not fail even if no CD is inserted */
1016 19cb3738 bellard
        open_flags |= O_NONBLOCK;
1017 19cb3738 bellard
        s->type = FTYPE_CD;
1018 19cb3738 bellard
    } else if (strstart(filename, "/dev/fd", NULL)) {
1019 19cb3738 bellard
        s->type = FTYPE_FD;
1020 6dd2db52 blueswir1
        s->fd_open_flags = open_flags;
1021 19cb3738 bellard
        /* open will not fail even if no floppy is inserted */
1022 19cb3738 bellard
        open_flags |= O_NONBLOCK;
1023 985a03b0 ths
    } else if (strstart(filename, "/dev/sg", NULL)) {
1024 985a03b0 ths
        bs->sg = 1;
1025 19cb3738 bellard
    }
1026 19cb3738 bellard
#endif
1027 19cb3738 bellard
    fd = open(filename, open_flags, 0644);
1028 19cb3738 bellard
    if (fd < 0) {
1029 19cb3738 bellard
        ret = -errno;
1030 19cb3738 bellard
        if (ret == -EROFS)
1031 19cb3738 bellard
            ret = -EACCES;
1032 19cb3738 bellard
        return ret;
1033 19cb3738 bellard
    }
1034 19cb3738 bellard
    s->fd = fd;
1035 53538725 aliguori
    for (i = 0; i < RAW_FD_POOL_SIZE; i++)
1036 53538725 aliguori
        s->fd_pool[i] = -1;
1037 19cb3738 bellard
#if defined(__linux__)
1038 19cb3738 bellard
    /* close fd so that we can reopen it as needed */
1039 19cb3738 bellard
    if (s->type == FTYPE_FD) {
1040 19cb3738 bellard
        close(s->fd);
1041 19cb3738 bellard
        s->fd = -1;
1042 19cb3738 bellard
        s->fd_media_changed = 1;
1043 19cb3738 bellard
    }
1044 19cb3738 bellard
#endif
1045 19cb3738 bellard
    return 0;
1046 19cb3738 bellard
}
1047 19cb3738 bellard
1048 03ff3ca3 aliguori
#if defined(__linux__)
1049 19cb3738 bellard
/* Note: we do not have a reliable method to detect if the floppy is
1050 19cb3738 bellard
   present. The current method is to try to open the floppy at every
1051 19cb3738 bellard
   I/O and to keep it opened during a few hundreds of ms. */
1052 19cb3738 bellard
static int fd_open(BlockDriverState *bs)
1053 19cb3738 bellard
{
1054 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1055 19cb3738 bellard
    int last_media_present;
1056 19cb3738 bellard
1057 19cb3738 bellard
    if (s->type != FTYPE_FD)
1058 19cb3738 bellard
        return 0;
1059 19cb3738 bellard
    last_media_present = (s->fd >= 0);
1060 5fafdf24 ths
    if (s->fd >= 0 &&
1061 19cb3738 bellard
        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
1062 19cb3738 bellard
        close(s->fd);
1063 19cb3738 bellard
        s->fd = -1;
1064 53538725 aliguori
        raw_close_fd_pool(s);
1065 19cb3738 bellard
#ifdef DEBUG_FLOPPY
1066 19cb3738 bellard
        printf("Floppy closed\n");
1067 19cb3738 bellard
#endif
1068 19cb3738 bellard
    }
1069 19cb3738 bellard
    if (s->fd < 0) {
1070 5fafdf24 ths
        if (s->fd_got_error &&
1071 19cb3738 bellard
            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
1072 19cb3738 bellard
#ifdef DEBUG_FLOPPY
1073 19cb3738 bellard
            printf("No floppy (open delayed)\n");
1074 19cb3738 bellard
#endif
1075 19cb3738 bellard
            return -EIO;
1076 19cb3738 bellard
        }
1077 6dd2db52 blueswir1
        s->fd = open(bs->filename, s->fd_open_flags);
1078 19cb3738 bellard
        if (s->fd < 0) {
1079 19cb3738 bellard
            s->fd_error_time = qemu_get_clock(rt_clock);
1080 19cb3738 bellard
            s->fd_got_error = 1;
1081 19cb3738 bellard
            if (last_media_present)
1082 19cb3738 bellard
                s->fd_media_changed = 1;
1083 19cb3738 bellard
#ifdef DEBUG_FLOPPY
1084 19cb3738 bellard
            printf("No floppy\n");
1085 19cb3738 bellard
#endif
1086 19cb3738 bellard
            return -EIO;
1087 19cb3738 bellard
        }
1088 19cb3738 bellard
#ifdef DEBUG_FLOPPY
1089 19cb3738 bellard
        printf("Floppy opened\n");
1090 19cb3738 bellard
#endif
1091 19cb3738 bellard
    }
1092 19cb3738 bellard
    if (!last_media_present)
1093 19cb3738 bellard
        s->fd_media_changed = 1;
1094 19cb3738 bellard
    s->fd_open_time = qemu_get_clock(rt_clock);
1095 19cb3738 bellard
    s->fd_got_error = 0;
1096 19cb3738 bellard
    return 0;
1097 19cb3738 bellard
}
1098 19cb3738 bellard
1099 19cb3738 bellard
static int raw_is_inserted(BlockDriverState *bs)
1100 19cb3738 bellard
{
1101 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1102 19cb3738 bellard
    int ret;
1103 19cb3738 bellard
1104 19cb3738 bellard
    switch(s->type) {
1105 19cb3738 bellard
    case FTYPE_CD:
1106 19cb3738 bellard
        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1107 19cb3738 bellard
        if (ret == CDS_DISC_OK)
1108 19cb3738 bellard
            return 1;
1109 19cb3738 bellard
        else
1110 19cb3738 bellard
            return 0;
1111 19cb3738 bellard
        break;
1112 19cb3738 bellard
    case FTYPE_FD:
1113 19cb3738 bellard
        ret = fd_open(bs);
1114 19cb3738 bellard
        return (ret >= 0);
1115 19cb3738 bellard
    default:
1116 19cb3738 bellard
        return 1;
1117 19cb3738 bellard
    }
1118 19cb3738 bellard
}
1119 19cb3738 bellard
1120 19cb3738 bellard
/* currently only used by fdc.c, but a CD version would be good too */
1121 19cb3738 bellard
static int raw_media_changed(BlockDriverState *bs)
1122 19cb3738 bellard
{
1123 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1124 19cb3738 bellard
1125 19cb3738 bellard
    switch(s->type) {
1126 19cb3738 bellard
    case FTYPE_FD:
1127 19cb3738 bellard
        {
1128 19cb3738 bellard
            int ret;
1129 19cb3738 bellard
            /* XXX: we do not have a true media changed indication. It
1130 19cb3738 bellard
               does not work if the floppy is changed without trying
1131 19cb3738 bellard
               to read it */
1132 19cb3738 bellard
            fd_open(bs);
1133 19cb3738 bellard
            ret = s->fd_media_changed;
1134 19cb3738 bellard
            s->fd_media_changed = 0;
1135 19cb3738 bellard
#ifdef DEBUG_FLOPPY
1136 19cb3738 bellard
            printf("Floppy changed=%d\n", ret);
1137 19cb3738 bellard
#endif
1138 19cb3738 bellard
            return ret;
1139 19cb3738 bellard
        }
1140 19cb3738 bellard
    default:
1141 19cb3738 bellard
        return -ENOTSUP;
1142 19cb3738 bellard
    }
1143 19cb3738 bellard
}
1144 19cb3738 bellard
1145 19cb3738 bellard
static int raw_eject(BlockDriverState *bs, int eject_flag)
1146 19cb3738 bellard
{
1147 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1148 19cb3738 bellard
1149 19cb3738 bellard
    switch(s->type) {
1150 19cb3738 bellard
    case FTYPE_CD:
1151 19cb3738 bellard
        if (eject_flag) {
1152 19cb3738 bellard
            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
1153 19cb3738 bellard
                perror("CDROMEJECT");
1154 19cb3738 bellard
        } else {
1155 19cb3738 bellard
            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
1156 19cb3738 bellard
                perror("CDROMEJECT");
1157 19cb3738 bellard
        }
1158 19cb3738 bellard
        break;
1159 19cb3738 bellard
    case FTYPE_FD:
1160 19cb3738 bellard
        {
1161 19cb3738 bellard
            int fd;
1162 19cb3738 bellard
            if (s->fd >= 0) {
1163 19cb3738 bellard
                close(s->fd);
1164 19cb3738 bellard
                s->fd = -1;
1165 53538725 aliguori
                raw_close_fd_pool(s);
1166 19cb3738 bellard
            }
1167 6dd2db52 blueswir1
            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
1168 19cb3738 bellard
            if (fd >= 0) {
1169 19cb3738 bellard
                if (ioctl(fd, FDEJECT, 0) < 0)
1170 19cb3738 bellard
                    perror("FDEJECT");
1171 19cb3738 bellard
                close(fd);
1172 19cb3738 bellard
            }
1173 19cb3738 bellard
        }
1174 19cb3738 bellard
        break;
1175 19cb3738 bellard
    default:
1176 19cb3738 bellard
        return -ENOTSUP;
1177 19cb3738 bellard
    }
1178 19cb3738 bellard
    return 0;
1179 19cb3738 bellard
}
1180 19cb3738 bellard
1181 19cb3738 bellard
static int raw_set_locked(BlockDriverState *bs, int locked)
1182 19cb3738 bellard
{
1183 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1184 19cb3738 bellard
1185 19cb3738 bellard
    switch(s->type) {
1186 19cb3738 bellard
    case FTYPE_CD:
1187 19cb3738 bellard
        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
1188 19cb3738 bellard
            /* Note: an error can happen if the distribution automatically
1189 19cb3738 bellard
               mounts the CD-ROM */
1190 19cb3738 bellard
            //        perror("CDROM_LOCKDOOR");
1191 19cb3738 bellard
        }
1192 19cb3738 bellard
        break;
1193 19cb3738 bellard
    default:
1194 19cb3738 bellard
        return -ENOTSUP;
1195 19cb3738 bellard
    }
1196 19cb3738 bellard
    return 0;
1197 19cb3738 bellard
}
1198 19cb3738 bellard
1199 985a03b0 ths
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1200 985a03b0 ths
{
1201 985a03b0 ths
    BDRVRawState *s = bs->opaque;
1202 985a03b0 ths
1203 985a03b0 ths
    return ioctl(s->fd, req, buf);
1204 985a03b0 ths
}
1205 19cb3738 bellard
#else
1206 19cb3738 bellard
1207 08af02e2 aliguori
static int fd_open(BlockDriverState *bs)
1208 08af02e2 aliguori
{
1209 08af02e2 aliguori
    return 0;
1210 08af02e2 aliguori
}
1211 08af02e2 aliguori
1212 19cb3738 bellard
static int raw_is_inserted(BlockDriverState *bs)
1213 19cb3738 bellard
{
1214 19cb3738 bellard
    return 1;
1215 19cb3738 bellard
}
1216 19cb3738 bellard
1217 19cb3738 bellard
static int raw_media_changed(BlockDriverState *bs)
1218 19cb3738 bellard
{
1219 19cb3738 bellard
    return -ENOTSUP;
1220 19cb3738 bellard
}
1221 19cb3738 bellard
1222 19cb3738 bellard
static int raw_eject(BlockDriverState *bs, int eject_flag)
1223 19cb3738 bellard
{
1224 19cb3738 bellard
    return -ENOTSUP;
1225 19cb3738 bellard
}
1226 19cb3738 bellard
1227 19cb3738 bellard
static int raw_set_locked(BlockDriverState *bs, int locked)
1228 19cb3738 bellard
{
1229 19cb3738 bellard
    return -ENOTSUP;
1230 19cb3738 bellard
}
1231 19cb3738 bellard
1232 985a03b0 ths
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1233 985a03b0 ths
{
1234 985a03b0 ths
    return -ENOTSUP;
1235 985a03b0 ths
}
1236 19cb3738 bellard
#endif /* !linux */
1237 19cb3738 bellard
1238 19cb3738 bellard
BlockDriver bdrv_host_device = {
1239 19cb3738 bellard
    "host_device",
1240 19cb3738 bellard
    sizeof(BDRVRawState),
1241 19cb3738 bellard
    NULL, /* no probe for protocols */
1242 19cb3738 bellard
    hdev_open,
1243 19cb3738 bellard
    NULL,
1244 19cb3738 bellard
    NULL,
1245 19cb3738 bellard
    raw_close,
1246 19cb3738 bellard
    NULL,
1247 19cb3738 bellard
    raw_flush,
1248 3b46e624 ths
1249 414f0dab blueswir1
#ifdef CONFIG_AIO
1250 19cb3738 bellard
    .bdrv_aio_read = raw_aio_read,
1251 19cb3738 bellard
    .bdrv_aio_write = raw_aio_write,
1252 19cb3738 bellard
    .bdrv_aio_cancel = raw_aio_cancel,
1253 19cb3738 bellard
    .aiocb_size = sizeof(RawAIOCB),
1254 414f0dab blueswir1
#endif
1255 19cb3738 bellard
    .bdrv_pread = raw_pread,
1256 19cb3738 bellard
    .bdrv_pwrite = raw_pwrite,
1257 19cb3738 bellard
    .bdrv_getlength = raw_getlength,
1258 19cb3738 bellard
1259 19cb3738 bellard
    /* removable device support */
1260 19cb3738 bellard
    .bdrv_is_inserted = raw_is_inserted,
1261 19cb3738 bellard
    .bdrv_media_changed = raw_media_changed,
1262 19cb3738 bellard
    .bdrv_eject = raw_eject,
1263 19cb3738 bellard
    .bdrv_set_locked = raw_set_locked,
1264 985a03b0 ths
    /* generic scsi device */
1265 985a03b0 ths
    .bdrv_ioctl = raw_ioctl,
1266 19cb3738 bellard
};