From f0372dde6a0a6e7de7d0a7c2002d0282df6101eb Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Tue, 11 May 2021 10:25:26 +0900 Subject: [PATCH] fs: nfs: Fix rpcclnt_send() in TCP mode Summary: - I noticed that NFS over TCP does not work with Ubuntu 18.04 - Finally, I found that the record marking packet should not be sent separately - This commit fixes this issue Impact: - TCP mode only Testing: - Tested with NFS server on Ubuntu 18.04 (x86_64) - Tested with spresense:rndis (defconfig will be updated later) Signed-off-by: Masayuki Ishikawa --- fs/nfs/rpc_clnt.c | 51 +++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/fs/nfs/rpc_clnt.c b/fs/nfs/rpc_clnt.c index f57fed23bf0..93579667a45 100644 --- a/fs/nfs/rpc_clnt.c +++ b/fs/nfs/rpc_clnt.c @@ -297,32 +297,49 @@ bad: static int rpcclnt_send(FAR struct rpcclnt *rpc, FAR void *call, int reqlen) { + struct iovec iov[2]; + struct msghdr msg; uint32_t mark; int ret = OK; - /* Send the record marking(RM) for stream only */ - if (rpc->rc_sotype == SOCK_STREAM) { - mark = txdr_unsigned(0x80000000 | reqlen); - ret = psock_send(&rpc->rc_so, &mark, sizeof(mark), 0); - if (ret < 0) - { - ferr("ERROR: psock_send mark failed: %d\n", ret); - return ret; - } + /* Prepare the record marking(RM) and compose an RPC request + * NOTE: Sending a separate packet does not work with Linux host + */ + + mark = txdr_unsigned(0x80000000 | (reqlen)); + + iov[0].iov_base = (FAR void *)&mark; + iov[0].iov_len = sizeof(mark); + iov[1].iov_base = (FAR void *)call; + iov[1].iov_len = reqlen; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 2; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + ret = psock_sendmsg(&rpc->rc_so, &msg, 0); + ferr("ERROR: psock_sendmsg request failed: %d\n", ret); + } + else + { + /* Send the call message + * + * On success, psock_send returns the number of bytes sent; + * On failure, it returns a negated errno value. + */ + + ret = psock_send(&rpc->rc_so, call, reqlen, 0); + ferr("ERROR: psock_send request failed: %d\n", ret); } - /* Send the call message - * - * On success, psock_send returns the number of bytes sent; - * On failure, it returns a negated errno value. - */ - - ret = psock_send(&rpc->rc_so, call, reqlen, 0); if (ret < 0) { - ferr("ERROR: psock_send request failed: %d\n", ret); return ret; }