From owner-freebsd-bugs@FreeBSD.ORG Mon Jan 3 21:40:20 2005 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C86A916A4CE for ; Mon, 3 Jan 2005 21:40:20 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9AF3A43D49 for ; Mon, 3 Jan 2005 21:40:20 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.1/8.13.1) with ESMTP id j03LeKZL085210 for ; Mon, 3 Jan 2005 21:40:20 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.1/8.13.1/Submit) id j03LeKrB085209; Mon, 3 Jan 2005 21:40:20 GMT (envelope-from gnats) Resent-Date: Mon, 3 Jan 2005 21:40:20 GMT Resent-Message-Id: <200501032140.j03LeKrB085209@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Mike Hibler Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 371FF16A4CE for ; Mon, 3 Jan 2005 21:33:00 +0000 (GMT) Received: from bas.flux.utah.edu (bas.flux.utah.edu [155.98.60.2]) by mx1.FreeBSD.org (Postfix) with ESMTP id C3A8C43D2F for ; Mon, 3 Jan 2005 21:32:59 +0000 (GMT) (envelope-from mike@flux.utah.edu) Received: from bas.flux.utah.edu (localhost [127.0.0.1]) by bas.flux.utah.edu (8.12.11/8.12.5) with ESMTP id j03LWxcO036532 for ; Mon, 3 Jan 2005 14:32:59 -0700 (MST) (envelope-from mike@bas.flux.utah.edu) Received: (from mike@localhost) by bas.flux.utah.edu (8.12.11/8.13.1/Submit) id j03LWwPc036531; Mon, 3 Jan 2005 14:32:58 -0700 (MST) (envelope-from mike) Message-Id: <200501032132.j03LWwPc036531@bas.flux.utah.edu> Date: Mon, 3 Jan 2005 14:32:58 -0700 (MST) From: Mike Hibler To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/75766: [patch] nfsd loops with TCP + multiple -h options X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Mike Hibler List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Jan 2005 21:40:21 -0000 >Number: 75766 >Category: bin >Synopsis: [patch] nfsd loops with TCP + multiple -h options >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Jan 03 21:40:20 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Mike Hibler >Release: FreeBSD 4.x >Organization: University of Utah >Environment: System: FreeBSD bas.flux.utah.edu 4.10-RELEASE-p5 FreeBSD 4.10-RELEASE-p5 #2: Thu Dec 30 16:50:05 MST 2004 root@bas.flux.utah.edu:/usr/obj/usr/src/sys/BAS i386 >Description: Running nfsd with TCP support (-t) and multiple -h options can lead to the nfsd master process spinning furiously. In short, when the master nfsd process returns from a select involving multiple fds, it only attempts to process the last fd rather than looping over all fds in the set. This bug exists in all 4.x versions as far as I know. >How-To-Repeat: Run nfsd with TCP support (-t) and multiple -h options and attempt to connect via any network except that of the last interface listed with -h. >Fix: Following is the minimal fix extracted from -CURRENT to fix the problem; i.e., stick a loop around the FD_ISSET() processing. Note that I did not bother to fix the "notyet" code. --- nfsd.c 2005/01/03 20:37:09 1.1 +++ nfsd.c 2005/01/03 20:41:44 @@ -593,26 +593,29 @@ exit(1); } } - if (tcpflag && FD_ISSET(tcpsock, &ready)) { - len = sizeof(inetpeer); - if ((msgsock = accept(tcpsock, - (struct sockaddr *)&inetpeer, &len)) < 0) { - syslog(LOG_ERR, "accept failed: %m"); - if (errno == ECONNABORTED || - errno == EINTR) - continue; - exit(1); + for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { + if (FD_ISSET(tcpsock, &ready)) { + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) { + syslog(LOG_ERR, "accept failed: %m"); + if (errno == ECONNABORTED || + errno == EINTR) + continue; + exit(1); + } + memset(inetpeer.sin_zero, 0, + sizeof(inetpeer.sin_zero)); + if (setsockopt(msgsock, SOL_SOCKET, + SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, + "setsockopt SO_KEEPALIVE: %m"); + nfsdargs.sock = msgsock; + nfsdargs.name = (caddr_t)&inetpeer; + nfsdargs.namelen = sizeof(inetpeer); + nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + (void)close(msgsock); } - memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); - if (setsockopt(msgsock, SOL_SOCKET, - SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) - syslog(LOG_ERR, - "setsockopt SO_KEEPALIVE: %m"); - nfsdargs.sock = msgsock; - nfsdargs.name = (caddr_t)&inetpeer; - nfsdargs.namelen = sizeof(inetpeer); - nfssvc(NFSSVC_ADDSOCK, &nfsdargs); - (void)close(msgsock); } #ifdef notyet if (tp4flag && FD_ISSET(tp4sock, &ready)) { >Release-Note: >Audit-Trail: >Unformatted: