Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 0834c9ea

History | View | Annotate | Download (35 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 0bf9e31a Blue Swirl
#include "qemu-log.h"
28 83f64091 bellard
#include "block_int.h"
29 5efa9d5a Anthony Liguori
#include "module.h"
30 9ef91a67 Christoph Hellwig
#include "block/raw-posix-aio.h"
31 83f64091 bellard
32 83affaa6 Pavel Borzenkov
#if defined(__APPLE__) && (__MACH__)
33 83f64091 bellard
#include <paths.h>
34 83f64091 bellard
#include <sys/param.h>
35 83f64091 bellard
#include <IOKit/IOKitLib.h>
36 83f64091 bellard
#include <IOKit/IOBSD.h>
37 83f64091 bellard
#include <IOKit/storage/IOMediaBSDClient.h>
38 83f64091 bellard
#include <IOKit/storage/IOMedia.h>
39 83f64091 bellard
#include <IOKit/storage/IOCDMedia.h>
40 83f64091 bellard
//#include <IOKit/storage/IOCDTypes.h>
41 83f64091 bellard
#include <CoreFoundation/CoreFoundation.h>
42 83f64091 bellard
#endif
43 83f64091 bellard
44 83f64091 bellard
#ifdef __sun__
45 2e9671da ths
#define _POSIX_PTHREAD_SEMANTICS 1
46 83f64091 bellard
#include <sys/dkio.h>
47 83f64091 bellard
#endif
48 19cb3738 bellard
#ifdef __linux__
49 343f8568 Johannes Stezenbach
#include <sys/types.h>
50 343f8568 Johannes Stezenbach
#include <sys/stat.h>
51 19cb3738 bellard
#include <sys/ioctl.h>
52 05acda4d Bernhard Kohl
#include <sys/param.h>
53 19cb3738 bellard
#include <linux/cdrom.h>
54 19cb3738 bellard
#include <linux/fd.h>
55 5500316d Paolo Bonzini
#include <linux/fs.h>
56 5500316d Paolo Bonzini
#endif
57 5500316d Paolo Bonzini
#ifdef CONFIG_FIEMAP
58 5500316d Paolo Bonzini
#include <linux/fiemap.h>
59 19cb3738 bellard
#endif
60 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
61 1cb6c3fd ths
#include <sys/disk.h>
62 9f23011a blueswir1
#include <sys/cdio.h>
63 1cb6c3fd ths
#endif
64 83f64091 bellard
65 128ab2ff blueswir1
#ifdef __OpenBSD__
66 128ab2ff blueswir1
#include <sys/ioctl.h>
67 128ab2ff blueswir1
#include <sys/disklabel.h>
68 128ab2ff blueswir1
#include <sys/dkio.h>
69 128ab2ff blueswir1
#endif
70 128ab2ff blueswir1
71 d1f6fd8d Christoph Egger
#ifdef __NetBSD__
72 d1f6fd8d Christoph Egger
#include <sys/ioctl.h>
73 d1f6fd8d Christoph Egger
#include <sys/disklabel.h>
74 d1f6fd8d Christoph Egger
#include <sys/dkio.h>
75 d1f6fd8d Christoph Egger
#include <sys/disk.h>
76 d1f6fd8d Christoph Egger
#endif
77 d1f6fd8d Christoph Egger
78 c5e97233 blueswir1
#ifdef __DragonFly__
79 c5e97233 blueswir1
#include <sys/ioctl.h>
80 c5e97233 blueswir1
#include <sys/diskslice.h>
81 c5e97233 blueswir1
#endif
82 c5e97233 blueswir1
83 dce512de Christoph Hellwig
#ifdef CONFIG_XFS
84 dce512de Christoph Hellwig
#include <xfs/xfs.h>
85 dce512de Christoph Hellwig
#endif
86 dce512de Christoph Hellwig
87 19cb3738 bellard
//#define DEBUG_FLOPPY
88 83f64091 bellard
89 faf07963 pbrook
//#define DEBUG_BLOCK
90 03ff3ca3 aliguori
#if defined(DEBUG_BLOCK)
91 001faf32 Blue Swirl
#define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
92 001faf32 Blue Swirl
    { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
93 8c05dbf9 ths
#else
94 001faf32 Blue Swirl
#define DEBUG_BLOCK_PRINT(formatCstr, ...)
95 8c05dbf9 ths
#endif
96 8c05dbf9 ths
97 f6465578 aliguori
/* OS X does not have O_DSYNC */
98 f6465578 aliguori
#ifndef O_DSYNC
99 1c27a8b3 G 3
#ifdef O_SYNC
100 7ab064d2 aliguori
#define O_DSYNC O_SYNC
101 1c27a8b3 G 3
#elif defined(O_FSYNC)
102 1c27a8b3 G 3
#define O_DSYNC O_FSYNC
103 1c27a8b3 G 3
#endif
104 f6465578 aliguori
#endif
105 f6465578 aliguori
106 9f7965c7 aliguori
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
107 9f7965c7 aliguori
#ifndef O_DIRECT
108 9f7965c7 aliguori
#define O_DIRECT O_DSYNC
109 9f7965c7 aliguori
#endif
110 9f7965c7 aliguori
111 19cb3738 bellard
#define FTYPE_FILE   0
112 19cb3738 bellard
#define FTYPE_CD     1
113 19cb3738 bellard
#define FTYPE_FD     2
114 83f64091 bellard
115 c57c846a Blue Swirl
/* if the FD is not accessed during that time (in ns), we try to
116 19cb3738 bellard
   reopen it to see if the disk has been changed */
117 c57c846a Blue Swirl
#define FD_OPEN_TIMEOUT (1000000000)
118 83f64091 bellard
119 581b9e29 Christoph Hellwig
#define MAX_BLOCKSIZE        4096
120 581b9e29 Christoph Hellwig
121 19cb3738 bellard
typedef struct BDRVRawState {
122 19cb3738 bellard
    int fd;
123 19cb3738 bellard
    int type;
124 0e1d8f4c Christoph Hellwig
    int open_flags;
125 19cb3738 bellard
#if defined(__linux__)
126 19cb3738 bellard
    /* linux floppy specific */
127 19cb3738 bellard
    int64_t fd_open_time;
128 19cb3738 bellard
    int64_t fd_error_time;
129 19cb3738 bellard
    int fd_got_error;
130 19cb3738 bellard
    int fd_media_changed;
131 83f64091 bellard
#endif
132 e44bd6fc Stefan Weil
#ifdef CONFIG_LINUX_AIO
133 5c6c3a6c Christoph Hellwig
    int use_aio;
134 1e5b9d2f Kevin Wolf
    void *aio_ctx;
135 e44bd6fc Stefan Weil
#endif
136 581b9e29 Christoph Hellwig
    uint8_t *aligned_buf;
137 581b9e29 Christoph Hellwig
    unsigned aligned_buf_size;
138 dce512de Christoph Hellwig
#ifdef CONFIG_XFS
139 dce512de Christoph Hellwig
    bool is_xfs : 1;
140 dce512de Christoph Hellwig
#endif
141 19cb3738 bellard
} BDRVRawState;
142 19cb3738 bellard
143 19cb3738 bellard
static int fd_open(BlockDriverState *bs);
144 22afa7b5 Kevin Wolf
static int64_t raw_getlength(BlockDriverState *bs);
145 83f64091 bellard
146 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
147 f3a5d3f8 Christoph Hellwig
static int cdrom_reopen(BlockDriverState *bs);
148 9f23011a blueswir1
#endif
149 9f23011a blueswir1
150 1de1ae0a Christoph Egger
#if defined(__NetBSD__)
151 1de1ae0a Christoph Egger
static int raw_normalize_devicepath(const char **filename)
152 1de1ae0a Christoph Egger
{
153 1de1ae0a Christoph Egger
    static char namebuf[PATH_MAX];
154 1de1ae0a Christoph Egger
    const char *dp, *fname;
155 1de1ae0a Christoph Egger
    struct stat sb;
156 1de1ae0a Christoph Egger
157 1de1ae0a Christoph Egger
    fname = *filename;
158 1de1ae0a Christoph Egger
    dp = strrchr(fname, '/');
159 1de1ae0a Christoph Egger
    if (lstat(fname, &sb) < 0) {
160 1de1ae0a Christoph Egger
        fprintf(stderr, "%s: stat failed: %s\n",
161 1de1ae0a Christoph Egger
            fname, strerror(errno));
162 1de1ae0a Christoph Egger
        return -errno;
163 1de1ae0a Christoph Egger
    }
164 1de1ae0a Christoph Egger
165 1de1ae0a Christoph Egger
    if (!S_ISBLK(sb.st_mode)) {
166 1de1ae0a Christoph Egger
        return 0;
167 1de1ae0a Christoph Egger
    }
168 1de1ae0a Christoph Egger
169 1de1ae0a Christoph Egger
    if (dp == NULL) {
170 1de1ae0a Christoph Egger
        snprintf(namebuf, PATH_MAX, "r%s", fname);
171 1de1ae0a Christoph Egger
    } else {
172 1de1ae0a Christoph Egger
        snprintf(namebuf, PATH_MAX, "%.*s/r%s",
173 1de1ae0a Christoph Egger
            (int)(dp - fname), fname, dp + 1);
174 1de1ae0a Christoph Egger
    }
175 1de1ae0a Christoph Egger
    fprintf(stderr, "%s is a block device", fname);
176 1de1ae0a Christoph Egger
    *filename = namebuf;
177 1de1ae0a Christoph Egger
    fprintf(stderr, ", using %s\n", *filename);
178 1de1ae0a Christoph Egger
179 1de1ae0a Christoph Egger
    return 0;
180 1de1ae0a Christoph Egger
}
181 1de1ae0a Christoph Egger
#else
182 1de1ae0a Christoph Egger
static int raw_normalize_devicepath(const char **filename)
183 1de1ae0a Christoph Egger
{
184 1de1ae0a Christoph Egger
    return 0;
185 1de1ae0a Christoph Egger
}
186 1de1ae0a Christoph Egger
#endif
187 1de1ae0a Christoph Egger
188 90babde0 Christoph Hellwig
static int raw_open_common(BlockDriverState *bs, const char *filename,
189 19a3da7f Blue Swirl
                           int bdrv_flags, int open_flags)
190 83f64091 bellard
{
191 83f64091 bellard
    BDRVRawState *s = bs->opaque;
192 0e1d8f4c Christoph Hellwig
    int fd, ret;
193 83f64091 bellard
194 1de1ae0a Christoph Egger
    ret = raw_normalize_devicepath(&filename);
195 1de1ae0a Christoph Egger
    if (ret != 0) {
196 1de1ae0a Christoph Egger
        return ret;
197 1de1ae0a Christoph Egger
    }
198 1de1ae0a Christoph Egger
199 19a3da7f Blue Swirl
    s->open_flags = open_flags | O_BINARY;
200 11a1feb6 Avi Kivity
    s->open_flags &= ~O_ACCMODE;
201 f5edb014 Naphtali Sprei
    if (bdrv_flags & BDRV_O_RDWR) {
202 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_RDWR;
203 83f64091 bellard
    } else {
204 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_RDONLY;
205 83f64091 bellard
    }
206 9f7965c7 aliguori
207 9f7965c7 aliguori
    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
208 9f7965c7 aliguori
     * and O_DIRECT for no caching. */
209 19a3da7f Blue Swirl
    if ((bdrv_flags & BDRV_O_NOCACHE))
210 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_DIRECT;
211 a6599793 Christoph Hellwig
    if (!(bdrv_flags & BDRV_O_CACHE_WB))
212 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_DSYNC;
213 83f64091 bellard
214 90babde0 Christoph Hellwig
    s->fd = -1;
215 40ff6d7e Kevin Wolf
    fd = qemu_open(filename, s->open_flags, 0644);
216 19cb3738 bellard
    if (fd < 0) {
217 19cb3738 bellard
        ret = -errno;
218 19cb3738 bellard
        if (ret == -EROFS)
219 19cb3738 bellard
            ret = -EACCES;
220 19cb3738 bellard
        return ret;
221 19cb3738 bellard
    }
222 83f64091 bellard
    s->fd = fd;
223 bed5cc52 bellard
    s->aligned_buf = NULL;
224 5c6c3a6c Christoph Hellwig
225 19a3da7f Blue Swirl
    if ((bdrv_flags & BDRV_O_NOCACHE)) {
226 581b9e29 Christoph Hellwig
        /*
227 581b9e29 Christoph Hellwig
         * Allocate a buffer for read/modify/write cycles.  Chose the size
228 581b9e29 Christoph Hellwig
         * pessimistically as we don't know the block size yet.
229 581b9e29 Christoph Hellwig
         */
230 581b9e29 Christoph Hellwig
        s->aligned_buf_size = 32 * MAX_BLOCKSIZE;
231 581b9e29 Christoph Hellwig
        s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, s->aligned_buf_size);
232 bed5cc52 bellard
        if (s->aligned_buf == NULL) {
233 9ef91a67 Christoph Hellwig
            goto out_close;
234 bed5cc52 bellard
        }
235 bed5cc52 bellard
    }
236 9ef91a67 Christoph Hellwig
237 f6e8ffc2 Frediano Ziglio
    /* We're falling back to POSIX AIO in some cases so init always */
238 f6e8ffc2 Frediano Ziglio
    if (paio_init() < 0) {
239 f6e8ffc2 Frediano Ziglio
        goto out_free_buf;
240 f6e8ffc2 Frediano Ziglio
    }
241 f6e8ffc2 Frediano Ziglio
242 5c6c3a6c Christoph Hellwig
#ifdef CONFIG_LINUX_AIO
243 c30e624d Frediano Ziglio
    /*
244 c30e624d Frediano Ziglio
     * Currently Linux do AIO only for files opened with O_DIRECT
245 c30e624d Frediano Ziglio
     * specified so check NOCACHE flag too
246 c30e624d Frediano Ziglio
     */
247 5c6c3a6c Christoph Hellwig
    if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
248 5c6c3a6c Christoph Hellwig
                      (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
249 d2e46345 Kevin Wolf
250 5c6c3a6c Christoph Hellwig
        s->aio_ctx = laio_init();
251 5c6c3a6c Christoph Hellwig
        if (!s->aio_ctx) {
252 5c6c3a6c Christoph Hellwig
            goto out_free_buf;
253 5c6c3a6c Christoph Hellwig
        }
254 5c6c3a6c Christoph Hellwig
        s->use_aio = 1;
255 5c6c3a6c Christoph Hellwig
    } else
256 5c6c3a6c Christoph Hellwig
#endif
257 5c6c3a6c Christoph Hellwig
    {
258 e44bd6fc Stefan Weil
#ifdef CONFIG_LINUX_AIO
259 5c6c3a6c Christoph Hellwig
        s->use_aio = 0;
260 e44bd6fc Stefan Weil
#endif
261 9ef91a67 Christoph Hellwig
    }
262 9ef91a67 Christoph Hellwig
263 dce512de Christoph Hellwig
#ifdef CONFIG_XFS
264 dce512de Christoph Hellwig
    if (platform_test_xfs_fd(s->fd)) {
265 dce512de Christoph Hellwig
        s->is_xfs = 1;
266 dce512de Christoph Hellwig
    }
267 dce512de Christoph Hellwig
#endif
268 dce512de Christoph Hellwig
269 83f64091 bellard
    return 0;
270 9ef91a67 Christoph Hellwig
271 9ef91a67 Christoph Hellwig
out_free_buf:
272 9ef91a67 Christoph Hellwig
    qemu_vfree(s->aligned_buf);
273 9ef91a67 Christoph Hellwig
out_close:
274 2e1e79da Corey Bryant
    qemu_close(fd);
275 9ef91a67 Christoph Hellwig
    return -errno;
276 83f64091 bellard
}
277 83f64091 bellard
278 90babde0 Christoph Hellwig
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
279 90babde0 Christoph Hellwig
{
280 90babde0 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
281 90babde0 Christoph Hellwig
282 90babde0 Christoph Hellwig
    s->type = FTYPE_FILE;
283 9a2d77ad Christoph Hellwig
    return raw_open_common(bs, filename, flags, 0);
284 90babde0 Christoph Hellwig
}
285 90babde0 Christoph Hellwig
286 83f64091 bellard
/* XXX: use host sector size if necessary with:
287 83f64091 bellard
#ifdef DIOCGSECTORSIZE
288 83f64091 bellard
        {
289 83f64091 bellard
            unsigned int sectorsize = 512;
290 83f64091 bellard
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
291 83f64091 bellard
                sectorsize > bufsize)
292 83f64091 bellard
                bufsize = sectorsize;
293 83f64091 bellard
        }
294 83f64091 bellard
#endif
295 83f64091 bellard
#ifdef CONFIG_COCOA
296 2ee9fb48 Stefan Weil
        uint32_t blockSize = 512;
297 83f64091 bellard
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
298 83f64091 bellard
            bufsize = blockSize;
299 83f64091 bellard
        }
300 83f64091 bellard
#endif
301 83f64091 bellard
*/
302 83f64091 bellard
303 bed5cc52 bellard
/*
304 9ef91a67 Christoph Hellwig
 * Check if all memory in this vector is sector aligned.
305 9ef91a67 Christoph Hellwig
 */
306 581b9e29 Christoph Hellwig
static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
307 a76bab49 aliguori
{
308 9ef91a67 Christoph Hellwig
    int i;
309 83f64091 bellard
310 9ef91a67 Christoph Hellwig
    for (i = 0; i < qiov->niov; i++) {
311 581b9e29 Christoph Hellwig
        if ((uintptr_t) qiov->iov[i].iov_base % bs->buffer_alignment) {
312 9ef91a67 Christoph Hellwig
            return 0;
313 c16b5a2c Christoph Hellwig
        }
314 c16b5a2c Christoph Hellwig
    }
315 c16b5a2c Christoph Hellwig
316 9ef91a67 Christoph Hellwig
    return 1;
317 c16b5a2c Christoph Hellwig
}
318 c16b5a2c Christoph Hellwig
319 9ef91a67 Christoph Hellwig
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
320 9ef91a67 Christoph Hellwig
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
321 9ef91a67 Christoph Hellwig
        BlockDriverCompletionFunc *cb, void *opaque, int type)
