From owner-svn-src-all@freebsd.org Tue Sep 3 14:07:40 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id EA375DD080; Tue, 3 Sep 2019 14:06:51 +0000 (UTC) (envelope-from yuripv@freebsd.org) Received: from freefall.freebsd.org (freefall.freebsd.org [96.47.72.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "freefall.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46N7zv1q1mz4PyP; Tue, 3 Sep 2019 14:06:51 +0000 (UTC) (envelope-from yuripv@freebsd.org) Received: by freefall.freebsd.org (Postfix, from userid 1452) id 2FF841AC84; Tue, 3 Sep 2019 14:06:19 +0000 (UTC) X-Original-To: yuripv@localmail.freebsd.org Delivered-To: yuripv@localmail.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client CN "mx1.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by freefall.freebsd.org (Postfix) with ESMTPS id 6305B1F136; Mon, 15 Apr 2019 01:27:20 +0000 (UTC) (envelope-from owner-src-committers@freebsd.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2610:1c1:1:6074::16:84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "freefall.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 2DE748A403; Mon, 15 Apr 2019 01:27:20 +0000 (UTC) (envelope-from owner-src-committers@freebsd.org) Received: by freefall.freebsd.org (Postfix, from userid 538) id 150021F134; Mon, 15 Apr 2019 01:27:20 +0000 (UTC) Delivered-To: src-committers@localmail.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client CN "mx1.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by freefall.freebsd.org (Postfix) with ESMTPS id 91F251F132 for ; Mon, 15 Apr 2019 01:27:17 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47CFA8A3FD; Mon, 15 Apr 2019 01:27:17 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 36647D0E; Mon, 15 Apr 2019 01:27:17 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x3F1RHWi062977; Mon, 15 Apr 2019 01:27:17 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x3F1RG7X062973; Mon, 15 Apr 2019 01:27:16 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201904150127.x3F1RG7X062973@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r346217 - in head/sys: fs/nfs fs/nfsclient kern sys X-SVN-Group: head X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in head/sys: fs/nfs fs/nfsclient kern sys X-SVN-Commit-Revision: 346217 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk X-Loop: FreeBSD.org Sender: owner-src-committers@freebsd.org X-Rspamd-Queue-Id: 2DE748A403 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.94 / 15.00]; local_wl_from(0.00)[freebsd.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.94)[-0.944,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] Status: O X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Date: Tue, 03 Sep 2019 14:07:41 -0000 X-Original-Date: Mon, 15 Apr 2019 01:27:16 +0000 (UTC) X-List-Received-Date: Tue, 03 Sep 2019 14:07:41 -0000 Author: rmacklem Date: Mon Apr 15 01:27:15 2019 New Revision: 346217 URL: https://svnweb.freebsd.org/changeset/base/346217 Log: Fix the NFSv4 client to safely find processes. r340744 broke the NFSv4 client, because it replaced pfind_locked() with a call to pfind(), since pfind() acquires the sx lock for the pid hash and the NFSv4 already holds a mutex when it does the call. The patch fixes the problem by recreating a pfind_any_locked() and adding the functions pidhash_slockall() and pidhash_sunlockall to acquire/release all of the pid hash locks. These functions are then used by the NFSv4 client instead of acquiring the allproc_lock and calling pfind(). Reviewed by: kib, mjg MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D19887 Modified: head/sys/fs/nfs/nfsport.h head/sys/fs/nfsclient/nfs_clport.c head/sys/fs/nfsclient/nfs_clstate.c head/sys/kern/kern_proc.c head/sys/sys/proc.h Modified: head/sys/fs/nfs/nfsport.h ============================================================================== --- head/sys/fs/nfs/nfsport.h Sun Apr 14 18:04:53 2019 (r346216) +++ head/sys/fs/nfs/nfsport.h Mon Apr 15 01:27:15 2019 (r346217) @@ -692,8 +692,6 @@ void nfsrvd_rcv(struct socket *, void *, int); #define NFSUNLOCKMNT(m) mtx_unlock(&((m)->nm_mtx)) #define NFSLOCKREQUEST(r) mtx_lock(&((r)->r_mtx)) #define NFSUNLOCKREQUEST(r) mtx_unlock(&((r)->r_mtx)) -#define NFSPROCLISTLOCK() sx_slock(&allproc_lock) -#define NFSPROCLISTUNLOCK() sx_sunlock(&allproc_lock) #define NFSLOCKSOCKREQ(r) mtx_lock(&((r)->nr_mtx)) #define NFSUNLOCKSOCKREQ(r) mtx_unlock(&((r)->nr_mtx)) #define NFSLOCKDS(d) mtx_lock(&((d)->nfsclds_mtx)) Modified: head/sys/fs/nfsclient/nfs_clport.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clport.c Sun Apr 14 18:04:53 2019 (r346216) +++ head/sys/fs/nfsclient/nfs_clport.c Mon Apr 15 01:27:15 2019 (r346217) @@ -1156,7 +1156,7 @@ nfscl_procdoesntexist(u_int8_t *own) tl.cval[2] = *own++; tl.cval[3] = *own++; pid = tl.lval; - p = pfind(pid); + p = pfind_any_locked(pid); if (p == NULL) return (1); if (p->p_stats == NULL) { Modified: head/sys/fs/nfsclient/nfs_clstate.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clstate.c Sun Apr 14 18:04:53 2019 (r346216) +++ head/sys/fs/nfsclient/nfs_clstate.c Mon Apr 15 01:27:15 2019 (r346217) @@ -1789,7 +1789,13 @@ nfscl_cleanupkext(struct nfsclclient *clp, struct nfsc struct nfscllockowner *lp, *nlp; struct nfscldeleg *dp; - NFSPROCLISTLOCK(); + /* + * All the pidhash locks must be acquired, since they are sx locks + * and must be acquired before the mutexes. The pid(s) that will + * be used aren't known yet, so all the locks need to be acquired. + * Fortunately, this function is only performed once/sec. + */ + pidhash_slockall(); NFSLOCKCLSTATE(); LIST_FOREACH_SAFE(owp, &clp->nfsc_owner, nfsow_list, nowp) { LIST_FOREACH(op, &owp->nfsow_open, nfso_list) { @@ -1816,7 +1822,7 @@ nfscl_cleanupkext(struct nfsclclient *clp, struct nfsc } } NFSUNLOCKCLSTATE(); - NFSPROCLISTUNLOCK(); + pidhash_sunlockall(); } /* Modified: head/sys/kern/kern_proc.c ============================================================================== --- head/sys/kern/kern_proc.c Sun Apr 14 18:04:53 2019 (r346216) +++ head/sys/kern/kern_proc.c Mon Apr 15 01:27:15 2019 (r346217) @@ -193,7 +193,7 @@ procinit(void) pidhashtbl_lock = malloc(sizeof(*pidhashtbl_lock) * (pidhashlock + 1), M_PROC, M_WAITOK | M_ZERO); for (i = 0; i < pidhashlock + 1; i++) - sx_init(&pidhashtbl_lock[i], "pidhash"); + sx_init_flags(&pidhashtbl_lock[i], "pidhash", SX_DUPOK); pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); proc_zone = uma_zcreate("PROC", sched_sizeof_proc(), proc_ctor, proc_dtor, proc_init, proc_fini, @@ -365,6 +365,52 @@ inferior(struct proc *p) return (0); } return (1); +} + +/* + * Shared lock all the pid hash lists. + */ +void +pidhash_slockall(void) +{ + u_long i; + + for (i = 0; i < pidhashlock + 1; i++) + sx_slock(&pidhashtbl_lock[i]); +} + +/* + * Shared unlock all the pid hash lists. + */ +void +pidhash_sunlockall(void) +{ + u_long i; + + for (i = 0; i < pidhashlock + 1; i++) + sx_sunlock(&pidhashtbl_lock[i]); +} + +/* + * Similar to pfind_any(), this function finds zombies. + */ +struct proc * +pfind_any_locked(pid_t pid) +{ + struct proc *p; + + sx_assert(PIDHASHLOCK(pid), SX_LOCKED); + LIST_FOREACH(p, PIDHASH(pid), p_hash) { + if (p->p_pid == pid) { + PROC_LOCK(p); + if (p->p_state == PRS_NEW) { + PROC_UNLOCK(p); + p = NULL; + } + break; + } + } + return (p); } /* Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Sun Apr 14 18:04:53 2019 (r346216) +++ head/sys/sys/proc.h Mon Apr 15 01:27:15 2019 (r346217) @@ -989,8 +989,11 @@ extern struct uma_zone *proc_zone; struct proc *pfind(pid_t); /* Find process by id. */ struct proc *pfind_any(pid_t); /* Find (zombie) process by id. */ +struct proc *pfind_any_locked(pid_t pid); /* Find process by id, locked. */ struct pgrp *pgfind(pid_t); /* Find process group by id. */ struct proc *zpfind(pid_t); /* Find zombie process by id. */ +void pidhash_slockall(void); /* Shared lock all pid hash lists. */ +void pidhash_sunlockall(void); /* Shared unlock all pid hash lists. */ struct fork_req { int fr_flags;