diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2026-09-03 09:43:07 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2026-09-03 09:43:07 +0100 |
| commit | 7eddb112ab207aa0b845e87a45204a87f2f4acd9 (patch) | |
| tree | 542397ea5497c47dabef7aa456b6d42d38f2d263 /block | |
| parent | 1a8f18541eef8761a709e44708758a4c08b50a15 (diff) | |
| parent | 29ed9606ba15aa346eaec349d169f90eff56fd01 (diff) | |
| download | qemu-7eddb112ab207aa0b845e87a45204a87f2f4acd9.tar.gz qemu-7eddb112ab207aa0b845e87a45204a87f2f4acd9.zip | |
Merge tag 'pull-nbd-2026-09-02' of https://gitlab.com/vsementsov/qemu into staging
block: nbd patches
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEi5wmzbL9FHyIDoahVh8kwfGfefsFAmqX4VgACgkQVh8kwfGf
# efv1KA//XpVJjBnou5RRgPvpGeTJz5G0ouI78sWsYFbqFRz1P/lvbvkl40a9wAJy
# 5IAeNCAj1FtTKJ+GMTVWKfLKn4fVLWdhcPX+33gxpVLbqx5uHweqxKN38p+hAvcr
# PtyVWX6kMRXGAyL7s3wb5qcvGqH/hf9+RG8hK+2KbrHnDJw7MRaicq17U7FL4Fzg
# EKxQMwGsjPEBGZYWSbYj6TfZI1sglfFifBEv5Y+kC2pWgVmmmXNRqXZcRPGNVBNS
# xMYus/nYPZAD3IdomCoQIERoccY5/mavy4UBQ2RdTNow4PiCMnjo+kRJRTrstBAE
# LokC9nUVs0hQkAd7Cq+M6aqXREJDfg871S4hYZmdpAsi6lIJPx6JvnjZ9NbO1TQY
# xvAThopZTA6qxgVc88K26/zwnJf3+tKgQ4JAKB7Pt25hPc4BJiYA/Uo8vIR7pu9H
# o1R+DAMWETv/x8J17+pbH8OgjqSe/KzptgwEi94lplz5lOTJOGvHz/5njPam6AsC
# 40DGtGG+ZoE7GTIKg2C3iYce+K0FtcM0ANuWj99bVO8vNdpKuv0TsCHLPSFViYev
# v37s20UVCX7AO4Q2G868BWUPwLFXSI+ENiT6Xbiwa3hBLGZK5fjqWwJxJVwSOA3q
# 3LpRNgCoDDO0kjkwqOh9000OjQhaBHOftax3mzW++Fb+TizW1n4=
# =IST8
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed Sep 2 09:42:00 2026 BST
# gpg: using RSA key 8B9C26CDB2FD147C880E86A1561F24C1F19F79FB
# gpg: Good signature from "Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>" [unknown]
# gpg: aka "Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8B9C 26CD B2FD 147C 880E 86A1 561F 24C1 F19F 79FB
* tag 'pull-nbd-2026-09-02' of https://gitlab.com/vsementsov/qemu:
iotests/nbd-commands: cover the command flags and sparse replies
iotests/nbd-commands: cover NBD_CMD_BLOCK_STATUS with a payload
iotests/nbd-commands: exercise the simple and structured reply modes
nbd/server: accept NBD_CMD_CACHE above the maximum payload size
iotests: add coverage for NBD transmission commands
block/nbd: clear reply.cookie under receive_mutex
block/nbd: never index requests[] with an unchecked cookie
block/nbd: clear reply.cookie when the reply is rejected
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block')
| -rw-r--r-- | block/nbd.c | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/block/nbd.c b/block/nbd.c index 5d231d5c4e..e5e16722ba 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -136,6 +136,19 @@ static void nbd_clear_bdrvstate(BlockDriverState *bs) s->x_dirty_bitmap = NULL; } +static NBDClientRequest *nbd_request_by_cookie(BDRVNBDState *s, uint64_t cookie, + Error **errp) +{ + uint64_t ind = COOKIE_TO_INDEX(cookie); + + if (ind >= MAX_NBD_REQUESTS || !s->requests[ind].coroutine) { + error_setg(errp, "unexpected cookie value"); + return NULL; + } + + return &s->requests[ind]; +} + /* Called with s->receive_mutex taken. */ static bool coroutine_fn nbd_recv_coroutine_wake_one(NBDClientRequest *req) { @@ -148,11 +161,11 @@ static bool coroutine_fn nbd_recv_coroutine_wake_one(NBDClientRequest *req) return false; } +/* Called with s->receive_mutex taken. */ static void coroutine_fn nbd_recv_coroutines_wake(BDRVNBDState *s) { int i; - QEMU_LOCK_GUARD(&s->receive_mutex); for (i = 0; i < MAX_NBD_REQUESTS; i++) { if (nbd_recv_coroutine_wake_one(&s->requests[i])) { return; @@ -422,7 +435,8 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie, Error **errp) { int ret; - uint64_t ind = COOKIE_TO_INDEX(cookie), ind2; + NBDClientRequest *req = nbd_request_by_cookie(s, cookie, &error_abort); + NBDClientRequest *owner; QEMU_LOCK_GUARD(&s->receive_mutex); while (true) { @@ -437,10 +451,10 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie, * woken by whoever set s->reply.cookie (or never wait in this * yield). So, we should not wake it here. */ - ind2 = COOKIE_TO_INDEX(s->reply.cookie); - assert(!s->requests[ind2].receiving); + owner = nbd_request_by_cookie(s, s->reply.cookie, &error_abort); + assert(!owner->receiving); - s->requests[ind].receiving = true; + req->receiving = true; qemu_co_mutex_unlock(&s->receive_mutex); qemu_coroutine_yield(); @@ -454,7 +468,7 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie, */ qemu_co_mutex_lock(&s->receive_mutex); - assert(!s->requests[ind].receiving); + assert(!req->receiving); continue; } @@ -466,27 +480,32 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie, error_setg(errp, "server dropped connection"); } if (ret < 0) { - nbd_channel_error(s, ret); - return ret; + goto err; } if (nbd_reply_is_structured(&s->reply) && s->info.mode < NBD_MODE_STRUCTURED) { - nbd_channel_error(s, -EINVAL); + ret = -EINVAL; error_setg(errp, "unexpected structured reply"); - return -EINVAL; + goto err; } - ind2 = COOKIE_TO_INDEX(s->reply.cookie); - if (ind2 >= MAX_NBD_REQUESTS || !s->requests[ind2].coroutine) { - nbd_channel_error(s, -EINVAL); - error_setg(errp, "unexpected cookie value"); - return -EINVAL; + owner = nbd_request_by_cookie(s, s->reply.cookie, errp); + if (!owner) { + ret = -EINVAL; + goto err; } if (s->reply.cookie == cookie) { /* We are done */ return 0; } - nbd_recv_coroutine_wake_one(&s->requests[ind2]); + nbd_recv_coroutine_wake_one(owner); } + +err: + /* Waiters look at this cookie, so do not leave a rejected one behind. */ + s->reply.cookie = 0; + nbd_channel_error(s, ret); + + return ret; } static int coroutine_fn GRAPH_RDLOCK @@ -855,7 +874,6 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( { ERRP_GUARD(); int ret; - int i = COOKIE_TO_INDEX(cookie); void *local_payload = NULL; NBDStructuredReplyChunk *chunk; @@ -913,8 +931,9 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( return -EINVAL; } - return nbd_co_receive_offset_data_payload(s, s->requests[i].offset, - qiov, errp); + return nbd_co_receive_offset_data_payload( + s, nbd_request_by_cookie(s, cookie, &error_abort)->offset, + qiov, errp); } if (nbd_reply_type_is_error(chunk->type)) { @@ -955,9 +974,11 @@ static coroutine_fn int nbd_co_receive_one_chunk( /* For assert at loop start in nbd_connection_entry */ *reply = s->reply; } - s->reply.cookie = 0; - nbd_recv_coroutines_wake(s); + WITH_QEMU_LOCK_GUARD(&s->receive_mutex) { + s->reply.cookie = 0; + nbd_recv_coroutines_wake(s); + } return ret; } @@ -1061,7 +1082,7 @@ static bool coroutine_fn nbd_reply_chunk_iter_receive(BDRVNBDState *s, break_loop: qemu_mutex_lock(&s->requests_lock); - s->requests[COOKIE_TO_INDEX(cookie)].coroutine = NULL; + nbd_request_by_cookie(s, cookie, &error_abort)->coroutine = NULL; s->in_flight--; qemu_co_queue_next(&s->free_sema); qemu_mutex_unlock(&s->requests_lock); |
