};
static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
+static QTAILQ_HEAD(, NBDExport) closed_exports =
+ QTAILQ_HEAD_INITIALIZER(closed_exports);
/* NBDExportMetaContexts represents a list of contexts to be exported,
* as selected by NBD_OPT_SET_META_CONTEXT. Also used for
if (bitmap) {
BdrvDirtyBitmap *bm = NULL;
- while (true) {
+ while (bs) {
bm = bdrv_find_dirty_bitmap(bs, bitmap);
- if (bm != NULL || bs->backing == NULL) {
+ if (bm != NULL) {
break;
}
- bs = bs->backing->bs;
+ bs = bdrv_filter_or_cow_bs(bs);
}
if (bm == NULL) {
g_free(exp->name);
exp->name = NULL;
QTAILQ_REMOVE(&exports, exp, next);
+ QTAILQ_INSERT_TAIL(&closed_exports, exp, next);
}
g_free(exp->description);
exp->description = NULL;
g_free(exp->export_bitmap_context);
}
+ QTAILQ_REMOVE(&closed_exports, exp, next);
g_free(exp);
+ aio_wait_kick();
}
}
nbd_export_close(exp);
aio_context_release(aio_context);
}
+
+ AIO_WAIT_WHILE(NULL, !(QTAILQ_EMPTY(&exports) &&
+ QTAILQ_EMPTY(&closed_exports)));
}
static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov,
if (request->flags & NBD_CMD_FLAG_FAST_ZERO) {
flags |= BDRV_REQ_NO_FALLBACK;
}
- ret = blk_pwrite_zeroes(exp->blk, request->from + exp->dev_offset,
- request->len, flags);
+ ret = 0;
+ /* FIXME simplify this when blk_pwrite_zeroes switches to 64-bit */
+ while (ret >= 0 && request->len) {
+ int align = client->check_align ?: 1;
+ int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES,
+ align));
+ ret = blk_pwrite_zeroes(exp->blk, request->from + exp->dev_offset,
+ len, flags);
+ request->len -= len;
+ request->from += len;
+ }
return nbd_send_generic_reply(client, request->handle, ret,
"writing to file failed", errp);
"flush failed", errp);
case NBD_CMD_TRIM:
- ret = blk_co_pdiscard(exp->blk, request->from + exp->dev_offset,
- request->len);
- if (ret == 0 && request->flags & NBD_CMD_FLAG_FUA) {
+ ret = 0;
+ /* FIXME simplify this when blk_co_pdiscard switches to 64-bit */
+ while (ret >= 0 && request->len) {
+ int align = client->check_align ?: 1;
+ int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES,
+ align));
+ ret = blk_co_pdiscard(exp->blk, request->from + exp->dev_offset,
+ len);
+ request->len -= len;
+ request->from += len;
+ }
+ if (ret >= 0 && request->flags & NBD_CMD_FLAG_FUA) {
ret = blk_co_flush(exp->blk);
}
return nbd_send_generic_reply(client, request->handle, ret,