From nobody Thu Jul 14 13:50:27 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4LkG8g6ttlz1J4RN; Thu, 14 Jul 2022 13:50:27 +0000 (UTC) (envelope-from git@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) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4LkG8g3sY4z3yFh; Thu, 14 Jul 2022 13:50:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657806627; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wyW2bnskJ1NrOOfHW6WkZey9AwJAzzowVDGUpCiw+/4=; b=l5DLU29rNlT2g4qQ0sdg3GVP4V4+BTtoadj5Dx1OThFJzVR6sBhOcf2iBh4c56GI4idnAH jXC5nShfNNHH0Krpa99EQS6L0J7kQWeVIrZz1tMHbZeWOU6r7MDsvT7//08Qhed6DDH8Ec AKy56cQ1IwL5yg7xWFYR+7tnJKxXcc9DsFidKbunYovx23tmH8bDtvlHXPFkly17hEAf3A cBJowaNHI1gKTlFH002nuAEHGjsDOoLkE8kIfFIYoojnJv5x3EAkyputhno8aBCSfsW0PG bSpfpdg93M/4rRG//AnOSO2YK7jcaCaMgafuaqm2PsUWgikAciZQ3QwJNMh7sw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4LkG8g2zJLz14RP; Thu, 14 Jul 2022 13:50:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 26EDoR1P067869; Thu, 14 Jul 2022 13:50:27 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 26EDoRA4067868; Thu, 14 Jul 2022 13:50:27 GMT (envelope-from git) Date: Thu, 14 Jul 2022 13:50:27 GMT Message-Id: <202207141350.26EDoRA4067868@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: a70c03b2d383 - stable/13 - pipe: Use a distinct wait channel for I/O serialization List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: a70c03b2d383011dece503716faf504598d5fe29 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1657806627; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wyW2bnskJ1NrOOfHW6WkZey9AwJAzzowVDGUpCiw+/4=; b=ZtJTHHU0/OODpHytJ6R4DZLmzcaVWD9WWvUNQIE1kLVi4o4bE7aPZ+4YA2nriOx7iwHkaU NKVskmCdhjydS916xLmxtf13cO9RZtc+YHMnA0jp6bXUOyhKnS8AKTNNKaKE2rzyyODCuR G2VI6FaOIFOrCFv34RO8iKm/FsPFmf6ArVaAsmmU+7plfSmbLd5BHL7U2CUBs2JWQ7SKBW u4QSXzsBtz+yMmt4JjmcfGn35HRSHsNIhZs/rsStCOcZNg4rB0SmcRf80duLmDLzjvkxWa s4TuMJtj/hKzTHnr2f0VArKTxjng9U5Bx2EZtjhddaRhRfVoOVvSYsZd3agf6w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1657806627; a=rsa-sha256; cv=none; b=dHTgGdfLY3N9iGAMDr9IErxczAq6n8gpBxi3ghTTLXYalWifwd4GZSNP37qkJLgkf74bR2 lwp9G8SasASapvih5DK6ReFkRYzFAUfmV6QQ9opAX7DF6AV3j1pxVGXATSC3qlePheci5g qwY4WhFvrKm8WqMfo08K+Fd+Ghn1u1seJUsHgafkdE2cqE0AeXWMEo/lNwn7ZFtOa1pmm/ uAcuPiarf8t5g/BI4AqD54hiqWsn59o2Lil6FNWjcj7Z0oR5QUyjPQaJr0mJ4ICCEcsY9h yd2w2UYwiF4ZMMwJemNWdEoVPW7YB5NHBZD00i4oVf7dU22amM0bweS6MRJ5Dg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=a70c03b2d383011dece503716faf504598d5fe29 commit a70c03b2d383011dece503716faf504598d5fe29 Author: Mark Johnston AuthorDate: 2022-06-14 14:52:03 +0000 Commit: Mark Johnston CommitDate: 2022-07-14 13:50:10 +0000 pipe: Use a distinct wait channel for I/O serialization Suppose a thread tries to read from an empty pipe. pipe_read() does the following: 1. pipelock(), possibly sleeping 2. check for buffered data 3. pipeunlock() 4. set PIPE_WANTR and sleep 5. goto 1 pipelock() is an open-coded mutex; if a thread blocks in pipelock(), it sleeps until the lock holder calls pipeunlock(). Both sleeps use the same wait channel. So if there are multiple threads in pipe_read(), a thread T1 in step 3 can wake up a thread T2 sleeping in step 4. Then T1 goes to sleep in step 4, and T2 acquires and releases the pipelock, waking up T1 again. This can go on indefinitely, livelocking the process (and potentially starving a would-be writer). Fix the problem by using a separate wait channel for pipelock(). Reported by: Paul Floyd Reviewed by: mjg, kib PR: 264441 Sponsored by: The FreeBSD Foundation (cherry picked from commit e8955bd643ee852d70a0b065f2a0d1bb3fa99df2) --- sys/kern/sys_pipe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 0e19bf8ae7b4..ad166ee992e9 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -627,8 +627,8 @@ pipelock(struct pipe *cpipe, int catch) ("%s: bad waiter count %d", __func__, cpipe->pipe_waiters)); cpipe->pipe_waiters++; - error = msleep(cpipe, PIPE_MTX(cpipe), - prio, "pipelk", 0); + error = msleep(&cpipe->pipe_waiters, PIPE_MTX(cpipe), prio, + "pipelk", 0); cpipe->pipe_waiters--; if (error != 0) return (error); @@ -651,9 +651,8 @@ pipeunlock(struct pipe *cpipe) ("%s: bad waiter count %d", __func__, cpipe->pipe_waiters)); cpipe->pipe_state &= ~PIPE_LOCKFL; - if (cpipe->pipe_waiters > 0) { - wakeup_one(cpipe); - } + if (cpipe->pipe_waiters > 0) + wakeup_one(&cpipe->pipe_waiters); } void