aboutsummaryrefslogtreecommitdiffstats
path: root/block/raw-posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/raw-posix.c')
-rw-r--r--block/raw-posix.c646
1 files changed, 262 insertions, 384 deletions
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 0e9e343..72fb8ce 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -24,11 +24,10 @@
#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>
@@ -52,7 +51,7 @@
#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>
@@ -81,7 +80,11 @@
/* 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 */
@@ -102,7 +105,6 @@
typedef struct BDRVRawState {
int fd;
int type;
- unsigned int lseek_err_cnt;
int open_flags;
#if defined(__linux__)
/* linux floppy specific */
@@ -111,14 +113,17 @@ typedef struct BDRVRawState {
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
@@ -128,17 +133,12 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
BDRVRawState *s = bs->opaque;
int fd, ret;
- posix_aio_init();
-
- s->lseek_err_cnt = 0;
-
s->open_flags = open_flags | O_BINARY;
s->open_flags &= ~O_ACCMODE;
- if ((bdrv_flags & BDRV_O_ACCESS) == BDRV_O_RDWR) {
+ if (bdrv_flags & BDRV_O_RDWR) {
s->open_flags |= O_RDWR;
} else {
s->open_flags |= O_RDONLY;
- bs->read_only = 1;
}
/* Use O_DSYNC for write-through caching, no flags for write-back caching,
@@ -149,7 +149,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
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)
@@ -158,27 +158,52 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
}
s->fd = fd;
s->aligned_buf = NULL;
+
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)
- open_flags = O_CREAT | O_TRUNC;
-
- return raw_open_common(bs, filename, flags, open_flags);
+ return raw_open_common(bs, filename, flags, 0);
}
/* XXX: use host sector size if necessary with:
@@ -191,7 +216,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
}
#endif
#ifdef CONFIG_COCOA
- u_int32_t blockSize = 512;
+ uint32_t blockSize = 512;
if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
bufsize = blockSize;
}
@@ -215,21 +240,18 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
if (ret < 0)
return ret;
- if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
- ++(s->lseek_err_cnt);
- if(s->lseek_err_cnt <= 10) {
- DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
- "] lseek failed : %d = %s\n",
- s->fd, bs->filename, offset, buf, count,
- bs->total_sectors, errno, strerror(errno));
+ ret = pread(s->fd, buf, count, offset);
+ if (ret == count)
+ return ret;
+
+ /* 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);
+ return count;
}
- return -1;
}
- s->lseek_err_cnt=0;
-
- ret = read(s->fd, buf, count);
- if (ret == count)
- goto label__raw_read__success;
DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] read failed %d : %d = %s\n",
@@ -237,15 +259,13 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
bs->total_sectors, ret, errno, strerror(errno));
/* Try harder for CDrom. */
- if (bs->type == BDRV_TYPE_CDROM) {
- lseek(s->fd, offset, SEEK_SET);
- ret = read(s->fd, buf, count);
+ if (s->type != FTYPE_FILE) {
+ ret = pread(s->fd, buf, count, offset);
if (ret == count)
- goto label__raw_read__success;
- lseek(s->fd, offset, SEEK_SET);
- ret = read(s->fd, buf, count);
+ return ret;
+ ret = pread(s->fd, buf, count, offset);
if (ret == count)
- goto label__raw_read__success;
+ return ret;
DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] retry read failed %d : %d = %s\n",
@@ -253,8 +273,6 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
bs->total_sectors, ret, errno, strerror(errno));
}
-label__raw_read__success:
-
return (ret < 0) ? -errno : ret;
}
@@ -275,29 +293,15 @@ static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
if (ret < 0)
return -errno;
- if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
- ++(s->lseek_err_cnt);
- if(s->lseek_err_cnt) {
- DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
- PRId64 "] lseek failed : %d = %s\n",
- s->fd, bs->filename, offset, buf, count,
- bs->total_sectors, errno, strerror(errno));
- }
- return -EIO;
- }
- s->lseek_err_cnt = 0;
-
- ret = write(s->fd, buf, count);
+ ret = pwrite(s->fd, buf, count, offset);
if (ret == count)
- goto label__raw_write__success;
+ return ret;
DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
"] write failed %d : %d = %s\n",
s->fd, bs->filename, offset, buf, count,
bs->total_sectors, ret, errno, strerror(errno));
-label__raw_write__success:
-
return (ret < 0) ? -errno : ret;
}
@@ -352,8 +356,12 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
size = ALIGNED_BUFFER_SIZE;
ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ } else if (ret == 0) {
+ fprintf(stderr, "raw_pread: read beyond end of file\n");
+ abort();
+ }
size = ret;
if (size > count)
@@ -379,8 +387,9 @@ static int raw_read(BlockDriverState *bs, int64_t sector_num,
{
int ret;
- ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
- if (ret == (nb_sectors * 512))
+ ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
ret = 0;
return ret;
}
@@ -467,255 +476,84 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
int ret;
- ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
- if (ret == (nb_sectors * 512))
+ ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
ret = 0;
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;
+ int i;
- 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);
-
- 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 % BDRV_SECTOR_SIZE) {
+ 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)
{
@@ -724,7 +562,7 @@ static void raw_close(BlockDriverState *bs)
close(s->fd);
s->fd = -1;
if (s->aligned_buf != NULL)
- qemu_free(s->aligned_buf);
+ qemu_vfree(s->aligned_buf);
}
}
@@ -757,30 +595,49 @@ static int64_t raw_getlength(BlockDriverState *bs)
} else
return st.st_size;
}
-#else /* !__OpenBSD__ */
-static int64_t raw_getlength(BlockDriverState *bs)
+#elif defined(__sun__)
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ struct dk_minfo minfo;
+ int ret;
+
+ ret = fd_open(bs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /*
+ * Use the DKIOCGMEDIAINFO ioctl to read the size.
+ */
+ ret = ioctl(s->fd, DKIOCGMEDIAINFO, &minfo);
+ if (ret != -1) {
+ return minfo.dki_lbsize * minfo.dki_capacity;
+ }
+
+ /*
+ * There are reports that lseek on some devices fails, but
+ * irc discussion said that contingency on contingency was overkill.
+ */
+ return lseek(s->fd, 0, SEEK_END);
+}
+#elif defined(CONFIG_BSD)
+static int64_t raw_getlength(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int fd = s->fd;
int64_t size;
-#ifdef CONFIG_BSD
struct stat sb;
-#ifdef __FreeBSD__
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
int reopened = 0;
#endif
-#endif
-#ifdef __sun__
- struct dk_minfo minfo;
- int rv;
-#endif
int ret;
ret = fd_open(bs);
if (ret < 0)
return ret;
-#ifdef CONFIG_BSD
-#ifdef __FreeBSD__
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
again:
#endif
if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
@@ -801,7 +658,7 @@ again:
#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 */
@@ -814,56 +671,59 @@ again:
}
}
#endif
- } else
-#endif
-#ifdef __sun__
- /*
- * use the DKIOCGMEDIAINFO ioctl to read the size.
- */
- rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
- if ( rv != -1 ) {
- size = minfo.dki_lbsize * minfo.dki_capacity;
- } else /* there are reports that lseek on some devices
- fails, but irc discussion said that contingency
- on contingency was overkill */
-#endif
- {
+ } else {
size = lseek(fd, 0, SEEK_END);
}
return size;
}
+#else
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ ret = fd_open(bs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return lseek(s->fd, 0, SEEK_END);
+}
#endif
static int raw_create(const char *filename, QEMUOptionParameter *options)
{
- int fd, ret;
+ int fd;
+ int result = 0;
int64_t total_size = 0;
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
- total_size = options->value.n / 512;
+ total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
- if (fd < 0)
- return -EIO;
- do {
- ret = ftruncate(fd, total_size * 512);
- } while (ret < 0 && errno == EINTR);
- close(fd);
- if (ret != 0)
- return -errno;
- return 0;
+ if (fd < 0) {
+ result = -errno;
+ } else {
+ if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 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);
}
@@ -876,21 +736,21 @@ static QEMUOptionParameter raw_create_options[] = {
{ NULL }
};
-static BlockDriver bdrv_raw = {
- .format_name = "raw",
+static BlockDriver bdrv_file = {
+ .format_name = "file",
+ .protocol_name = "file",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe = NULL, /* no probe for protocols */
- .bdrv_open = raw_open,
+ .bdrv_file_open = raw_open,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_close = raw_close,
.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,
@@ -1007,7 +867,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
#endif
s->type = FTYPE_FILE;
-#if defined(__linux__) && defined(CONFIG_AIO)
+#if defined(__linux__)
if (strstart(filename, "/dev/sg", NULL)) {
bs->sg = 1;
}
@@ -1073,40 +933,18 @@ static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
return ioctl(s->fd, req, buf);
}
-#ifdef CONFIG_AIO
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;
@@ -1135,39 +973,46 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, "size")) {
- total_size = options->value.n / 512;
+ total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
fd = open(filename, O_WRONLY | O_BINARY);
if (fd < 0)
- return -EIO;
+ return -errno;
if (fstat(fd, &stat_buf) < 0)
- ret = -EIO;
+ ret = -errno;
else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
- ret = -EIO;
- else if (lseek(fd, 0, SEEK_END) < total_size * 512)
+ ret = -ENODEV;
+ else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
ret = -ENOSPC;
close(fd);
return ret;
}
+static int hdev_has_zero_init(BlockDriverState *bs)
+{
+ return 0;
+}
+
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",
+ .protocol_name = "host_device",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_probe_device = hdev_probe_device,
+ .bdrv_file_open = hdev_open,
+ .bdrv_close = raw_close,
.bdrv_create = hdev_create,
- .bdrv_flush = raw_flush,
+ .create_options = raw_create_options,
+ .bdrv_has_zero_init = hdev_has_zero_init,
+ .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,
@@ -1176,10 +1021,8 @@ static BlockDriver bdrv_host_device = {
/* generic scsi device */
#ifdef __linux__
.bdrv_ioctl = hdev_ioctl,
-#ifdef CONFIG_AIO
.bdrv_aio_ioctl = hdev_aio_ioctl,
#endif
-#endif
};
#ifdef __linux__
@@ -1188,8 +1031,6 @@ static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
BDRVRawState *s = bs->opaque;
int ret;
- posix_aio_init();
-
s->type = FTYPE_FD;
/* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
@@ -1207,9 +1048,26 @@ static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
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;
}
@@ -1257,17 +1115,19 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag)
static BlockDriver bdrv_host_floppy = {
.format_name = "host_floppy",
+ .protocol_name = "host_floppy",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = floppy_probe_device,
- .bdrv_open = floppy_open,
+ .bdrv_file_open = floppy_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
+ .create_options = raw_create_options,
+ .bdrv_has_zero_init = hdev_has_zero_init,
.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,
@@ -1291,9 +1151,25 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
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)
@@ -1339,17 +1215,19 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
static BlockDriver bdrv_host_cdrom = {
.format_name = "host_cdrom",
+ .protocol_name = "host_cdrom",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = cdrom_probe_device,
- .bdrv_open = cdrom_open,
+ .bdrv_file_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
+ .create_options = raw_create_options,
+ .bdrv_has_zero_init = hdev_has_zero_init,
.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,
@@ -1362,13 +1240,11 @@ static BlockDriver bdrv_host_cdrom = {
/* generic scsi device */
.bdrv_ioctl = hdev_ioctl,
-#ifdef CONFIG_AIO
.bdrv_aio_ioctl = hdev_aio_ioctl,
-#endif
};
#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;
@@ -1462,17 +1338,19 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
static BlockDriver bdrv_host_cdrom = {
.format_name = "host_cdrom",
+ .protocol_name = "host_cdrom",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = cdrom_probe_device,
- .bdrv_open = cdrom_open,
+ .bdrv_file_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
+ .create_options = raw_create_options,
+ .bdrv_has_zero_init = hdev_has_zero_init,
.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,
@@ -1485,21 +1363,21 @@ static BlockDriver bdrv_host_cdrom = {
};
#endif /* __FreeBSD__ */
-static void bdrv_raw_init(void)
+static void bdrv_file_init(void)
{
/*
* Register all the drivers. Note that order is important, the driver
* registered last will get probed first.
*/
- bdrv_register(&bdrv_raw);
+ bdrv_register(&bdrv_file);
bdrv_register(&bdrv_host_device);
#ifdef __linux__
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
}
-block_init(bdrv_raw_init);
+block_init(bdrv_file_init);