Statistics
| Branch: | Revision:

root / block / raw-posix.c @ fc32a72d

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