#include "qemu-common.h"
#include "qemu-timer.h"
#include "qemu-char.h"
+#include "qemu-log.h"
#include "block_int.h"
#include "module.h"
-#ifdef CONFIG_AIO
-#include "posix-aio-compat.h"
-#endif
+#include "block/raw-posix-aio.h"
#ifdef CONFIG_COCOA
#include <paths.h>
#include <linux/cdrom.h>
#include <linux/fd.h>
#endif
-#ifdef __FreeBSD__
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <signal.h>
#include <sys/disk.h>
#include <sys/cdio.h>
/* OS X does not have O_DSYNC */
#ifndef O_DSYNC
+#ifdef O_SYNC
#define O_DSYNC O_SYNC
+#elif defined(O_FSYNC)
+#define O_DSYNC O_FSYNC
+#endif
#endif
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
int64_t fd_error_time;
int fd_got_error;
int fd_media_changed;
+#endif
+#ifdef CONFIG_LINUX_AIO
+ int use_aio;
+ void *aio_ctx;
#endif
uint8_t* aligned_buf;
} BDRVRawState;
-static int posix_aio_init(void);
-
static int fd_open(BlockDriverState *bs);
+static int64_t raw_getlength(BlockDriverState *bs);
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int cdrom_reopen(BlockDriverState *bs);
#endif
static int raw_open_common(BlockDriverState *bs, const char *filename,
- int flags)
+ int bdrv_flags, int open_flags)
{
BDRVRawState *s = bs->opaque;
int fd, ret;
- posix_aio_init();
-
s->lseek_err_cnt = 0;
- s->open_flags |= O_BINARY;
- if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+ s->open_flags = open_flags | O_BINARY;
+ s->open_flags &= ~O_ACCMODE;
+ if (bdrv_flags & BDRV_O_RDWR) {
s->open_flags |= O_RDWR;
} else {
s->open_flags |= O_RDONLY;
/* Use O_DSYNC for write-through caching, no flags for write-back caching,
* and O_DIRECT for no caching. */
- if ((flags & BDRV_O_NOCACHE))
+ if ((bdrv_flags & BDRV_O_NOCACHE))
s->open_flags |= O_DIRECT;
- else if (!(flags & BDRV_O_CACHE_WB))
+ else if (!(bdrv_flags & BDRV_O_CACHE_WB))
s->open_flags |= O_DSYNC;
s->fd = -1;
- fd = open(filename, s->open_flags, 0644);
+ fd = qemu_open(filename, s->open_flags, 0644);
if (fd < 0) {
ret = -errno;
if (ret == -EROFS)
}
s->fd = fd;
s->aligned_buf = NULL;
- if ((flags & BDRV_O_NOCACHE)) {
+
+ if ((bdrv_flags & BDRV_O_NOCACHE)) {
s->aligned_buf = qemu_blockalign(bs, ALIGNED_BUFFER_SIZE);
if (s->aligned_buf == NULL) {
- ret = -errno;
- close(fd);
- return ret;
+ goto out_close;
+ }
+ }
+
+#ifdef CONFIG_LINUX_AIO
+ if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
+ (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
+
+ /* We're falling back to POSIX AIO in some cases */
+ paio_init();
+
+ s->aio_ctx = laio_init();
+ if (!s->aio_ctx) {
+ goto out_free_buf;
+ }
+ s->use_aio = 1;
+ } else
+#endif
+ {
+ if (paio_init() < 0) {
+ goto out_free_buf;
}
+#ifdef CONFIG_LINUX_AIO
+ s->use_aio = 0;
+#endif
}
+
return 0;
+
+out_free_buf:
+ qemu_vfree(s->aligned_buf);
+out_close:
+ close(fd);
+ return -errno;
}
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
+ int open_flags = 0;
s->type = FTYPE_FILE;
if (flags & BDRV_O_CREAT)
- s->open_flags |= O_CREAT | O_TRUNC;
+ open_flags = O_CREAT | O_TRUNC;
- return raw_open_common(bs, filename, flags);
+ return raw_open_common(bs, filename, flags, open_flags);
}
/* XXX: use host sector size if necessary with:
if (ret == count)
goto label__raw_read__success;
+ /* Allow reads beyond the end (needed for pwrite) */
+ if ((ret == 0) && bs->growable) {
+ int64_t size = raw_getlength(bs);
+ if (offset >= size) {
+ memset(buf, 0, count);
+ ret = count;
+ goto label__raw_read__success;
+ }
+ }
+
DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] read failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
return ret;
}
-#ifdef CONFIG_AIO
-/***********************************************************/
-/* Unix AIO using POSIX AIO */
-
-typedef struct RawAIOCB {
- BlockDriverAIOCB common;
- struct qemu_paiocb aiocb;
- struct RawAIOCB *next;
- int ret;
-} RawAIOCB;
-
-typedef struct PosixAioState
-{
- int rfd, wfd;
- RawAIOCB *first_aio;
-} PosixAioState;
-
-static void posix_aio_read(void *opaque)
-{
- PosixAioState *s = opaque;
- RawAIOCB *acb, **pacb;
- int ret;
- ssize_t len;
-
- /* read all bytes from signal pipe */
- for (;;) {
- char bytes[16];
-
- len = read(s->rfd, bytes, sizeof(bytes));
- if (len == -1 && errno == EINTR)
- continue; /* try again */
- if (len == sizeof(bytes))
- continue; /* more to read */
- break;
- }
-
- for(;;) {
- pacb = &s->first_aio;
- for(;;) {
- acb = *pacb;
- if (!acb)
- goto the_end;
- ret = qemu_paio_error(&acb->aiocb);
- if (ret == ECANCELED) {
- /* remove the request */
- *pacb = acb->next;
- qemu_aio_release(acb);
- } else if (ret != EINPROGRESS) {
- /* end of aio */
- if (ret == 0) {
- ret = qemu_paio_return(&acb->aiocb);
- if (ret == acb->aiocb.aio_nbytes)
- ret = 0;
- else
- ret = -EINVAL;
- } else {
- ret = -ret;
- }
- /* remove the request */
- *pacb = acb->next;
- /* call the callback */
- acb->common.cb(acb->common.opaque, ret);
- qemu_aio_release(acb);
- break;
- } else {
- pacb = &acb->next;
- }
- }
- }
- the_end: ;
-}
-
-static int posix_aio_flush(void *opaque)
-{
- PosixAioState *s = opaque;
- return !!s->first_aio;
-}
-
-static PosixAioState *posix_aio_state;
-
-static void aio_signal_handler(int signum)
-{
- if (posix_aio_state) {
- char byte = 0;
-
- write(posix_aio_state->wfd, &byte, sizeof(byte));
- }
-
- qemu_service_io();
-}
-
-static int posix_aio_init(void)
+/*
+ * Check if all memory in this vector is sector aligned.
+ */
+static int qiov_is_aligned(QEMUIOVector *qiov)
{
- struct sigaction act;
- PosixAioState *s;
- int fds[2];
- struct qemu_paioinit ai;
-
- if (posix_aio_state)
- return 0;
-
- s = qemu_malloc(sizeof(PosixAioState));
-
- sigfillset(&act.sa_mask);
- act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
- act.sa_handler = aio_signal_handler;
- sigaction(SIGUSR2, &act, NULL);
-
- s->first_aio = NULL;
- if (pipe(fds) == -1) {
- fprintf(stderr, "failed to create pipe\n");
- return -errno;
- }
-
- s->rfd = fds[0];
- s->wfd = fds[1];
-
- fcntl(s->rfd, F_SETFL, O_NONBLOCK);
- fcntl(s->wfd, F_SETFL, O_NONBLOCK);
-
- qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
-
- memset(&ai, 0, sizeof(ai));
- ai.aio_threads = 64;
- ai.aio_num = 64;
- qemu_paio_init(&ai);
+ int i;
- posix_aio_state = s;
-
- return 0;
-}
-
-static void raw_aio_remove(RawAIOCB *acb)
-{
- RawAIOCB **pacb;
-
- /* remove the callback from the queue */
- pacb = &posix_aio_state->first_aio;
- for(;;) {
- if (*pacb == NULL) {
- fprintf(stderr, "raw_aio_remove: aio request not found!\n");
- break;
- } else if (*pacb == acb) {
- *pacb = acb->next;
- qemu_aio_release(acb);
- break;
+ for (i = 0; i < qiov->niov; i++) {
+ if ((uintptr_t) qiov->iov[i].iov_base % 512) {
+ return 0;
}
- pacb = &(*pacb)->next;
- }
-}
-
-static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
-{
- int ret;
- RawAIOCB *acb = (RawAIOCB *)blockacb;
-
- ret = qemu_paio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
- if (ret == QEMU_PAIO_NOTCANCELED) {
- /* fail safe: if the aio could not be canceled, we wait for
- it */
- while (qemu_paio_error(&acb->aiocb) == EINPROGRESS);
}
- raw_aio_remove(acb);
+ return 1;
}
-static AIOPool raw_aio_pool = {
- .aiocb_size = sizeof(RawAIOCB),
- .cancel = raw_aio_cancel,
-};
-
-static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int64_t sector_num,
- QEMUIOVector *qiov, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
+static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque, int type)
{
BDRVRawState *s = bs->opaque;
- RawAIOCB *acb;
if (fd_open(bs) < 0)
return NULL;
- acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
- if (!acb)
- return NULL;
- acb->aiocb.aio_fildes = s->fd;
- acb->aiocb.ev_signo = SIGUSR2;
- acb->aiocb.aio_iov = qiov->iov;
- acb->aiocb.aio_niov = qiov->niov;
- acb->aiocb.aio_nbytes = nb_sectors * 512;
- acb->aiocb.aio_offset = sector_num * 512;
- acb->aiocb.aio_flags = 0;
-
/*
* If O_DIRECT is used the buffer needs to be aligned on a sector
- * boundary. Tell the low level code to ensure that in case it's
- * not done yet.
+ * boundary. Check if this is the case or telll the low-level
+ * driver that it needs to copy the buffer.
*/
- if (s->aligned_buf)
- acb->aiocb.aio_flags |= QEMU_AIO_SECTOR_ALIGNED;
+ if (s->aligned_buf) {
+ if (!qiov_is_aligned(qiov)) {
+ type |= QEMU_AIO_MISALIGNED;
+#ifdef CONFIG_LINUX_AIO
+ } else if (s->use_aio) {
+ return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
+ nb_sectors, cb, opaque, type);
+#endif
+ }
+ }
- acb->next = posix_aio_state->first_aio;
- posix_aio_state->first_aio = acb;
- return acb;
+ return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
+ cb, opaque, type);
}
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
- RawAIOCB *acb;
-
- acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque);
- if (!acb)
- return NULL;
- if (qemu_paio_read(&acb->aiocb) < 0) {
- raw_aio_remove(acb);
- return NULL;
- }
- return &acb->common;
+ return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
+ cb, opaque, QEMU_AIO_READ);
}
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
- RawAIOCB *acb;
-
- acb = raw_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque);
- if (!acb)
- return NULL;
- if (qemu_paio_write(&acb->aiocb) < 0) {
- raw_aio_remove(acb);
- return NULL;
- }
- return &acb->common;
+ return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
+ cb, opaque, QEMU_AIO_WRITE);
}
-#else /* CONFIG_AIO */
-static int posix_aio_init(void)
+
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque)
{
- return 0;
-}
-#endif /* CONFIG_AIO */
+ BDRVRawState *s = bs->opaque;
+
+ if (fd_open(bs) < 0)
+ return NULL;
+ return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
+}
static void raw_close(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int fd = s->fd;
int64_t size;
-#ifdef HOST_BSD
+#ifdef CONFIG_BSD
struct stat sb;
-#ifdef __FreeBSD__
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
int reopened = 0;
#endif
#endif
if (ret < 0)
return ret;
-#ifdef HOST_BSD
-#ifdef __FreeBSD__
+#ifdef CONFIG_BSD
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
again:
#endif
if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
#else
size = lseek(fd, 0LL, SEEK_END);
#endif
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
switch(s->type) {
case FTYPE_CD:
/* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
+ int result = 0;
int64_t total_size = 0;
/* Read out options */
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
- if (fd < 0)
- return -EIO;
- ftruncate(fd, total_size * 512);
- close(fd);
- return 0;
+ if (fd < 0) {
+ result = -errno;
+ } else {
+ if (ftruncate(fd, total_size * 512) != 0) {
+ result = -errno;
+ }
+ if (close(fd) != 0) {
+ result = -errno;
+ }
+ }
+ return result;
}
static void raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
- fsync(s->fd);
+ qemu_fdatasync(s->fd);
}
.bdrv_create = raw_create,
.bdrv_flush = raw_flush,
-#ifdef CONFIG_AIO
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
-#endif
+ .bdrv_aio_flush = raw_aio_flush,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
#endif
s->type = FTYPE_FILE;
-#if defined(__linux__) && defined(CONFIG_AIO)
+#if defined(__linux__)
if (strstart(filename, "/dev/sg", NULL)) {
bs->sg = 1;
}
#endif
- return raw_open_common(bs, filename, flags);
+ return raw_open_common(bs, filename, flags, 0);
}
#if defined(__linux__)
return 0;
}
-static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
BDRVRawState *s = bs->opaque;
return ioctl(s->fd, req, buf);
}
-#ifdef CONFIG_AIO
-static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
+static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
- RawAIOCB *acb;
if (fd_open(bs) < 0)
return NULL;
-
- acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
- if (!acb)
- return NULL;
- acb->aiocb.aio_fildes = s->fd;
- acb->aiocb.ev_signo = SIGUSR2;
- acb->aiocb.aio_offset = 0;
- acb->aiocb.aio_flags = 0;
-
- acb->next = posix_aio_state->first_aio;
- posix_aio_state->first_aio = acb;
-
- acb->aiocb.aio_ioctl_buf = buf;
- acb->aiocb.aio_ioctl_cmd = req;
- if (qemu_paio_ioctl(&acb->aiocb) < 0) {
- raw_aio_remove(acb);
- return NULL;
- }
-
- return &acb->common;
+ return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
}
-#endif
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int fd_open(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
return 0;
return -EIO;
}
-
-static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
-{
- return -ENOTSUP;
-}
#else /* !linux && !FreeBSD */
static int fd_open(BlockDriverState *bs)
return 0;
}
-static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
-{
- return -ENOTSUP;
-}
-
-static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
- unsigned long int req, void *buf,
- BlockDriverCompletionFunc *cb, void *opaque)
-{
- return NULL;
-}
#endif /* !linux && !FreeBSD */
static int hdev_create(const char *filename, QEMUOptionParameter *options)
}
static BlockDriver bdrv_host_device = {
- .format_name = "host_device",
- .instance_size = sizeof(BDRVRawState),
- .bdrv_probe_device = hdev_probe_device,
- .bdrv_open = hdev_open,
- .bdrv_close = raw_close,
+ .format_name = "host_device",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_probe_device = hdev_probe_device,
+ .bdrv_open = hdev_open,
+ .bdrv_close = raw_close,
.bdrv_create = hdev_create,
- .bdrv_flush = raw_flush,
+ .create_options = raw_create_options,
+ .no_zero_init = 1,
+ .bdrv_flush = raw_flush,
-#ifdef CONFIG_AIO
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
-#endif
+ .bdrv_aio_flush = raw_aio_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
/* generic scsi device */
- .bdrv_ioctl = raw_ioctl,
-#ifdef CONFIG_AIO
- .bdrv_aio_ioctl = raw_aio_ioctl,
+#ifdef __linux__
+ .bdrv_ioctl = hdev_ioctl,
+ .bdrv_aio_ioctl = hdev_aio_ioctl,
#endif
};
BDRVRawState *s = bs->opaque;
int ret;
- posix_aio_init();
-
s->type = FTYPE_FD;
- /* open will not fail even if no floppy is inserted */
- s->open_flags |= O_NONBLOCK;
- ret = raw_open_common(bs, filename, flags);
+ /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
+ ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
if (ret)
return ret;
static int floppy_probe_device(const char *filename)
{
+ int fd, ret;
+ int prio = 0;
+ struct floppy_struct fdparam;
+
if (strstart(filename, "/dev/fd", NULL))
- return 100;
- return 0;
+ prio = 50;
+
+ fd = open(filename, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ goto out;
+ }
+
+ /* Attempt to detect via a floppy specific ioctl */
+ ret = ioctl(fd, FDGETPRM, &fdparam);
+ if (ret >= 0)
+ prio = 100;
+
+ close(fd);
+out:
+ return prio;
}
.bdrv_open = floppy_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
+ .create_options = raw_create_options,
+ .no_zero_init = 1,
.bdrv_flush = raw_flush,
-#ifdef CONFIG_AIO
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
-#endif
+ .bdrv_aio_flush = raw_aio_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_is_inserted = floppy_is_inserted,
.bdrv_media_changed = floppy_media_changed,
.bdrv_eject = floppy_eject,
-
- /* generic scsi device */
- .bdrv_ioctl = raw_ioctl,
-#ifdef CONFIG_AIO
- .bdrv_aio_ioctl = raw_aio_ioctl,
-#endif
};
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
- /* open will not fail even if no CD is inserted */
- s->open_flags |= O_NONBLOCK;
s->type = FTYPE_CD;
- return raw_open_common(bs, filename, flags);
+ /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
+ return raw_open_common(bs, filename, flags, O_NONBLOCK);
}
static int cdrom_probe_device(const char *filename)
{
+ int fd, ret;
+ int prio = 0;
+
if (strstart(filename, "/dev/cd", NULL))
- return 100;
- return 0;
+ prio = 50;
+
+ fd = open(filename, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ goto out;
+ }
+
+ /* Attempt to detect via a CDROM specific ioctl */
+ ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+ if (ret >= 0)
+ prio = 100;
+
+ close(fd);
+out:
+ return prio;
}
static int cdrom_is_inserted(BlockDriverState *bs)
.bdrv_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
+ .create_options = raw_create_options,
+ .no_zero_init = 1,
.bdrv_flush = raw_flush,
-#ifdef CONFIG_AIO
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
-#endif
+ .bdrv_aio_flush = raw_aio_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_set_locked = cdrom_set_locked,
/* generic scsi device */
- .bdrv_ioctl = raw_ioctl,
-#ifdef CONFIG_AIO
- .bdrv_aio_ioctl = raw_aio_ioctl,
-#endif
+ .bdrv_ioctl = hdev_ioctl,
+ .bdrv_aio_ioctl = hdev_aio_ioctl,
};
#endif /* __linux__ */
-#ifdef __FreeBSD__
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
s->type = FTYPE_CD;
- ret = raw_open_common(bs, filename, flags);
+ ret = raw_open_common(bs, filename, flags, 0);
if (ret)
return ret;
.bdrv_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
+ .create_options = raw_create_options,
+ .no_zero_init = 1,
.bdrv_flush = raw_flush,
-#ifdef CONFIG_AIO
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
-#endif
+ .bdrv_aio_flush = raw_aio_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_is_inserted = cdrom_is_inserted,
.bdrv_eject = cdrom_eject,
.bdrv_set_locked = cdrom_set_locked,
-
- /* generic scsi device */
- .bdrv_ioctl = raw_ioctl,
-#ifdef CONFIG_AIO
- .bdrv_aio_ioctl = raw_aio_ioctl,
-#endif
};
#endif /* __FreeBSD__ */
bdrv_register(&bdrv_host_floppy);
bdrv_register(&bdrv_host_cdrom);
#endif
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
bdrv_register(&bdrv_host_cdrom);
#endif
}