Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix svc_ioq_flushv send more msg #294

Merged
merged 1 commit into from
Apr 19, 2024
Merged

Conversation

liyinshubyte
Copy link

@liyinshubyte liyinshubyte commented Apr 16, 2024

copy from nfs-ganesha/nfs-ganesha#1115

@ffilz @dang we met nfs client hang for rpc length and body mismatch.

Reason
let's see the function svc_ioq_flushv in ntirpc.

step1
svc_ioq_flushv process an xioq with xioq->write_start=0, and end=10, i.e. there exist 10 bytes to send
step2
first into while loop with remaining=10, because xioq->write_start is 0, so frag_hdr_size is 4 bytes, and we need 4 bytes header to save the length of 10 bytes, so need to send 14bytes = 4bytes(header) + 10bytes(body).
step3
sendmsg send 2 bytes of header, and result=2 which less than frag_hdr_size=4bytes, and goto again
step4
in again, sendmsg send 5bytes(result=5) including 2bytes header and 3bytes body, then result-= frag_hdr_size, so result=1, then remaining-=result, so remaining is 9bytes, and xioq->write_start+=result, so xioq->write_start=1. but actually remaining should be 7 and xioq->write_start should be 3, because already sent [0, 3)bytes body.
step5
twice into while loop with remaining=9, and xioq->write_start=1, so send [1, 3)bytes body again. i.e. we send [1, 3)bytes body twice times in step4 and step5. and error happens.

Copy link
Collaborator

@dang dang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. It must be an extremely rare case that <4 bytes get sent.

@liyinshubyte
Copy link
Author

the more interesting thing is, debian client can not reproduce this client hang, but we can reproduce this on ubuntu client.

@@ -257,6 +257,7 @@ svc_ioq_flushv(SVCXPRT *xprt, struct xdr_ioq *xioq)
xioq->frag_hdr_bytes_sent += result;
iov[0].iov_base += result;
iov[0].iov_len -= result;
frag_hdr_size -= result;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to cause a problem down below when frag_hdr_size is subtracted from result?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Maybe, instead, use
if (result < (frag_hdr_size - xioq->frag_hdr_bytes_sent))

Copy link
Author

@liyinshubyte liyinshubyte Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to cause a problem down below when frag_hdr_size is subtracted from result?

sorry, I checked the code, but did not find this will cause a problem. actually, the variable related to frag_hdr_size is remaining, fbytes and xioq->write_start, all need frag_hdr_size is subtracted from result.

Copy link
Author

@liyinshubyte liyinshubyte Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Maybe, instead, use if (result < (frag_hdr_size - xioq->frag_hdr_bytes_sent))

if we only use if (result < (frag_hdr_size - xioq->frag_hdr_bytes_sent)) to replace if (result < frag_hdr_size). but without the change of this pull request, xioq->write_start will be wrong and the problem still exist.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if the whole frag header isn't sent, we goto again, to try and send the rest of it.

Below, when frag_hdr_size is used, it's after all the attempts to send, so we would only subtract the reduced frag_hdr_size from remaining and fbytes, and add to write_start. But since we've sent the whole frag header, we should change all of those by the original frag_hdr_size

Copy link
Author

@liyinshubyte liyinshubyte Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffilz thanks the reply, remaining and fbytes always record the left body length, it should not subtract the frag header. remaining come from remaining = end - xioq->write_start. in the second time we send 5bytes(result=5) including the left 2bytes frag header and 3bytes body, then remaining should subtract 3 bytes, but currently remaining only subtract 1 bytes, this cause send more msg.

For example, the data is ABCDEF, the second send 2bytes header and ABC, remaining should subtract 3, but it subtract 1 which means it only send A, then it will send BCDEF, which cause BC send two times.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I agree.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I see it now. Can we have some comments talking about what's going on here because it is really confusing as evidenced by my confusion throughout this discussion. Maybe an example showing the two packets, one with part of the fragment header, and the other with the rest of the fragment header and some portion of the fragment.

Other than that, I approve of this change now that I understand it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, already add some comments.

@dang dang self-requested a review April 16, 2024 18:07
@@ -257,6 +257,7 @@ svc_ioq_flushv(SVCXPRT *xprt, struct xdr_ioq *xioq)
xioq->frag_hdr_bytes_sent += result;
iov[0].iov_base += result;
iov[0].iov_len -= result;
frag_hdr_size -= result;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I agree.

@dang
Copy link
Collaborator

dang commented Apr 19, 2024

This probably rates a pullup in the next -dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants