bool has_discard:1;
bool has_write_zeroes:1;
bool discard_zeroes:1;
+ bool use_linux_aio:1;
bool has_fallocate;
bool needs_alignment;
} BDRVRawState;
}
}
-#ifdef CONFIG_LINUX_AIO
-static bool raw_use_aio(int bdrv_flags)
-{
- /*
- * Currently Linux do AIO only for files opened with O_DIRECT
- * specified so check NOCACHE flag too
- */
- return (bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
- (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO);
-}
-#endif
-
static void raw_parse_filename(const char *filename, QDict *options,
Error **errp)
{
.type = QEMU_OPT_STRING,
.help = "File name of the image",
},
+ {
+ .name = "aio",
+ .type = QEMU_OPT_STRING,
+ .help = "host AIO implementation (threads, native)",
+ },
{ /* end of list */ }
},
};
QemuOpts *opts;
Error *local_err = NULL;
const char *filename = NULL;
+ BlockdevAioOptions aio, aio_default;
int fd, ret;
struct stat st;
goto fail;
}
+ aio_default = (bdrv_flags & BDRV_O_NATIVE_AIO)
+ ? BLOCKDEV_AIO_OPTIONS_NATIVE
+ : BLOCKDEV_AIO_OPTIONS_THREADS;
+ aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
+ BLOCKDEV_AIO_OPTIONS__MAX, aio_default, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+ s->use_linux_aio = (aio == BLOCKDEV_AIO_OPTIONS_NATIVE);
+
s->open_flags = open_flags;
raw_parse_flags(bdrv_flags, &s->open_flags);
fd = qemu_open(filename, s->open_flags, 0644);
if (fd < 0) {
ret = -errno;
+ error_setg_errno(errp, errno, "Could not open '%s'", filename);
if (ret == -EROFS) {
ret = -EACCES;
}
s->fd = fd;
#ifdef CONFIG_LINUX_AIO
- if (!raw_use_aio(bdrv_flags) && (bdrv_flags & BDRV_O_NATIVE_AIO)) {
+ /* Currently Linux does AIO only for files opened with O_DIRECT */
+ if (s->use_linux_aio && !(s->open_flags & O_DIRECT)) {
error_setg(errp, "aio=native was specified, but it requires "
"cache.direct=on, which was not specified.");
ret = -EINVAL;
goto fail;
}
#else
- if (bdrv_flags & BDRV_O_NATIVE_AIO) {
+ if (s->use_linux_aio) {
error_setg(errp, "aio=native was specified, but is not supported "
"in this build.");
ret = -EINVAL;
BlockReopenQueue *queue, Error **errp)
{
BDRVRawState *s;
- BDRVRawReopenState *raw_s;
+ BDRVRawReopenState *rs;
int ret = 0;
Error *local_err = NULL;
s = state->bs->opaque;
state->opaque = g_new0(BDRVRawReopenState, 1);
- raw_s = state->opaque;
+ rs = state->opaque;
if (s->type == FTYPE_CD) {
- raw_s->open_flags |= O_NONBLOCK;
+ rs->open_flags |= O_NONBLOCK;
}
- raw_parse_flags(state->flags, &raw_s->open_flags);
+ raw_parse_flags(state->flags, &rs->open_flags);
- raw_s->fd = -1;
+ rs->fd = -1;
int fcntl_flags = O_APPEND | O_NONBLOCK;
#ifdef O_NOATIME
#ifdef O_ASYNC
/* Not all operating systems have O_ASYNC, and those that don't
- * will not let us track the state into raw_s->open_flags (typically
+ * will not let us track the state into rs->open_flags (typically
* you achieve the same effect with an ioctl, for example I_SETSIG
* on Solaris). But we do not use O_ASYNC, so that's fine.
*/
assert((s->open_flags & O_ASYNC) == 0);
#endif
- if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
+ if ((rs->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
/* dup the original fd */
- raw_s->fd = qemu_dup(s->fd);
- if (raw_s->fd >= 0) {
- ret = fcntl_setfl(raw_s->fd, raw_s->open_flags);
+ rs->fd = qemu_dup(s->fd);
+ if (rs->fd >= 0) {
+ ret = fcntl_setfl(rs->fd, rs->open_flags);
if (ret) {
- qemu_close(raw_s->fd);
- raw_s->fd = -1;
+ qemu_close(rs->fd);
+ rs->fd = -1;
}
}
}
/* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */
- if (raw_s->fd == -1) {
+ if (rs->fd == -1) {
const char *normalized_filename = state->bs->filename;
ret = raw_normalize_devicepath(&normalized_filename);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not normalize device path");
} else {
- assert(!(raw_s->open_flags & O_CREAT));
- raw_s->fd = qemu_open(normalized_filename, raw_s->open_flags);
- if (raw_s->fd == -1) {
+ assert(!(rs->open_flags & O_CREAT));
+ rs->fd = qemu_open(normalized_filename, rs->open_flags);
+ if (rs->fd == -1) {
error_setg_errno(errp, errno, "Could not reopen file");
ret = -1;
}
/* Fail already reopen_prepare() if we can't get a working O_DIRECT
* alignment with the new fd. */
- if (raw_s->fd != -1) {
- raw_probe_alignment(state->bs, raw_s->fd, &local_err);
+ if (rs->fd != -1) {
+ raw_probe_alignment(state->bs, rs->fd, &local_err);
if (local_err) {
- qemu_close(raw_s->fd);
- raw_s->fd = -1;
+ qemu_close(rs->fd);
+ rs->fd = -1;
error_propagate(errp, local_err);
ret = -EINVAL;
}
static void raw_reopen_commit(BDRVReopenState *state)
{
- BDRVRawReopenState *raw_s = state->opaque;
+ BDRVRawReopenState *rs = state->opaque;
BDRVRawState *s = state->bs->opaque;
- s->open_flags = raw_s->open_flags;
+ s->open_flags = rs->open_flags;
qemu_close(s->fd);
- s->fd = raw_s->fd;
+ s->fd = rs->fd;
g_free(state->opaque);
state->opaque = NULL;
static void raw_reopen_abort(BDRVReopenState *state)
{
- BDRVRawReopenState *raw_s = state->opaque;
+ BDRVRawReopenState *rs = state->opaque;
/* nothing to do if NULL, we didn't get far enough */
- if (raw_s == NULL) {
+ if (rs == NULL) {
return;
}
- if (raw_s->fd >= 0) {
- qemu_close(raw_s->fd);
- raw_s->fd = -1;
+ if (rs->fd >= 0) {
+ qemu_close(rs->fd);
+ rs->fd = -1;
}
g_free(state->opaque);
state->opaque = NULL;
if (!bdrv_qiov_is_aligned(bs, qiov)) {
type |= QEMU_AIO_MISALIGNED;
#ifdef CONFIG_LINUX_AIO
- } else if (bs->open_flags & BDRV_O_NATIVE_AIO) {
+ } else if (s->use_linux_aio) {
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
assert(qiov->size == bytes);
return laio_co_submit(bs, aio, s->fd, offset, qiov, type);
static void raw_aio_plug(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
- if (bs->open_flags & BDRV_O_NATIVE_AIO) {
+ BDRVRawState *s = bs->opaque;
+ if (s->use_linux_aio) {
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
laio_io_plug(bs, aio);
}
static void raw_aio_unplug(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
- if (bs->open_flags & BDRV_O_NATIVE_AIO) {
+ BDRVRawState *s = bs->opaque;
+ if (s->use_linux_aio) {
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
laio_io_unplug(bs, aio);
}
#if defined(__linux__)
+ BDRVRawState *s = bs->opaque;
struct stat st;
struct sg_scsi_id scsiid;
int sg_version;
+ int ret;
- if (stat(bs->filename, &st) >= 0 && S_ISCHR(st.st_mode) &&
- !bdrv_ioctl(bs, SG_GET_VERSION_NUM, &sg_version) &&
- !bdrv_ioctl(bs, SG_GET_SCSI_ID, &scsiid)) {
+ if (stat(bs->filename, &st) < 0 || !S_ISCHR(st.st_mode)) {
+ return false;
+ }
+
+ ret = ioctl(s->fd, SG_GET_VERSION_NUM, &sg_version);
+ if (ret < 0) {
+ return false;
+ }
+
+ ret = ioctl(s->fd, SG_GET_SCSI_ID, &scsiid);
+ if (ret >= 0) {
DPRINTF("SG device found: type=%d, version=%d\n",
scsiid.scsi_type, sg_version);
return true;