322 83f64091 bellard
{
323 ce1a14dc pbrook
    BDRVRawState *s = bs->opaque;
324 ce1a14dc pbrook
325 19cb3738 bellard
    if (fd_open(bs) < 0)
326 19cb3738 bellard
        return NULL;
327 19cb3738 bellard
328 f141eafe aliguori
    /*
329 f141eafe aliguori
     * If O_DIRECT is used the buffer needs to be aligned on a sector
330 c1ee7d56 Frediano Ziglio
     * boundary.  Check if this is the case or tell the low-level
331 9ef91a67 Christoph Hellwig
     * driver that it needs to copy the buffer.
332 f141eafe aliguori
     */
333 5c6c3a6c Christoph Hellwig
    if (s->aligned_buf) {
334 581b9e29 Christoph Hellwig
        if (!qiov_is_aligned(bs, qiov)) {
335 5c6c3a6c Christoph Hellwig
            type |= QEMU_AIO_MISALIGNED;
336 e44bd6fc Stefan Weil
#ifdef CONFIG_LINUX_AIO
337 5c6c3a6c Christoph Hellwig
        } else if (s->use_aio) {
338 5c6c3a6c Christoph Hellwig
            return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
339 e44bd6fc Stefan Weil
                               nb_sectors, cb, opaque, type);
340 e44bd6fc Stefan Weil
#endif
341 5c6c3a6c Christoph Hellwig
        }
342 9ef91a67 Christoph Hellwig
    }
343 f141eafe aliguori
344 1e5b9d2f Kevin Wolf
    return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
345 9ef91a67 Christoph Hellwig
                       cb, opaque, type);
346 83f64091 bellard
}
347 83f64091 bellard
348 f141eafe aliguori
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
349 f141eafe aliguori
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
350 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
351 83f64091 bellard
{
352 9ef91a67 Christoph Hellwig
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
353 9ef91a67 Christoph Hellwig
                          cb, opaque, QEMU_AIO_READ);
354 83f64091 bellard
}
355 83f64091 bellard
356 f141eafe aliguori
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
357 f141eafe aliguori
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
358 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
359 83f64091 bellard
{
360 9ef91a67 Christoph Hellwig
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
361 9ef91a67 Christoph Hellwig
                          cb, opaque, QEMU_AIO_WRITE);
362 83f64091 bellard
}
363 53538725 aliguori
364 b2e12bc6 Christoph Hellwig
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
365 b2e12bc6 Christoph Hellwig
        BlockDriverCompletionFunc *cb, void *opaque)
366 b2e12bc6 Christoph Hellwig
{
367 b2e12bc6 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
368 b2e12bc6 Christoph Hellwig
369 b2e12bc6 Christoph Hellwig
    if (fd_open(bs) < 0)
370 b2e12bc6 Christoph Hellwig
        return NULL;
371 b2e12bc6 Christoph Hellwig
372 1e5b9d2f Kevin Wolf
    return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
373 b2e12bc6 Christoph Hellwig
}
374 b2e12bc6 Christoph Hellwig
375 83f64091 bellard
static void raw_close(BlockDriverState *bs)
376 83f64091 bellard
{
377 83f64091 bellard
    BDRVRawState *s = bs->opaque;
378 19cb3738 bellard
    if (s->fd >= 0) {
379 2e1e79da Corey Bryant
        qemu_close(s->fd);
380 19cb3738 bellard
        s->fd = -1;
381 bed5cc52 bellard
        if (s->aligned_buf != NULL)
382 f8a83245 Herve Poussineau
            qemu_vfree(s->aligned_buf);
383 19cb3738 bellard
    }
384 83f64091 bellard
}
385 83f64091 bellard
386 83f64091 bellard
static int raw_truncate(BlockDriverState *bs, int64_t offset)
387 83f64091 bellard
{
388 83f64091 bellard
    BDRVRawState *s = bs->opaque;
389 55b949c8 Christoph Hellwig
    struct stat st;
390 55b949c8 Christoph Hellwig
391 55b949c8 Christoph Hellwig
    if (fstat(s->fd, &st)) {
392 83f64091 bellard
        return -errno;
393 55b949c8 Christoph Hellwig
    }
394 55b949c8 Christoph Hellwig
395 55b949c8 Christoph Hellwig
    if (S_ISREG(st.st_mode)) {
396 55b949c8 Christoph Hellwig
        if (ftruncate(s->fd, offset) < 0) {
397 55b949c8 Christoph Hellwig
            return -errno;
398 55b949c8 Christoph Hellwig
        }
399 55b949c8 Christoph Hellwig
    } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
400 55b949c8 Christoph Hellwig
       if (offset > raw_getlength(bs)) {
401 55b949c8 Christoph Hellwig
           return -EINVAL;
402 55b949c8 Christoph Hellwig
       }
403 55b949c8 Christoph Hellwig
    } else {
404 55b949c8 Christoph Hellwig
        return -ENOTSUP;
405 55b949c8 Christoph Hellwig
    }
406 55b949c8 Christoph Hellwig
407 83f64091 bellard
    return 0;
408 83f64091 bellard
}
409 83f64091 bellard
410 128ab2ff blueswir1
#ifdef __OpenBSD__
411 128ab2ff blueswir1
static int64_t raw_getlength(BlockDriverState *bs)
412 128ab2ff blueswir1
{
413 128ab2ff blueswir1
    BDRVRawState *s = bs->opaque;
414 128ab2ff blueswir1
    int fd = s->fd;
415 128ab2ff blueswir1
    struct stat st;
416 128ab2ff blueswir1
417 128ab2ff blueswir1
    if (fstat(fd, &st))
418 128ab2ff blueswir1
        return -1;
419 128ab2ff blueswir1
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
420 128ab2ff blueswir1
        struct disklabel dl;
421 128ab2ff blueswir1
422 128ab2ff blueswir1
        if (ioctl(fd, DIOCGDINFO, &dl))
423 128ab2ff blueswir1
            return -1;
424 128ab2ff blueswir1
        return (uint64_t)dl.d_secsize *
425 128ab2ff blueswir1
            dl.d_partitions[DISKPART(st.st_rdev)].p_size;
426 128ab2ff blueswir1
    } else
427 128ab2ff blueswir1
        return st.st_size;
428 128ab2ff blueswir1
}
429 d1f6fd8d Christoph Egger
#elif defined(__NetBSD__)
430 d1f6fd8d Christoph Egger
static int64_t raw_getlength(BlockDriverState *bs)
431 d1f6fd8d Christoph Egger
{
432 d1f6fd8d Christoph Egger
    BDRVRawState *s = bs->opaque;
433 d1f6fd8d Christoph Egger
    int fd = s->fd;
434 d1f6fd8d Christoph Egger
    struct stat st;
435 d1f6fd8d Christoph Egger
436 d1f6fd8d Christoph Egger
    if (fstat(fd, &st))
437 d1f6fd8d Christoph Egger
        return -1;
438 d1f6fd8d Christoph Egger
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
439 d1f6fd8d Christoph Egger
        struct dkwedge_info dkw;
440 d1f6fd8d Christoph Egger
441 d1f6fd8d Christoph Egger
        if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
442 d1f6fd8d Christoph Egger
            return dkw.dkw_size * 512;
443 d1f6fd8d Christoph Egger
        } else {
444 d1f6fd8d Christoph Egger
            struct disklabel dl;
445 d1f6fd8d Christoph Egger
446 d1f6fd8d Christoph Egger
            if (ioctl(fd, DIOCGDINFO, &dl))
447 d1f6fd8d Christoph Egger
                return -1;
448 d1f6fd8d Christoph Egger
            return (uint64_t)dl.d_secsize *
449 d1f6fd8d Christoph Egger
                dl.d_partitions[DISKPART(st.st_rdev)].p_size;
450 d1f6fd8d Christoph Egger
        }
451 d1f6fd8d Christoph Egger
    } else
452 d1f6fd8d Christoph Egger
        return st.st_size;
453 d1f6fd8d Christoph Egger
}
454 50779cc2 Christoph Hellwig
#elif defined(__sun__)
455 50779cc2 Christoph Hellwig
static int64_t raw_getlength(BlockDriverState *bs)
456 50779cc2 Christoph Hellwig
{
457 50779cc2 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
458 50779cc2 Christoph Hellwig
    struct dk_minfo minfo;
459 50779cc2 Christoph Hellwig
    int ret;
460 50779cc2 Christoph Hellwig
461 50779cc2 Christoph Hellwig
    ret = fd_open(bs);
462 50779cc2 Christoph Hellwig
    if (ret < 0) {
463 50779cc2 Christoph Hellwig
        return ret;
464 50779cc2 Christoph Hellwig
    }
465 50779cc2 Christoph Hellwig
466 50779cc2 Christoph Hellwig
    /*
467 50779cc2 Christoph Hellwig
     * Use the DKIOCGMEDIAINFO ioctl to read the size.
468 50779cc2 Christoph Hellwig
     */
469 50779cc2 Christoph Hellwig
    ret = ioctl(s->fd, DKIOCGMEDIAINFO, &minfo);
470 50779cc2 Christoph Hellwig
    if (ret != -1) {
471 50779cc2 Christoph Hellwig
        return minfo.dki_lbsize * minfo.dki_capacity;
472 50779cc2 Christoph Hellwig
    }
473 50779cc2 Christoph Hellwig
474 50779cc2 Christoph Hellwig
    /*
475 50779cc2 Christoph Hellwig
     * There are reports that lseek on some devices fails, but
476 50779cc2 Christoph Hellwig
     * irc discussion said that contingency on contingency was overkill.
477 50779cc2 Christoph Hellwig
     */
478 50779cc2 Christoph Hellwig
    return lseek(s->fd, 0, SEEK_END);
479 50779cc2 Christoph Hellwig
}
480 50779cc2 Christoph Hellwig
#elif defined(CONFIG_BSD)
481 50779cc2 Christoph Hellwig
static int64_t raw_getlength(BlockDriverState *bs)
482 83f64091 bellard
{
483 83f64091 bellard
    BDRVRawState *s = bs->opaque;
484 83f64091 bellard
    int fd = s->fd;
485 83f64091 bellard
    int64_t size;
486 83f64091 bellard
    struct stat sb;
487 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
488 9f23011a blueswir1
    int reopened = 0;
489 9f23011a blueswir1
#endif
490 19cb3738 bellard
    int ret;
491 19cb3738 bellard
492 19cb3738 bellard
    ret = fd_open(bs);
493 19cb3738 bellard
    if (ret < 0)
494 19cb3738 bellard
        return ret;
495 83f64091 bellard
496 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
497 9f23011a blueswir1
again:
498 9f23011a blueswir1
#endif
499 83f64091 bellard
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
500 83f64091 bellard
#ifdef DIOCGMEDIASIZE
501 83f64091 bellard
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
502 c5e97233 blueswir1
#elif defined(DIOCGPART)
503 c5e97233 blueswir1
        {
504 c5e97233 blueswir1
                struct partinfo pi;
505 c5e97233 blueswir1
                if (ioctl(fd, DIOCGPART, &pi) == 0)
506 c5e97233 blueswir1
                        size = pi.media_size;
507 c5e97233 blueswir1
                else
508 c5e97233 blueswir1
                        size = 0;
509 c5e97233 blueswir1
        }
510 c5e97233 blueswir1
        if (size == 0)
511 83f64091 bellard
#endif
512 83affaa6 Pavel Borzenkov
#if defined(__APPLE__) && defined(__MACH__)
513 83f64091 bellard
        size = LONG_LONG_MAX;
514 83f64091 bellard
#else
515 83f64091 bellard
        size = lseek(fd, 0LL, SEEK_END);
516 83f64091 bellard
#endif
517 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
518 9f23011a blueswir1
        switch(s->type) {
519 9f23011a blueswir1
        case FTYPE_CD:
520 9f23011a blueswir1
            /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
521 9f23011a blueswir1
            if (size == 2048LL * (unsigned)-1)
522 9f23011a blueswir1
                size = 0;
523 9f23011a blueswir1
            /* XXX no disc?  maybe we need to reopen... */
524 f3a5d3f8 Christoph Hellwig
            if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
525 9f23011a blueswir1
                reopened = 1;
526 9f23011a blueswir1
                goto again;
527 9f23011a blueswir1
            }
528 9f23011a blueswir1
        }
529 9f23011a blueswir1
#endif
530 50779cc2 Christoph Hellwig
    } else {
531 83f64091 bellard
        size = lseek(fd, 0, SEEK_END);
532 83f64091 bellard
    }
533 83f64091 bellard
    return size;
