}
}
-void blk_register_buf(BlockBackend *blk, void *host, size_t size)
+bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp)
{
GLOBAL_STATE_CODE();
- bdrv_register_buf(blk_bs(blk), host, size);
+ return bdrv_register_buf(blk_bs(blk), host, size, errp);
}
void blk_unregister_buf(BlockBackend *blk, void *host, size_t size)
}
}
-void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size)
+/* Helper that undoes bdrv_register_buf() when it fails partway through */
+static void bdrv_register_buf_rollback(BlockDriverState *bs,
+ void *host,
+ size_t size,
+ BdrvChild *final_child)
+{
+ BdrvChild *child;
+
+ QLIST_FOREACH(child, &bs->children, next) {
+ if (child == final_child) {
+ break;
+ }
+
+ bdrv_unregister_buf(child->bs, host, size);
+ }
+
+ if (bs->drv && bs->drv->bdrv_unregister_buf) {
+ bs->drv->bdrv_unregister_buf(bs, host, size);
+ }
+}
+
+bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
+ Error **errp)
{
BdrvChild *child;
GLOBAL_STATE_CODE();
if (bs->drv && bs->drv->bdrv_register_buf) {
- bs->drv->bdrv_register_buf(bs, host, size);
+ if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) {
+ return false;
+ }
}
QLIST_FOREACH(child, &bs->children, next) {
- bdrv_register_buf(child->bs, host, size);
+ if (!bdrv_register_buf(child->bs, host, size, errp)) {
+ bdrv_register_buf_rollback(bs, host, size, child);
+ return false;
+ }
}
+ return true;
}
void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
}
}
-static void nvme_register_buf(BlockDriverState *bs, void *host, size_t size)
+static bool nvme_register_buf(BlockDriverState *bs, void *host, size_t size,
+ Error **errp)
{
int ret;
- Error *local_err = NULL;
BDRVNVMeState *s = bs->opaque;
- ret = qemu_vfio_dma_map(s->vfio, host, size, false, NULL, &local_err);
- if (ret) {
- /* FIXME: we may run out of IOVA addresses after repeated
- * bdrv_register_buf/bdrv_unregister_buf, because nvme_vfio_dma_unmap
- * doesn't reclaim addresses for fixed mappings. */
- error_reportf_err(local_err, "nvme_register_buf failed: ");
- }
+ /*
+ * FIXME: we may run out of IOVA addresses after repeated
+ * bdrv_register_buf/bdrv_unregister_buf, because nvme_vfio_dma_unmap
+ * doesn't reclaim addresses for fixed mappings.
+ */
+ ret = qemu_vfio_dma_map(s->vfio, host, size, false, NULL, errp);
+ return ret == 0;
}
static void nvme_unregister_buf(BlockDriverState *bs, void *host, size_t size)
*
* Buffers must not overlap and they must be unregistered with the same <host,
* size> values that they were registered with.
+ *
+ * Returns: true on success, false on failure
*/
-void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size);
+bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
+ Error **errp);
void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size);
void bdrv_cancel_in_flight(BlockDriverState *bs);
* that it can do IOMMU mapping with VFIO etc., in order to get better
* performance. In the case of VFIO drivers, this callback is used to do
* DMA mapping for hot buffers.
+ *
+ * Returns: true on success, false on failure
*/
- void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
+ bool (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size,
+ Error **errp);
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host, size_t size);
/*
void blk_io_limits_update_group(BlockBackend *blk, const char *group);
void blk_set_force_allow_inactivate(BlockBackend *blk);
-void blk_register_buf(BlockBackend *blk, void *host, size_t size);
+bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp);
void blk_unregister_buf(BlockBackend *blk, void *host, size_t size);
const BdrvChild *blk_root(BlockBackend *blk);
data.buf = blk_blockalign(blk, buf_size);
memset(data.buf, pattern, data.nrreq * data.bufsize);
- blk_register_buf(blk, data.buf, buf_size);
+ blk_register_buf(blk, data.buf, buf_size, &error_fatal);
data.qiov = g_new(QEMUIOVector, data.nrreq);
for (i = 0; i < data.nrreq; i++) {