char *name;
off_t dev_offset;
off_t size;
- uint32_t nbdflags;
+ uint16_t nbdflags;
QTAILQ_HEAD(, NBDClient) clients;
QTAILQ_ENTRY(NBDExport) next;
AioContext *ctx;
+ BlockBackend *eject_notifier_blk;
Notifier eject_notifier;
};
GIOCondition condition,
void *opaque)
{
- qemu_coroutine_enter(opaque, NULL);
+ qemu_coroutine_enter(opaque);
return TRUE;
}
NBDClient *client = data->client;
char buf[8 + 8 + 8 + 128];
int rc;
- const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
- NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
+ const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
+ NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
bool oldStyle;
/* Old style negotiation header without options
oldStyle = client->exp != NULL && !client->tlscreds;
if (oldStyle) {
- assert ((client->exp->nbdflags & ~65535) == 0);
TRACE("advertising size %" PRIu64 " and flags %x",
client->exp->size, client->exp->nbdflags | myflags);
stq_be_p(buf + 8, NBD_CLIENT_MAGIC);
goto fail;
}
- assert ((client->exp->nbdflags & ~65535) == 0);
TRACE("advertising size %" PRIu64 " and flags %x",
client->exp->size, client->exp->nbdflags | myflags);
stq_be_p(buf + 18, client->exp->size);
nbd_export_close(exp);
}
-NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
- uint32_t nbdflags, void (*close)(NBDExport *),
+NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
+ uint16_t nbdflags, void (*close)(NBDExport *),
+ bool writethrough, BlockBackend *on_eject_blk,
Error **errp)
{
+ BlockBackend *blk;
NBDExport *exp = g_malloc0(sizeof(NBDExport));
+
+ blk = blk_new();
+ blk_insert_bs(blk, bs);
+ blk_set_enable_write_cache(blk, !writethrough);
+
exp->refcount = 1;
QTAILQ_INIT(&exp->clients);
exp->blk = blk;
exp->close = close;
exp->ctx = blk_get_aio_context(blk);
- blk_ref(blk);
blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
- exp->eject_notifier.notify = nbd_eject_notifier;
- blk_add_remove_bs_notifier(blk, &exp->eject_notifier);
+ if (on_eject_blk) {
+ blk_ref(on_eject_blk);
+ exp->eject_notifier_blk = on_eject_blk;
+ exp->eject_notifier.notify = nbd_eject_notifier;
+ blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier);
+ }
/*
* NBD exports are used for non-shared storage migration. Make sure
return exp;
fail:
+ blk_unref(blk);
g_free(exp);
return NULL;
}
}
if (exp->blk) {
- notifier_remove(&exp->eject_notifier);
+ if (exp->eject_notifier_blk) {
+ notifier_remove(&exp->eject_notifier);
+ blk_unref(exp->eject_notifier_blk);
+ }
blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
blk_aio_detach, exp);
blk_unref(exp->blk);
if (request->type & ~NBD_CMD_MASK_COMMAND & ~NBD_CMD_FLAG_FUA) {
LOG("unsupported flags (got 0x%x)",
request->type & ~NBD_CMD_MASK_COMMAND);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
rc = 0;
break;
case NBD_CMD_TRIM:
TRACE("Request type is TRIM");
- /* Ignore unaligned head or tail, until block layer adds byte
- * interface */
- if (request.len >= BDRV_SECTOR_SIZE) {
- request.len -= (request.from + request.len) % BDRV_SECTOR_SIZE;
- ret = blk_co_discard(exp->blk,
- DIV_ROUND_UP(request.from + exp->dev_offset,
- BDRV_SECTOR_SIZE),
- request.len / BDRV_SECTOR_SIZE);
- if (ret < 0) {
- LOG("discard failed");
- reply.error = -ret;
- }
- } else {
- TRACE("trim request too small, ignoring");
+ ret = blk_co_pdiscard(exp->blk, request.from + exp->dev_offset,
+ request.len);
+ if (ret < 0) {
+ LOG("discard failed");
+ reply.error = -ret;
}
if (nbd_co_send_reply(req, &reply, 0) < 0) {
goto out;
NBDClient *client = opaque;
if (client->recv_coroutine) {
- qemu_coroutine_enter(client->recv_coroutine, NULL);
+ qemu_coroutine_enter(client->recv_coroutine);
} else {
- qemu_coroutine_enter(qemu_coroutine_create(nbd_trip), client);
+ qemu_coroutine_enter(qemu_coroutine_create(nbd_trip, client));
}
}
{
NBDClient *client = opaque;
- qemu_coroutine_enter(client->send_coroutine, NULL);
+ qemu_coroutine_enter(client->send_coroutine);
}
static void nbd_set_handlers(NBDClient *client)
client->close = close_fn;
data->client = client;
- data->co = qemu_coroutine_create(nbd_co_client_start);
- qemu_coroutine_enter(data->co, data);
+ data->co = qemu_coroutine_create(nbd_co_client_start, data);
+ qemu_coroutine_enter(data->co);
}