534 83f64091 bellard
}
535 50779cc2 Christoph Hellwig
#else
536 50779cc2 Christoph Hellwig
static int64_t raw_getlength(BlockDriverState *bs)
537 50779cc2 Christoph Hellwig
{
538 50779cc2 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
539 50779cc2 Christoph Hellwig
    int ret;
540 50779cc2 Christoph Hellwig
541 50779cc2 Christoph Hellwig
    ret = fd_open(bs);
542 50779cc2 Christoph Hellwig
    if (ret < 0) {
543 50779cc2 Christoph Hellwig
        return ret;
544 50779cc2 Christoph Hellwig
    }
545 50779cc2 Christoph Hellwig
546 50779cc2 Christoph Hellwig
    return lseek(s->fd, 0, SEEK_END);
547 50779cc2 Christoph Hellwig
}
548 128ab2ff blueswir1
#endif
549 83f64091 bellard
550 4a1d5e1f Fam Zheng
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
551 4a1d5e1f Fam Zheng
{
552 4a1d5e1f Fam Zheng
    struct stat st;
553 4a1d5e1f Fam Zheng
    BDRVRawState *s = bs->opaque;
554 4a1d5e1f Fam Zheng
555 4a1d5e1f Fam Zheng
    if (fstat(s->fd, &st) < 0) {
556 4a1d5e1f Fam Zheng
        return -errno;
557 4a1d5e1f Fam Zheng
    }
558 4a1d5e1f Fam Zheng
    return (int64_t)st.st_blocks * 512;
559 4a1d5e1f Fam Zheng
}
560 4a1d5e1f Fam Zheng
561 0e7e1989 Kevin Wolf
static int raw_create(const char *filename, QEMUOptionParameter *options)
562 83f64091 bellard
{
563 83f64091 bellard
    int fd;
564 1e37d059 Stefan Weil
    int result = 0;
565 0e7e1989 Kevin Wolf
    int64_t total_size = 0;
566 83f64091 bellard
567 0e7e1989 Kevin Wolf
    /* Read out options */
568 0e7e1989 Kevin Wolf
    while (options && options->name) {
569 0e7e1989 Kevin Wolf
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
570 9040385d Jes Sorensen
            total_size = options->value.n / BDRV_SECTOR_SIZE;
571 0e7e1989 Kevin Wolf
        }
572 0e7e1989 Kevin Wolf
        options++;
573 0e7e1989 Kevin Wolf
    }
574 83f64091 bellard
575 6165f4d8 Corey Bryant
    fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
576 6165f4d8 Corey Bryant
                   0644);
577 1e37d059 Stefan Weil
    if (fd < 0) {
578 1e37d059 Stefan Weil
        result = -errno;
579 1e37d059 Stefan Weil
    } else {
580 9040385d Jes Sorensen
        if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
581 1e37d059 Stefan Weil
            result = -errno;
582 1e37d059 Stefan Weil
        }
583 2e1e79da Corey Bryant
        if (qemu_close(fd) != 0) {
584 1e37d059 Stefan Weil
            result = -errno;
585 1e37d059 Stefan Weil
        }
586 1e37d059 Stefan Weil
    }
587 1e37d059 Stefan Weil
    return result;
588 83f64091 bellard
}
589 83f64091 bellard
590 5500316d Paolo Bonzini
/*
591 5500316d Paolo Bonzini
 * Returns true iff the specified sector is present in the disk image. Drivers
592 5500316d Paolo Bonzini
 * not implementing the functionality are assumed to not support backing files,
593 5500316d Paolo Bonzini
 * hence all their sectors are reported as allocated.
594 5500316d Paolo Bonzini
 *
595 5500316d Paolo Bonzini
 * If 'sector_num' is beyond the end of the disk image the return value is 0
596 5500316d Paolo Bonzini
 * and 'pnum' is set to 0.
597 5500316d Paolo Bonzini
 *
598 5500316d Paolo Bonzini
 * 'pnum' is set to the number of sectors (including and immediately following
599 5500316d Paolo Bonzini
 * the specified sector) that are known to be in the same
600 5500316d Paolo Bonzini
 * allocated/unallocated state.
601 5500316d Paolo Bonzini
 *
602 5500316d Paolo Bonzini
 * 'nb_sectors' is the max value 'pnum' should be set to.  If nb_sectors goes
603 5500316d Paolo Bonzini
 * beyond the end of the disk image it will be clamped.
604 5500316d Paolo Bonzini
 */
605 5500316d Paolo Bonzini
static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs,
606 5500316d Paolo Bonzini
                                            int64_t sector_num,
607 5500316d Paolo Bonzini
                                            int nb_sectors, int *pnum)
608 5500316d Paolo Bonzini
{
609 5500316d Paolo Bonzini
    off_t start, data, hole;
610 5500316d Paolo Bonzini
    int ret;
611 5500316d Paolo Bonzini
612 5500316d Paolo Bonzini
    ret = fd_open(bs);
613 5500316d Paolo Bonzini
    if (ret < 0) {
614 5500316d Paolo Bonzini
        return ret;
615 5500316d Paolo Bonzini
    }
616 5500316d Paolo Bonzini
617 5500316d Paolo Bonzini
    start = sector_num * BDRV_SECTOR_SIZE;
618 94282e71 Kevin Wolf
619 5500316d Paolo Bonzini
#ifdef CONFIG_FIEMAP
620 94282e71 Kevin Wolf
621 94282e71 Kevin Wolf
    BDRVRawState *s = bs->opaque;
622 5500316d Paolo Bonzini
    struct {
623 5500316d Paolo Bonzini
        struct fiemap fm;
624 5500316d Paolo Bonzini
        struct fiemap_extent fe;
625 5500316d Paolo Bonzini
    } f;
626 94282e71 Kevin Wolf
627 5500316d Paolo Bonzini
    f.fm.fm_start = start;
628 5500316d Paolo Bonzini
    f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
629 5500316d Paolo Bonzini
    f.fm.fm_flags = 0;
630 5500316d Paolo Bonzini
    f.fm.fm_extent_count = 1;
631 5500316d Paolo Bonzini
    f.fm.fm_reserved = 0;
632 5500316d Paolo Bonzini
    if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
633 5500316d Paolo Bonzini
        /* Assume everything is allocated.  */
634 5500316d Paolo Bonzini
        *pnum = nb_sectors;
635 5500316d Paolo Bonzini
        return 1;
636 5500316d Paolo Bonzini
    }
637 5500316d Paolo Bonzini
638 5500316d Paolo Bonzini
    if (f.fm.fm_mapped_extents == 0) {
639 5500316d Paolo Bonzini
        /* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
640 5500316d Paolo Bonzini
         * f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
641 5500316d Paolo Bonzini
         */
642 5500316d Paolo Bonzini
        off_t length = lseek(s->fd, 0, SEEK_END);
643 5500316d Paolo Bonzini
        hole = f.fm.fm_start;
644 5500316d Paolo Bonzini
        data = MIN(f.fm.fm_start + f.fm.fm_length, length);
645 5500316d Paolo Bonzini
    } else {
646 5500316d Paolo Bonzini
        data = f.fe.fe_logical;
647 5500316d Paolo Bonzini
        hole = f.fe.fe_logical + f.fe.fe_length;
648 5500316d Paolo Bonzini
    }
649 94282e71 Kevin Wolf
650 5500316d Paolo Bonzini
#elif defined SEEK_HOLE && defined SEEK_DATA
651 94282e71 Kevin Wolf
652 94282e71 Kevin Wolf
    BDRVRawState *s = bs->opaque;
653 94282e71 Kevin Wolf
654 5500316d Paolo Bonzini
    hole = lseek(s->fd, start, SEEK_HOLE);
655 5500316d Paolo Bonzini
    if (hole == -1) {
656 5500316d Paolo Bonzini
        /* -ENXIO indicates that sector_num was past the end of the file.
657 5500316d Paolo Bonzini
         * There is a virtual hole there.  */
658 5500316d Paolo Bonzini
        assert(errno != -ENXIO);
659 5500316d Paolo Bonzini
660 5500316d Paolo Bonzini
        /* Most likely EINVAL.  Assume everything is allocated.  */
661 5500316d Paolo Bonzini
        *pnum = nb_sectors;
662 5500316d Paolo Bonzini
        return 1;
663 5500316d Paolo Bonzini
    }
664 5500316d Paolo Bonzini
665 5500316d Paolo Bonzini
    if (hole > start) {
666 5500316d Paolo Bonzini
        data = start;
667 5500316d Paolo Bonzini
    } else {
668 5500316d Paolo Bonzini
        /* On a hole.  We need another syscall to find its end.  */
669 5500316d Paolo Bonzini
        data = lseek(s->fd, start, SEEK_DATA);
670 5500316d Paolo Bonzini
        if (data == -1) {
671 5500316d Paolo Bonzini
            data = lseek(s->fd, 0, SEEK_END);
672 5500316d Paolo Bonzini
        }
673 5500316d Paolo Bonzini
    }
674 5500316d Paolo Bonzini
#else
675 5500316d Paolo Bonzini
    *pnum = nb_sectors;
676 5500316d Paolo Bonzini
    return 1;
677 5500316d Paolo Bonzini
#endif
678 5500316d Paolo Bonzini
679 5500316d Paolo Bonzini
    if (data <= start) {
680 5500316d Paolo Bonzini
        /* On a data extent, compute sectors to the end of the extent.  */
681 5500316d Paolo Bonzini
        *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
682 5500316d Paolo Bonzini
        return 1;
683 5500316d Paolo Bonzini
    } else {
684 5500316d Paolo Bonzini
        /* On a hole, compute sectors to the beginning of the next extent.  */
685 5500316d Paolo Bonzini
        *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
686 5500316d Paolo Bonzini
        return 0;
687 5500316d Paolo Bonzini
    }
688 5500316d Paolo Bonzini
}
689 5500316d Paolo Bonzini
690 dce512de Christoph Hellwig
#ifdef CONFIG_XFS
691 dce512de Christoph Hellwig
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
692 dce512de Christoph Hellwig
{
693 dce512de Christoph Hellwig
    struct xfs_flock64 fl;
694 dce512de Christoph Hellwig
695 dce512de Christoph Hellwig
    memset(&fl, 0, sizeof(fl));
696 dce512de Christoph Hellwig
    fl.l_whence = SEEK_SET;
697 dce512de Christoph Hellwig
    fl.l_start = sector_num << 9;
698 dce512de Christoph Hellwig
    fl.l_len = (int64_t)nb_sectors << 9;
699 dce512de Christoph Hellwig
700 dce512de Christoph Hellwig
    if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
701 dce512de Christoph Hellwig
        DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
702 dce512de Christoph Hellwig
        return -errno;
703 dce512de Christoph Hellwig
    }
704 dce512de Christoph Hellwig
705 dce512de Christoph Hellwig
    return 0;
706 dce512de Christoph Hellwig
}
707 dce512de Christoph Hellwig
#endif
708 dce512de Christoph Hellwig
709 6db39ae2 Paolo Bonzini
static coroutine_fn int raw_co_discard(BlockDriverState *bs,
710 6db39ae2 Paolo Bonzini
    int64_t sector_num, int nb_sectors)
711 dce512de Christoph Hellwig
{
712 dce512de Christoph Hellwig
#ifdef CONFIG_XFS
713 dce512de Christoph Hellwig
    BDRVRawState *s = bs->opaque;
714 dce512de Christoph Hellwig
715 dce512de Christoph Hellwig
    if (s->is_xfs) {
716 dce512de Christoph Hellwig
        return xfs_discard(s, sector_num, nb_sectors);
717 dce512de Christoph Hellwig
    }
718 dce512de Christoph Hellwig
#endif
719 dce512de Christoph Hellwig
720 dce512de Christoph Hellwig
    return 0;
721 dce512de Christoph Hellwig
}
722 0e7e1989 Kevin Wolf
723 0e7e1989 Kevin Wolf
static QEMUOptionParameter raw_create_options[] = {
724 db08adf5 Kevin Wolf
    {
725 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_SIZE,
726 db08adf5 Kevin Wolf
        .type = OPT_SIZE,
727 db08adf5 Kevin Wolf
        .help = "Virtual disk size"
728 db08adf5 Kevin Wolf
    },
729 0e7e1989 Kevin Wolf
    { NULL }
730 0e7e1989 Kevin Wolf
};
731 0e7e1989 Kevin Wolf
732 84a12e66 Christoph Hellwig
static BlockDriver bdrv_file = {
733 84a12e66 Christoph Hellwig
    .format_name = "file",
734 84a12e66 Christoph Hellwig
    .protocol_name = "file",
735 856ae5c3 blueswir1
    .instance_size = sizeof(BDRVRawState),
736 856ae5c3 blueswir1
    .bdrv_probe = NULL, /* no probe for protocols */
737 66f82cee Kevin Wolf
    .bdrv_file_open = raw_open,
738 856ae5c3 blueswir1
    .bdrv_close = raw_close,
739 856ae5c3 blueswir1
    .bdrv_create = raw_create,
740 6db39ae2 Paolo Bonzini
    .bdrv_co_discard = raw_co_discard,
741 5500316d Paolo Bonzini
    .bdrv_co_is_allocated = raw_co_is_allocated,
742 3b46e624 ths
743 f141eafe aliguori
    .bdrv_aio_readv = raw_aio_readv,
744 f141eafe aliguori
    .bdrv_aio_writev = raw_aio_writev,
745 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush = raw_aio_flush,
746 3c529d93 aliguori
747 83f64091 bellard
    .bdrv_truncate = raw_truncate,
748 83f64091 bellard
    .bdrv_getlength = raw_getlength,
749 4a1d5e1f Fam Zheng
    .bdrv_get_allocated_file_size
750 4a1d5e1f Fam Zheng
                        = raw_get_allocated_file_size,
751 0e7e1989 Kevin Wolf
752 0e7e1989 Kevin Wolf
    .create_options = raw_create_options,
753 83f64091 bellard
};
754 83f64091 bellard
755 19cb3738 bellard
/***********************************************/
756 19cb3738 bellard
/* host device */
757 19cb3738 bellard
758 83affaa6 Pavel Borzenkov
#if defined(__APPLE__) && defined(__MACH__)
759 19cb3738 bellard
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
760 19cb3738 bellard
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
761 19cb3738 bellard
762 19cb3738 bellard
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
763 19cb3738 bellard
{
764 5fafdf24 ths
    kern_return_t       kernResult;
765 19cb3738 bellard
    mach_port_t     masterPort;
766 19cb3738 bellard
    CFMutableDictionaryRef  classesToMatch;
767 19cb3738 bellard
768 19cb3738 bellard
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
769 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult ) {
770 19cb3738 bellard
        printf( "IOMasterPort returned %d\n", kernResult );
771 19cb3738 bellard
    }
772 3b46e624 ths
773 5fafdf24 ths
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
774 19cb3738 bellard
    if ( classesToMatch == NULL ) {
775 19cb3738 bellard
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
776 19cb3738 bellard
    } else {
777 19cb3738 bellard
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
778 19cb3738 bellard
    }
779 19cb3738 bellard
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
780 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult )
781 19cb3738 bellard
    {
782 19cb3738 bellard
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
783 19cb3738 bellard
    }
784 3b46e624 ths
785 19cb3738 bellard
    return kernResult;
786 19cb3738 bellard
}
787 19cb3738 bellard
788 19cb3738 bellard
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
789 19cb3738 bellard
{
790 19cb3738 bellard
    io_object_t     nextMedia;
791 19cb3738 bellard
    kern_return_t   kernResult = KERN_FAILURE;
792 19cb3738 bellard
    *bsdPath = '\0';
793 19cb3738 bellard
    nextMedia = IOIteratorNext( mediaIterator );
794 19cb3738 bellard
    if ( nextMedia )
795 19cb3738 bellard
    {
796 19cb3738 bellard
        CFTypeRef   bsdPathAsCFString;
797 19cb3738 bellard
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
798 19cb3738 bellard
        if ( bsdPathAsCFString ) {
799 19cb3738 bellard
            size_t devPathLength;
800 19cb3738 bellard
            strcpy( bsdPath, _PATH_DEV );
801 19cb3738 bellard
            strcat( bsdPath, "r" );
802 19cb3738 bellard
            devPathLength = strlen( bsdPath );
803 19cb3738 bellard
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
804 19cb3738 bellard
                kernResult = KERN_SUCCESS;
805 19cb3738 bellard
            }
806 19cb3738 bellard
            CFRelease( bsdPathAsCFString );
807 19cb3738 bellard
        }
808 19cb3738 bellard
        IOObjectRelease( nextMedia );
809 19cb3738 bellard
    }
810 3b46e624 ths
811 19cb3738 bellard
    return kernResult;
812 19cb3738 bellard
}
813 19cb3738 bellard
814 19cb3738 bellard
#endif
815 19cb3738 bellard
816 508c7cb3 Christoph Hellwig
static int hdev_probe_device(const char *filename)
817 508c7cb3 Christoph Hellwig
{
818 508c7cb3 Christoph Hellwig
    struct stat st;
819 508c7cb3 Christoph Hellwig
820 508c7cb3 Christoph Hellwig
    /* allow a dedicated CD-ROM driver to match with a higher priority */
821 508c7cb3 Christoph Hellwig
    if (strstart(filename, "/dev/cdrom", NULL))
822 508c7cb3 Christoph Hellwig
        return 50;
823 508c7cb3 Christoph Hellwig
824 508c7cb3 Christoph Hellwig
    if (stat(filename, &st) >= 0 &&
825 508c7cb3 Christoph Hellwig
            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
826 508c7cb3 Christoph Hellwig
        return 100;
827 508c7cb3 Christoph Hellwig
    }
828 508c7cb3 Christoph Hellwig
829 508c7cb3 Christoph Hellwig
    return 0;
830 508c7cb3 Christoph Hellwig
}
831 508c7cb3 Christoph Hellwig
832 19cb3738 bellard
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
833 19cb3738 bellard
{
834 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
835 a76bab49 aliguori
836 83affaa6 Pavel Borzenkov
#if defined(__APPLE__) && defined(__MACH__)
837 19cb3738 bellard
    if (strstart(filename, "/dev/cdrom", NULL)) {
838 19cb3738 bellard
        kern_return_t kernResult;
839 19cb3738 bellard
        io_iterator_t mediaIterator;
840 19cb3738 bellard
        char bsdPath[ MAXPATHLEN ];
841 19cb3738 bellard
        int fd;
842 5fafdf24 ths
843 19cb3738 bellard
        kernResult = FindEjectableCDMedia( &mediaIterator );
844 19cb3738 bellard
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
845 3b46e624 ths
846 19cb3738 bellard
        if ( bsdPath[ 0 ] != '\0' ) {
847 19cb3738 bellard
            strcat(bsdPath,"s0");
848 19cb3738 bellard
            /* some CDs don't have a partition 0 */
849 6165f4d8 Corey Bryant
            fd = qemu_open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
850 19cb3738 bellard
            if (fd < 0) {
851 19cb3738 bellard
                bsdPath[strlen(bsdPath)-1] = '1';
852 19cb3738 bellard
            } else {
853 2e1e79da Corey Bryant
                qemu_close(fd);
854 19cb3738 bellard
            }
855 19cb3738 bellard
            filename = bsdPath;
856 19cb3738 bellard
        }
857 3b46e624 ths
858 19cb3738 bellard
        if ( mediaIterator )
859 19cb3738 bellard
            IOObjectRelease( mediaIterator );
860 19cb3738 bellard
    }
861 19cb3738 bellard
#endif
862 19cb3738 bellard
863 19cb3738 bellard
    s->type = FTYPE_FILE;
864 4dd75c70 Christoph Hellwig
#if defined(__linux__)
865 05acda4d Bernhard Kohl
    {
866 05acda4d Bernhard Kohl
        char resolved_path[ MAXPATHLEN ], *temp;
867 05acda4d Bernhard Kohl
868 05acda4d Bernhard Kohl
        temp = realpath(filename, resolved_path);
869 05acda4d Bernhard Kohl
        if (temp && strstart(temp, "/dev/sg", NULL)) {
870 05acda4d Bernhard Kohl
            bs->sg = 1;
871 05acda4d Bernhard Kohl
        }
872 19cb3738 bellard
    }
873 19cb3738 bellard
#endif
874 90babde0 Christoph Hellwig
875 19a3da7f Blue Swirl
    return raw_open_common(bs, filename, flags, 0);
876 19cb3738 bellard
}
877 19cb3738 bellard
878 03ff3ca3 aliguori
#if defined(__linux__)
879 19cb3738 bellard
/* Note: we do not have a reliable method to detect if the floppy is
880 19cb3738 bellard
   present. The current method is to try to open the floppy at every
881 19cb3738 bellard
   I/O and to keep it opened during a few hundreds of ms. */
