When retrying MNT requests with lower RPC protocol versions, the showmount command leaves several TCP sockets in TIME_WAIT: at least one socket for each rpcbind GETPORT call, and one for each attempted MNT request. Note that TIME_WAIT sockets may not be a problem on an individual client, but this does tie up potentially valuable network resources on the server for up to 120 seconds. To reduce the resources required when retrying, downshift the RPC protocol version of the existing RPC client using CLNT_CONTROL(), rather than creating a new RPC client for each RPC protocol version. Without this patch, "showmount -e" targeting a TCP-capable server with a single export takes 64 packets and leaves 6 sockets in TIME_WAIT if the server supports only MNTv1. With it, showmount takes 29 packets and leaves two TIME_WAIT sockets. Newer versions of libtirpc will reduce that by one more socket (on IPv4), and a handful of packets. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- utils/showmount/showmount.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/utils/showmount/showmount.c b/utils/showmount/showmount.c index 652aa85..343f94b 100644 --- a/utils/showmount/showmount.c +++ b/utils/showmount/showmount.c @@ -193,12 +193,12 @@ int main(int argc, char **argv) break; } -again: mclient = nfs_get_mount_client(hostname, mount_vers_tbl[vers]); mclient->cl_auth = authunix_create_default(); total_timeout.tv_sec = TOTAL_TIMEOUT; total_timeout.tv_usec = 0; +again: if (eflag) { memset(&exportlist, '\0', sizeof(exportlist)); @@ -207,8 +207,11 @@ again: (xdrproc_t) xdr_exports, (caddr_t) &exportlist, total_timeout); if (clnt_stat == RPC_PROGVERSMISMATCH) { - if (++vers < max_vers_tblsz) + if (++vers < max_vers_tblsz) { + (void)CLNT_CONTROL(mclient, CLSET_VERS, + (void *)&mount_vers_tbl[vers]); goto again; + } } if (clnt_stat != RPC_SUCCESS) { clnt_perror(mclient, "rpc mount export"); @@ -246,8 +249,11 @@ again: (xdrproc_t) xdr_mountlist, (caddr_t) &dumplist, total_timeout); if (clnt_stat == RPC_PROGVERSMISMATCH) { - if (++vers < max_vers_tblsz) + if (++vers < max_vers_tblsz) { + (void)CLNT_CONTROL(mclient, CLSET_VERS, + (void *)&mount_vers_tbl[vers]); goto again; + } } if (clnt_stat != RPC_SUCCESS) { clnt_perror(mclient, "rpc mount dump"); -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html