diff options
Diffstat (limited to 'hw/9pfs/9p.c')
-rw-r--r-- | hw/9pfs/9p.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 364c7cb446..e88bb50f13 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -630,6 +630,24 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len) V9fsState *s = pdu->s; int ret; + /* + * The 9p spec requires that successfully cancelled pdus receive no reply. + * Sending a reply would confuse clients because they would + * assume that any EINTR is the actual result of the operation, + * rather than a consequence of the cancellation. However, if + * the operation completed (succesfully or with an error other + * than caused be cancellation), we do send out that reply, both + * for efficiency and to avoid confusing the rest of the state machine + * that assumes passing a non-error here will mean a successful + * transmission of the reply. + */ + bool discard = pdu->cancelled && len == -EINTR; + if (discard) { + trace_v9fs_rcancel(pdu->tag, pdu->id); + pdu->size = 0; + goto out_notify; + } + if (len < 0) { int err = -len; len = 7; |