882 19cb3738 bellard
static int fd_open(BlockDriverState *bs)
883 19cb3738 bellard
{
884 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
885 19cb3738 bellard
    int last_media_present;
886 19cb3738 bellard
887 19cb3738 bellard
    if (s->type != FTYPE_FD)
888 19cb3738 bellard
        return 0;
889 19cb3738 bellard
    last_media_present = (s->fd >= 0);
890 5fafdf24 ths
    if (s->fd >= 0 &&
891 c57c846a Blue Swirl
        (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
892 2e1e79da Corey Bryant
        qemu_close(s->fd);
893 19cb3738 bellard
        s->fd = -1;
894 19cb3738 bellard
#ifdef DEBUG_FLOPPY
895 19cb3738 bellard
        printf("Floppy closed\n");
896 19cb3738 bellard
#endif
897 19cb3738 bellard
    }
898 19cb3738 bellard
    if (s->fd < 0) {
899 5fafdf24 ths
        if (s->fd_got_error &&
900 c57c846a Blue Swirl
            (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) {
901 19cb3738 bellard
#ifdef DEBUG_FLOPPY
902 19cb3738 bellard
            printf("No floppy (open delayed)\n");
903 19cb3738 bellard
#endif
904 19cb3738 bellard
            return -EIO;
905 19cb3738 bellard
        }
906 6165f4d8 Corey Bryant
        s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK);
907 19cb3738 bellard
        if (s->fd < 0) {
908 c57c846a Blue Swirl
            s->fd_error_time = get_clock();
909 19cb3738 bellard
            s->fd_got_error = 1;
910 19cb3738 bellard
            if (last_media_present)
911 19cb3738 bellard
                s->fd_media_changed = 1;
912 19cb3738 bellard
#ifdef DEBUG_FLOPPY
913 19cb3738 bellard
            printf("No floppy\n");
914 19cb3738 bellard
#endif
915 19cb3738 bellard
            return -EIO;
916 19cb3738 bellard
        }
917 19cb3738 bellard
#ifdef DEBUG_FLOPPY
918 19cb3738 bellard
        printf("Floppy opened\n");
919 19cb3738 bellard
#endif
920 19cb3738 bellard
    }
921 19cb3738 bellard
    if (!last_media_present)
922 19cb3738 bellard
        s->fd_media_changed = 1;
923 c57c846a Blue Swirl
    s->fd_open_time = get_clock();
924 19cb3738 bellard
    s->fd_got_error = 0;
925 19cb3738 bellard
    return 0;
926 19cb3738 bellard
}
927 19cb3738 bellard
928 63ec93db Christoph Hellwig
static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
929 985a03b0 ths
{
930 985a03b0 ths
    BDRVRawState *s = bs->opaque;
931 985a03b0 ths
932 985a03b0 ths
    return ioctl(s->fd, req, buf);
933 985a03b0 ths
}
934 221f715d aliguori
935 63ec93db Christoph Hellwig
static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
936 221f715d aliguori
        unsigned long int req, void *buf,
937 221f715d aliguori
        BlockDriverCompletionFunc *cb, void *opaque)
938 221f715d aliguori
{
939 f141eafe aliguori
    BDRVRawState *s = bs->opaque;
940 221f715d aliguori
941 f141eafe aliguori
    if (fd_open(bs) < 0)
942 f141eafe aliguori
        return NULL;
943 9ef91a67 Christoph Hellwig
    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
944 221f715d aliguori
}
945 221f715d aliguori
946 a167ba50 Aurelien Jarno
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
947 9f23011a blueswir1
static int fd_open(BlockDriverState *bs)
948 9f23011a blueswir1
{
949 9f23011a blueswir1
    BDRVRawState *s = bs->opaque;
950 9f23011a blueswir1
951 9f23011a blueswir1
    /* this is just to ensure s->fd is sane (its called by io ops) */
952 9f23011a blueswir1
    if (s->fd >= 0)
953 9f23011a blueswir1
        return 0;
954 9f23011a blueswir1
    return -EIO;
955 9f23011a blueswir1
}
956 9f23011a blueswir1
#else /* !linux && !FreeBSD */
957 19cb3738 bellard
958 08af02e2 aliguori
static int fd_open(BlockDriverState *bs)
959 08af02e2 aliguori
{
960 08af02e2 aliguori
    return 0;
961 08af02e2 aliguori
}
962 08af02e2 aliguori
963 221f715d aliguori
#endif /* !linux && !FreeBSD */
964 04eeb8b6 aliguori
965 0e7e1989 Kevin Wolf
static int hdev_create(const char *filename, QEMUOptionParameter *options)
966 93c65b47 aliguori
{
967 93c65b47 aliguori
    int fd;
968 93c65b47 aliguori
    int ret = 0;
969 93c65b47 aliguori
    struct stat stat_buf;
970 0e7e1989 Kevin Wolf
    int64_t total_size = 0;
971 93c65b47 aliguori
972 0e7e1989 Kevin Wolf
    /* Read out options */
973 0e7e1989 Kevin Wolf
    while (options && options->name) {
974 0e7e1989 Kevin Wolf
        if (!strcmp(options->name, "size")) {
975 9040385d Jes Sorensen
            total_size = options->value.n / BDRV_SECTOR_SIZE;
976 0e7e1989 Kevin Wolf
        }
977 0e7e1989 Kevin Wolf
        options++;
978 0e7e1989 Kevin Wolf
    }
979 93c65b47 aliguori
980 6165f4d8 Corey Bryant
    fd = qemu_open(filename, O_WRONLY | O_BINARY);
981 93c65b47 aliguori
    if (fd < 0)
982 57e69b7d Kevin Wolf
        return -errno;
983 93c65b47 aliguori
984 93c65b47 aliguori
    if (fstat(fd, &stat_buf) < 0)
985 57e69b7d Kevin Wolf
        ret = -errno;
986 4099df58 Christoph Hellwig
    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
987 57e69b7d Kevin Wolf
        ret = -ENODEV;
988 9040385d Jes Sorensen
    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
989 93c65b47 aliguori
        ret = -ENOSPC;
990 93c65b47 aliguori
991 2e1e79da Corey Bryant
    qemu_close(fd);
992 93c65b47 aliguori
    return ret;
993 93c65b47 aliguori
}
994 93c65b47 aliguori
995 336c1c12 Kevin Wolf
static int hdev_has_zero_init(BlockDriverState *bs)
996 336c1c12 Kevin Wolf
{
997 336c1c12 Kevin Wolf
    return 0;
998 336c1c12 Kevin Wolf
}
999 336c1c12 Kevin Wolf
1000 5efa9d5a Anthony Liguori
static BlockDriver bdrv_host_device = {
1001 0b4ce02e Kevin Wolf
    .format_name        = "host_device",
1002 84a12e66 Christoph Hellwig
    .protocol_name        = "host_device",
1003 0b4ce02e Kevin Wolf
    .instance_size      = sizeof(BDRVRawState),
1004 0b4ce02e Kevin Wolf
    .bdrv_probe_device  = hdev_probe_device,
1005 66f82cee Kevin Wolf
    .bdrv_file_open     = hdev_open,
1006 0b4ce02e Kevin Wolf
    .bdrv_close         = raw_close,
1007 93c65b47 aliguori
    .bdrv_create        = hdev_create,
1008 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1009 336c1c12 Kevin Wolf
    .bdrv_has_zero_init = hdev_has_zero_init,
1010 3b46e624 ths
1011 f141eafe aliguori
    .bdrv_aio_readv        = raw_aio_readv,
1012 f141eafe aliguori
    .bdrv_aio_writev        = raw_aio_writev,
1013 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1014 3c529d93 aliguori
1015 55b949c8 Christoph Hellwig
    .bdrv_truncate      = raw_truncate,
1016 e60f469c aurel32
    .bdrv_getlength        = raw_getlength,
1017 4a1d5e1f Fam Zheng
    .bdrv_get_allocated_file_size
1018 4a1d5e1f Fam Zheng
                        = raw_get_allocated_file_size,
1019 19cb3738 bellard
1020 f3a5d3f8 Christoph Hellwig
    /* generic scsi device */
1021 63ec93db Christoph Hellwig
#ifdef __linux__
1022 63ec93db Christoph Hellwig
    .bdrv_ioctl         = hdev_ioctl,
1023 63ec93db Christoph Hellwig
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1024 63ec93db Christoph Hellwig
#endif
1025 f3a5d3f8 Christoph Hellwig
};
1026 f3a5d3f8 Christoph Hellwig
1027 f3a5d3f8 Christoph Hellwig
#ifdef __linux__
1028 f3a5d3f8 Christoph Hellwig
static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1029 f3a5d3f8 Christoph Hellwig
{
1030 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1031 f3a5d3f8 Christoph Hellwig
    int ret;
1032 f3a5d3f8 Christoph Hellwig
1033 f3a5d3f8 Christoph Hellwig
    s->type = FTYPE_FD;
1034 f3a5d3f8 Christoph Hellwig
1035 19a3da7f Blue Swirl
    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1036 19a3da7f Blue Swirl
    ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
1037 f3a5d3f8 Christoph Hellwig
    if (ret)
1038 f3a5d3f8 Christoph Hellwig
        return ret;
1039 f3a5d3f8 Christoph Hellwig
1040 f3a5d3f8 Christoph Hellwig
    /* close fd so that we can reopen it as needed */
1041 2e1e79da Corey Bryant
    qemu_close(s->fd);
1042 f3a5d3f8 Christoph Hellwig
    s->fd = -1;
1043 f3a5d3f8 Christoph Hellwig
    s->fd_media_changed = 1;
1044 f3a5d3f8 Christoph Hellwig
1045 f3a5d3f8 Christoph Hellwig
    return 0;
1046 f3a5d3f8 Christoph Hellwig
}
1047 f3a5d3f8 Christoph Hellwig
1048 508c7cb3 Christoph Hellwig
static int floppy_probe_device(const char *filename)
1049 508c7cb3 Christoph Hellwig
{
1050 2ebf7c4b Cole Robinson
    int fd, ret;
1051 2ebf7c4b Cole Robinson
    int prio = 0;
1052 2ebf7c4b Cole Robinson
    struct floppy_struct fdparam;
1053 343f8568 Johannes Stezenbach
    struct stat st;
1054 2ebf7c4b Cole Robinson
1055 e1740828 Corey Bryant
    if (strstart(filename, "/dev/fd", NULL) &&
1056 e1740828 Corey Bryant
        !strstart(filename, "/dev/fdset/", NULL)) {
1057 2ebf7c4b Cole Robinson
        prio = 50;
1058 e1740828 Corey Bryant
    }
1059 2ebf7c4b Cole Robinson
1060 6165f4d8 Corey Bryant
    fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
1061 2ebf7c4b Cole Robinson
    if (fd < 0) {
1062 2ebf7c4b Cole Robinson
        goto out;
1063 2ebf7c4b Cole Robinson
    }
1064 343f8568 Johannes Stezenbach
    ret = fstat(fd, &st);
1065 343f8568 Johannes Stezenbach
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
1066 343f8568 Johannes Stezenbach
        goto outc;
1067 343f8568 Johannes Stezenbach
    }
1068 2ebf7c4b Cole Robinson
1069 2ebf7c4b Cole Robinson
    /* Attempt to detect via a floppy specific ioctl */
1070 2ebf7c4b Cole Robinson
    ret = ioctl(fd, FDGETPRM, &fdparam);
1071 2ebf7c4b Cole Robinson
    if (ret >= 0)
1072 2ebf7c4b Cole Robinson
        prio = 100;
1073 2ebf7c4b Cole Robinson
1074 343f8568 Johannes Stezenbach
outc:
1075 2e1e79da Corey Bryant
    qemu_close(fd);
1076 2ebf7c4b Cole Robinson
out:
1077 2ebf7c4b Cole Robinson
    return prio;
