}
#endif
- bs->supported_zero_flags = s->discard_zeroes ? BDRV_REQ_MAY_UNMAP : 0;
+ bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP;
ret = 0;
fail:
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
"Failed to get \"%s\" lock",
perm_name);
g_free(perm_name);
- error_append_hint(errp,
- "Is another process using the image?\n");
return ret;
}
}
"Failed to get shared \"%s\" lock",
perm_name);
g_free(perm_name);
- error_append_hint(errp,
- "Is another process using the image?\n");
return ret;
}
}
if (!ret) {
return 0;
}
+ error_append_hint(errp,
+ "Is another process using the image [%s]?\n",
+ bs->filename);
}
op = RAW_PL_ABORT;
/* fall through to unlock bytes. */
goto out;
}
- rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped",
- s->check_cache_dropped);
+ rs->check_cache_dropped =
+ qemu_opt_get_bool_del(opts, "x-check-cache-dropped", false);
+
+ /* This driver's reopen function doesn't currently allow changing
+ * other options, so let's put them back in the original QDict and
+ * bdrv_reopen_prepare() will detect changes and complain. */
+ qemu_opts_to_qdict(opts, state->options);
if (s->type == FTYPE_CD) {
rs->open_flags |= O_NONBLOCK;
return -ENOTSUP;
}
+static ssize_t handle_aiocb_write_zeroes_unmap(RawPosixAIOData *aiocb)
+{
+ BDRVRawState *s G_GNUC_UNUSED = aiocb->bs->opaque;
+ int ret;
+
+ /* First try to write zeros and unmap at the same time */
+
+#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
+ ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ aiocb->aio_offset, aiocb->aio_nbytes);
+ if (ret != -ENOTSUP) {
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_XFS
+ if (s->is_xfs) {
+ /* xfs_discard() guarantees that the discarded area reads as all-zero
+ * afterwards, so we can use it here. */
+ return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes);
+ }
+#endif
+
+ /* If we couldn't manage to unmap while guaranteed that the area reads as
+ * all-zero afterwards, just write zeroes without unmapping */
+ ret = handle_aiocb_write_zeroes(aiocb);
+ return ret;
+}
+
#ifndef HAVE_COPY_FILE_RANGE
static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
off_t *out_off, size_t len, unsigned int flags)
num = MIN(left, 65536);
result = write(fd, buf, num);
if (result < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
result = -errno;
error_setg_errno(errp, -result,
"Could not write zeros for preallocation");
case QEMU_AIO_WRITE_ZEROES:
ret = handle_aiocb_write_zeroes(aiocb);
break;
+ case QEMU_AIO_WRITE_ZEROES | QEMU_AIO_DISCARD:
+ ret = handle_aiocb_write_zeroes_unmap(aiocb);
+ break;
case QEMU_AIO_COPY_RANGE:
ret = handle_aiocb_copy_range(aiocb);
break;
/* Step two: Check that nobody else has taken conflicting locks */
result = raw_check_lock_bytes(fd, perm, shared, errp);
if (result < 0) {
+ error_append_hint(errp,
+ "Is another process using the image [%s]?\n",
+ file_opts->filename);
goto out_unlock;
}
int bytes, BdrvRequestFlags flags)
{
BDRVRawState *s = bs->opaque;
+ int operation = QEMU_AIO_WRITE_ZEROES;
- if (!(flags & BDRV_REQ_MAY_UNMAP)) {
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
- QEMU_AIO_WRITE_ZEROES);
- } else if (s->discard_zeroes) {
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
- QEMU_AIO_DISCARD);
+ if (flags & BDRV_REQ_MAY_UNMAP) {
+ operation |= QEMU_AIO_DISCARD;
}
- return -ENOTSUP;
+
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes, operation);
}
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
int64_t offset, int bytes, BdrvRequestFlags flags)
{
BDRVRawState *s = bs->opaque;
+ int operation = QEMU_AIO_WRITE_ZEROES | QEMU_AIO_BLKDEV;
int rc;
rc = fd_open(bs);
if (rc < 0) {
return rc;
}
- if (!(flags & BDRV_REQ_MAY_UNMAP)) {
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
- QEMU_AIO_WRITE_ZEROES|QEMU_AIO_BLKDEV);
- } else if (s->discard_zeroes) {
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
- QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
+
+ if (flags & BDRV_REQ_MAY_UNMAP) {
+ operation |= QEMU_AIO_DISCARD;
}
- return -ENOTSUP;
+
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes, operation);
}
static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
.bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug,
.bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug,
.bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength,
.bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug,
.bdrv_io_unplug = raw_aio_unplug,
+ .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate,
.bdrv_getlength = raw_getlength,