1078 508c7cb3 Christoph Hellwig
}
1079 508c7cb3 Christoph Hellwig
1080 508c7cb3 Christoph Hellwig
1081 f3a5d3f8 Christoph Hellwig
static int floppy_is_inserted(BlockDriverState *bs)
1082 f3a5d3f8 Christoph Hellwig
{
1083 f3a5d3f8 Christoph Hellwig
    return fd_open(bs) >= 0;
1084 f3a5d3f8 Christoph Hellwig
}
1085 f3a5d3f8 Christoph Hellwig
1086 f3a5d3f8 Christoph Hellwig
static int floppy_media_changed(BlockDriverState *bs)
1087 f3a5d3f8 Christoph Hellwig
{
1088 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1089 f3a5d3f8 Christoph Hellwig
    int ret;
1090 f3a5d3f8 Christoph Hellwig
1091 f3a5d3f8 Christoph Hellwig
    /*
1092 f3a5d3f8 Christoph Hellwig
     * XXX: we do not have a true media changed indication.
1093 f3a5d3f8 Christoph Hellwig
     * It does not work if the floppy is changed without trying to read it.
1094 f3a5d3f8 Christoph Hellwig
     */
1095 f3a5d3f8 Christoph Hellwig
    fd_open(bs);
1096 f3a5d3f8 Christoph Hellwig
    ret = s->fd_media_changed;
1097 f3a5d3f8 Christoph Hellwig
    s->fd_media_changed = 0;
1098 f3a5d3f8 Christoph Hellwig
#ifdef DEBUG_FLOPPY
1099 f3a5d3f8 Christoph Hellwig
    printf("Floppy changed=%d\n", ret);
1100 f3a5d3f8 Christoph Hellwig
#endif
1101 f3a5d3f8 Christoph Hellwig
    return ret;
1102 f3a5d3f8 Christoph Hellwig
}
1103 f3a5d3f8 Christoph Hellwig
1104 f36f3949 Luiz Capitulino
static void floppy_eject(BlockDriverState *bs, bool eject_flag)
1105 f3a5d3f8 Christoph Hellwig
{
1106 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1107 f3a5d3f8 Christoph Hellwig
    int fd;
1108 f3a5d3f8 Christoph Hellwig
1109 f3a5d3f8 Christoph Hellwig
    if (s->fd >= 0) {
1110 2e1e79da Corey Bryant
        qemu_close(s->fd);
1111 f3a5d3f8 Christoph Hellwig
        s->fd = -1;
1112 f3a5d3f8 Christoph Hellwig
    }
1113 6165f4d8 Corey Bryant
    fd = qemu_open(bs->filename, s->open_flags | O_NONBLOCK);
1114 f3a5d3f8 Christoph Hellwig
    if (fd >= 0) {
1115 f3a5d3f8 Christoph Hellwig
        if (ioctl(fd, FDEJECT, 0) < 0)
1116 f3a5d3f8 Christoph Hellwig
            perror("FDEJECT");
1117 2e1e79da Corey Bryant
        qemu_close(fd);
1118 f3a5d3f8 Christoph Hellwig
    }
1119 f3a5d3f8 Christoph Hellwig
}
1120 f3a5d3f8 Christoph Hellwig
1121 f3a5d3f8 Christoph Hellwig
static BlockDriver bdrv_host_floppy = {
1122 f3a5d3f8 Christoph Hellwig
    .format_name        = "host_floppy",
1123 84a12e66 Christoph Hellwig
    .protocol_name      = "host_floppy",
1124 f3a5d3f8 Christoph Hellwig
    .instance_size      = sizeof(BDRVRawState),
1125 508c7cb3 Christoph Hellwig
    .bdrv_probe_device        = floppy_probe_device,
1126 66f82cee Kevin Wolf
    .bdrv_file_open     = floppy_open,
1127 f3a5d3f8 Christoph Hellwig
    .bdrv_close         = raw_close,
1128 f3a5d3f8 Christoph Hellwig
    .bdrv_create        = hdev_create,
1129 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1130 336c1c12 Kevin Wolf
    .bdrv_has_zero_init = hdev_has_zero_init,
1131 f3a5d3f8 Christoph Hellwig
1132 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_readv     = raw_aio_readv,
1133 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_writev    = raw_aio_writev,
1134 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1135 f3a5d3f8 Christoph Hellwig
1136 55b949c8 Christoph Hellwig
    .bdrv_truncate      = raw_truncate,
1137 f3a5d3f8 Christoph Hellwig
    .bdrv_getlength        = raw_getlength,
1138 4a1d5e1f Fam Zheng
    .bdrv_get_allocated_file_size
1139 4a1d5e1f Fam Zheng
                        = raw_get_allocated_file_size,
1140 f3a5d3f8 Christoph Hellwig
1141 f3a5d3f8 Christoph Hellwig
    /* removable device support */
1142 f3a5d3f8 Christoph Hellwig
    .bdrv_is_inserted   = floppy_is_inserted,
1143 f3a5d3f8 Christoph Hellwig
    .bdrv_media_changed = floppy_media_changed,
1144 f3a5d3f8 Christoph Hellwig
    .bdrv_eject         = floppy_eject,
1145 f3a5d3f8 Christoph Hellwig
};
1146 f3a5d3f8 Christoph Hellwig
1147 f3a5d3f8 Christoph Hellwig
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1148 f3a5d3f8 Christoph Hellwig
{
1149 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1150 f3a5d3f8 Christoph Hellwig
1151 f3a5d3f8 Christoph Hellwig
    s->type = FTYPE_CD;
1152 f3a5d3f8 Christoph Hellwig
1153 19a3da7f Blue Swirl
    /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1154 19a3da7f Blue Swirl
    return raw_open_common(bs, filename, flags, O_NONBLOCK);
1155 f3a5d3f8 Christoph Hellwig
}
1156 f3a5d3f8 Christoph Hellwig
1157 508c7cb3 Christoph Hellwig
static int cdrom_probe_device(const char *filename)
1158 508c7cb3 Christoph Hellwig
{
1159 3baf720e Cole Robinson
    int fd, ret;
1160 3baf720e Cole Robinson
    int prio = 0;
1161 343f8568 Johannes Stezenbach
    struct stat st;
1162 3baf720e Cole Robinson
1163 6165f4d8 Corey Bryant
    fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
1164 3baf720e Cole Robinson
    if (fd < 0) {
1165 3baf720e Cole Robinson
        goto out;
1166 3baf720e Cole Robinson
    }
1167 343f8568 Johannes Stezenbach
    ret = fstat(fd, &st);
1168 343f8568 Johannes Stezenbach
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
1169 343f8568 Johannes Stezenbach
        goto outc;
1170 343f8568 Johannes Stezenbach
    }
1171 3baf720e Cole Robinson
1172 3baf720e Cole Robinson
    /* Attempt to detect via a CDROM specific ioctl */
1173 3baf720e Cole Robinson
    ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1174 3baf720e Cole Robinson
    if (ret >= 0)
1175 3baf720e Cole Robinson
        prio = 100;
1176 3baf720e Cole Robinson
1177 343f8568 Johannes Stezenbach
outc:
1178 2e1e79da Corey Bryant
    qemu_close(fd);
1179 3baf720e Cole Robinson
out:
1180 3baf720e Cole Robinson
    return prio;
1181 508c7cb3 Christoph Hellwig
}
1182 508c7cb3 Christoph Hellwig
1183 f3a5d3f8 Christoph Hellwig
static int cdrom_is_inserted(BlockDriverState *bs)
1184 f3a5d3f8 Christoph Hellwig
{
1185 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1186 f3a5d3f8 Christoph Hellwig
    int ret;
1187 f3a5d3f8 Christoph Hellwig
1188 f3a5d3f8 Christoph Hellwig
    ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1189 f3a5d3f8 Christoph Hellwig
    if (ret == CDS_DISC_OK)
1190 f3a5d3f8 Christoph Hellwig
        return 1;
1191 f3a5d3f8 Christoph Hellwig
    return 0;
1192 f3a5d3f8 Christoph Hellwig
}
1193 f3a5d3f8 Christoph Hellwig
1194 f36f3949 Luiz Capitulino
static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
1195 f3a5d3f8 Christoph Hellwig
{
1196 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1197 f3a5d3f8 Christoph Hellwig
1198 f3a5d3f8 Christoph Hellwig
    if (eject_flag) {
1199 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1200 f3a5d3f8 Christoph Hellwig
            perror("CDROMEJECT");
1201 f3a5d3f8 Christoph Hellwig
    } else {
1202 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1203 f3a5d3f8 Christoph Hellwig
            perror("CDROMEJECT");
1204 f3a5d3f8 Christoph Hellwig
    }
1205 f3a5d3f8 Christoph Hellwig
}
1206 f3a5d3f8 Christoph Hellwig
1207 025e849a Markus Armbruster
static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
1208 f3a5d3f8 Christoph Hellwig
{
1209 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1210 f3a5d3f8 Christoph Hellwig
1211 f3a5d3f8 Christoph Hellwig
    if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1212 f3a5d3f8 Christoph Hellwig
        /*
1213 f3a5d3f8 Christoph Hellwig
         * Note: an error can happen if the distribution automatically
1214 f3a5d3f8 Christoph Hellwig
         * mounts the CD-ROM
1215 f3a5d3f8 Christoph Hellwig
         */
1216 f3a5d3f8 Christoph Hellwig
        /* perror("CDROM_LOCKDOOR"); */
1217 f3a5d3f8 Christoph Hellwig
    }
1218 f3a5d3f8 Christoph Hellwig
}
1219 f3a5d3f8 Christoph Hellwig
1220 f3a5d3f8 Christoph Hellwig
static BlockDriver bdrv_host_cdrom = {
1221 f3a5d3f8 Christoph Hellwig
    .format_name        = "host_cdrom",
1222 84a12e66 Christoph Hellwig
    .protocol_name      = "host_cdrom",
1223 f3a5d3f8 Christoph Hellwig
    .instance_size      = sizeof(BDRVRawState),
1224 508c7cb3 Christoph Hellwig
    .bdrv_probe_device        = cdrom_probe_device,
1225 66f82cee Kevin Wolf
    .bdrv_file_open     = cdrom_open,
1226 f3a5d3f8 Christoph Hellwig
    .bdrv_close         = raw_close,
1227 f3a5d3f8 Christoph Hellwig
    .bdrv_create        = hdev_create,
1228 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1229 336c1c12 Kevin Wolf
    .bdrv_has_zero_init = hdev_has_zero_init,
1230 f3a5d3f8 Christoph Hellwig
1231 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_readv     = raw_aio_readv,
1232 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_writev    = raw_aio_writev,
1233 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1234 f3a5d3f8 Christoph Hellwig
1235 55b949c8 Christoph Hellwig
    .bdrv_truncate      = raw_truncate,
1236 f3a5d3f8 Christoph Hellwig
    .bdrv_getlength     = raw_getlength,
1237 4a1d5e1f Fam Zheng
    .bdrv_get_allocated_file_size
1238 4a1d5e1f Fam Zheng
                        = raw_get_allocated_file_size,
1239 f3a5d3f8 Christoph Hellwig
1240 f3a5d3f8 Christoph Hellwig
    /* removable device support */
1241 f3a5d3f8 Christoph Hellwig
    .bdrv_is_inserted   = cdrom_is_inserted,
1242 f3a5d3f8 Christoph Hellwig
    .bdrv_eject         = cdrom_eject,
1243 025e849a Markus Armbruster
    .bdrv_lock_medium   = cdrom_lock_medium,
1244 f3a5d3f8 Christoph Hellwig
1245 f3a5d3f8 Christoph Hellwig
    /* generic scsi device */
1246 63ec93db Christoph Hellwig
    .bdrv_ioctl         = hdev_ioctl,
1247 63ec93db Christoph Hellwig
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1248 f3a5d3f8 Christoph Hellwig
};
1249 f3a5d3f8 Christoph Hellwig
#endif /* __linux__ */
1250 f3a5d3f8 Christoph Hellwig
1251 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1252 f3a5d3f8 Christoph Hellwig
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1253 f3a5d3f8 Christoph Hellwig
{
1254 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1255 f3a5d3f8 Christoph Hellwig
    int ret;
1256 f3a5d3f8 Christoph Hellwig
1257 f3a5d3f8 Christoph Hellwig
    s->type = FTYPE_CD;
1258 f3a5d3f8 Christoph Hellwig
1259 19a3da7f Blue Swirl
    ret = raw_open_common(bs, filename, flags, 0);
1260 f3a5d3f8 Christoph Hellwig
    if (ret)
1261 f3a5d3f8 Christoph Hellwig
        return ret;
1262 f3a5d3f8 Christoph Hellwig
1263 9b2260cb Dong Xu Wang
    /* make sure the door isn't locked at this time */
1264 f3a5d3f8 Christoph Hellwig
    ioctl(s->fd, CDIOCALLOW);
1265 f3a5d3f8 Christoph Hellwig
    return 0;
1266 f3a5d3f8 Christoph Hellwig
}
1267 f3a5d3f8 Christoph Hellwig
1268 508c7cb3 Christoph Hellwig
static int cdrom_probe_device(const char *filename)
1269 508c7cb3 Christoph Hellwig
{
1270 508c7cb3 Christoph Hellwig
    if (strstart(filename, "/dev/cd", NULL) ||
1271 508c7cb3 Christoph Hellwig
            strstart(filename, "/dev/acd", NULL))
1272 508c7cb3 Christoph Hellwig
        return 100;
1273 508c7cb3 Christoph Hellwig
    return 0;
1274 508c7cb3 Christoph Hellwig
}
1275 508c7cb3 Christoph Hellwig
1276 f3a5d3f8 Christoph Hellwig
static int cdrom_reopen(BlockDriverState *bs)
1277 f3a5d3f8 Christoph Hellwig
{
1278 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1279 f3a5d3f8 Christoph Hellwig
    int fd;
1280 f3a5d3f8 Christoph Hellwig
1281 f3a5d3f8 Christoph Hellwig
    /*
1282 f3a5d3f8 Christoph Hellwig
     * Force reread of possibly changed/newly loaded disc,
1283 f3a5d3f8 Christoph Hellwig
     * FreeBSD seems to not notice sometimes...
1284 f3a5d3f8 Christoph Hellwig
     */
1285 f3a5d3f8 Christoph Hellwig
    if (s->fd >= 0)
1286 2e1e79da Corey Bryant
        qemu_close(s->fd);
1287 6165f4d8 Corey Bryant
    fd = qemu_open(bs->filename, s->open_flags, 0644);
1288 f3a5d3f8 Christoph Hellwig
    if (fd < 0) {
1289 f3a5d3f8 Christoph Hellwig
        s->fd = -1;
1290 f3a5d3f8 Christoph Hellwig
        return -EIO;
1291 f3a5d3f8 Christoph Hellwig
    }
1292 f3a5d3f8 Christoph Hellwig
    s->fd = fd;
1293 f3a5d3f8 Christoph Hellwig
1294 9b2260cb Dong Xu Wang
    /* make sure the door isn't locked at this time */
1295 f3a5d3f8 Christoph Hellwig
    ioctl(s->fd, CDIOCALLOW);
1296 f3a5d3f8 Christoph Hellwig
    return 0;
1297 f3a5d3f8 Christoph Hellwig
}
1298 f3a5d3f8 Christoph Hellwig
1299 f3a5d3f8 Christoph Hellwig
static int cdrom_is_inserted(BlockDriverState *bs)
1300 f3a5d3f8 Christoph Hellwig
{
1301 f3a5d3f8 Christoph Hellwig
    return raw_getlength(bs) > 0;
1302 f3a5d3f8 Christoph Hellwig
}
1303 f3a5d3f8 Christoph Hellwig
1304 f36f3949 Luiz Capitulino
static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
1305 f3a5d3f8 Christoph Hellwig
{
1306 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1307 f3a5d3f8 Christoph Hellwig
1308 f3a5d3f8 Christoph Hellwig
    if (s->fd < 0)
1309 822e1cd1 Markus Armbruster
        return;
1310 f3a5d3f8 Christoph Hellwig
1311 f3a5d3f8 Christoph Hellwig
    (void) ioctl(s->fd, CDIOCALLOW);
1312 f3a5d3f8 Christoph Hellwig
1313 f3a5d3f8 Christoph Hellwig
    if (eject_flag) {
1314 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDIOCEJECT) < 0)
1315 f3a5d3f8 Christoph Hellwig
            perror("CDIOCEJECT");
1316 f3a5d3f8 Christoph Hellwig
    } else {
1317 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDIOCCLOSE) < 0)
1318 f3a5d3f8 Christoph Hellwig
            perror("CDIOCCLOSE");
1319 f3a5d3f8 Christoph Hellwig
    }
1320 f3a5d3f8 Christoph Hellwig
1321 822e1cd1 Markus Armbruster
    cdrom_reopen(bs);
1322 f3a5d3f8 Christoph Hellwig
}
1323 f3a5d3f8 Christoph Hellwig
1324 025e849a Markus Armbruster
static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
1325 f3a5d3f8 Christoph Hellwig
{
1326 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1327 f3a5d3f8 Christoph Hellwig
1328 f3a5d3f8 Christoph Hellwig
    if (s->fd < 0)
1329 7bf37fed Markus Armbruster
        return;
1330 f3a5d3f8 Christoph Hellwig
    if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1331 f3a5d3f8 Christoph Hellwig
        /*
1332 f3a5d3f8 Christoph Hellwig
         * Note: an error can happen if the distribution automatically
1333 f3a5d3f8 Christoph Hellwig
         * mounts the CD-ROM
1334 f3a5d3f8 Christoph Hellwig
         */
1335 f3a5d3f8 Christoph Hellwig
        /* perror("CDROM_LOCKDOOR"); */
1336 f3a5d3f8 Christoph Hellwig
    }
1337 f3a5d3f8 Christoph Hellwig
}
1338 f3a5d3f8 Christoph Hellwig
1339 f3a5d3f8 Christoph Hellwig
static BlockDriver bdrv_host_cdrom = {
1340 f3a5d3f8 Christoph Hellwig
    .format_name        = "host_cdrom",
1341 84a12e66 Christoph Hellwig
    .protocol_name      = "host_cdrom",
1342 f3a5d3f8 Christoph Hellwig
    .instance_size      = sizeof(BDRVRawState),
1343 508c7cb3 Christoph Hellwig
    .bdrv_probe_device        = cdrom_probe_device,
1344 66f82cee Kevin Wolf
    .bdrv_file_open     = cdrom_open,
1345 f3a5d3f8 Christoph Hellwig
    .bdrv_close         = raw_close,
1346 f3a5d3f8 Christoph Hellwig
    .bdrv_create        = hdev_create,
1347 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1348 336c1c12 Kevin Wolf
    .bdrv_has_zero_init = hdev_has_zero_init,
1349 f3a5d3f8 Christoph Hellwig
1350 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_readv     = raw_aio_readv,
1351 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_writev    = raw_aio_writev,
1352 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1353 f3a5d3f8 Christoph Hellwig
1354 55b949c8 Christoph Hellwig
    .bdrv_truncate      = raw_truncate,
1355 f3a5d3f8 Christoph Hellwig
    .bdrv_getlength     = raw_getlength,
1356 4a1d5e1f Fam Zheng
    .bdrv_get_allocated_file_size
1357 4a1d5e1f Fam Zheng
                        = raw_get_allocated_file_size,
1358 f3a5d3f8 Christoph Hellwig
1359 19cb3738 bellard
    /* removable device support */
1360 f3a5d3f8 Christoph Hellwig
    .bdrv_is_inserted   = cdrom_is_inserted,
1361 f3a5d3f8 Christoph Hellwig
    .bdrv_eject         = cdrom_eject,
1362 025e849a Markus Armbruster
    .bdrv_lock_medium   = cdrom_lock_medium,
1363 19cb3738 bellard
};
1364 f3a5d3f8 Christoph Hellwig
#endif /* __FreeBSD__ */
1365 5efa9d5a Anthony Liguori
1366 84a12e66 Christoph Hellwig
static void bdrv_file_init(void)
1367 5efa9d5a Anthony Liguori
{
1368 508c7cb3 Christoph Hellwig
    /*
1369 508c7cb3 Christoph Hellwig
     * Register all the drivers.  Note that order is important, the driver
1370 508c7cb3 Christoph Hellwig
     * registered last will get probed first.
1371 508c7cb3 Christoph Hellwig
     */
1372 84a12e66 Christoph Hellwig
    bdrv_register(&bdrv_file);
1373 5efa9d5a Anthony Liguori
    bdrv_register(&bdrv_host_device);
1374 f3a5d3f8 Christoph Hellwig
#ifdef __linux__
1375 f3a5d3f8 Christoph Hellwig
    bdrv_register(&bdrv_host_floppy);
1376 f3a5d3f8 Christoph Hellwig
    bdrv_register(&bdrv_host_cdrom);
1377 f3a5d3f8 Christoph Hellwig
#endif
1378 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1379 f3a5d3f8 Christoph Hellwig
    bdrv_register(&bdrv_host_cdrom);
1380 f3a5d3f8 Christoph Hellwig
#endif
1381 5efa9d5a Anthony Liguori
}
1382 5efa9d5a Anthony Liguori
1383 84a12e66 Christoph Hellwig
block_init(bdrv_file_init);