From wanghai38 at huawei.com  Fri Sep  4 09:08:37 2020
From: wanghai38 at huawei.com (Wang Hai)
Date: Fri, 4 Sep 2020 21:08:37 +0800
Subject: [PATCH net-next] rxrpc: Remove unused macro rxrpc_min_rtt_wlen
Message-ID: <20200904130837.20875-1-wanghai38@huawei.com>

rxrpc_min_rtt_wlen is never used after it was introduced.
So better to remove it.

Reported-by: Hulk Robot <hulkci at huawei.com>
Signed-off-by: Wang Hai <wanghai38 at huawei.com>
---
 net/rxrpc/rtt.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/rxrpc/rtt.c b/net/rxrpc/rtt.c
index 928d8b34a3ee..a056c9bcf1d6 100644
--- a/net/rxrpc/rtt.c
+++ b/net/rxrpc/rtt.c
@@ -14,7 +14,6 @@
 #define RXRPC_RTO_MAX	((unsigned)(120 * HZ))
 #define RXRPC_TIMEOUT_INIT ((unsigned)(1*HZ))	/* RFC6298 2.1 initial RTO value	*/
 #define rxrpc_jiffies32 ((u32)jiffies)		/* As rxrpc_jiffies32 */
-#define rxrpc_min_rtt_wlen 300			/* As sysctl_tcp_min_rtt_wlen */
 
 static u32 rxrpc_rto_min_us(struct rxrpc_peer *peer)
 {
-- 
2.17.1



From sashal at kernel.org  Mon Sep  7 12:31:31 2020
From: sashal at kernel.org (Sasha Levin)
Date: Mon,  7 Sep 2020 12:31:31 -0400
Subject: [PATCH AUTOSEL 5.8 05/53] rxrpc: Keep the ACK serial in a var in
 rxrpc_input_ack()
In-Reply-To: <20200907163220.1280412-1-sashal@kernel.org>
References: <20200907163220.1280412-1-sashal@kernel.org>
Message-ID: <20200907163220.1280412-5-sashal@kernel.org>

From: David Howells <dhowells at redhat.com>

[ Upstream commit 68528d937dcd675e79973061c1a314db598162d1 ]

Keep the ACK serial number in a variable in rxrpc_input_ack() as it's used
frequently.

Signed-off-by: David Howells <dhowells at redhat.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 net/rxrpc/input.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 767579328a069..a7699e56eac88 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -843,7 +843,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 		struct rxrpc_ackinfo info;
 		u8 acks[RXRPC_MAXACKS];
 	} buf;
-	rxrpc_serial_t acked_serial;
+	rxrpc_serial_t ack_serial, acked_serial;
 	rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;
 	int nr_acks, offset, ioffset;
 
@@ -856,6 +856,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 	}
 	offset += sizeof(buf.ack);
 
+	ack_serial = sp->hdr.serial;
 	acked_serial = ntohl(buf.ack.serial);
 	first_soft_ack = ntohl(buf.ack.firstPacket);
 	prev_pkt = ntohl(buf.ack.previousPacket);
@@ -864,31 +865,31 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 	summary.ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?
 			      buf.ack.reason : RXRPC_ACK__INVALID);
 
-	trace_rxrpc_rx_ack(call, sp->hdr.serial, acked_serial,
+	trace_rxrpc_rx_ack(call, ack_serial, acked_serial,
 			   first_soft_ack, prev_pkt,
 			   summary.ack_reason, nr_acks);
 
 	if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
 		rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
-					  sp->hdr.serial);
+					  ack_serial);
 	if (buf.ack.reason == RXRPC_ACK_REQUESTED)
 		rxrpc_input_requested_ack(call, skb->tstamp, acked_serial,
-					  sp->hdr.serial);
+					  ack_serial);
 
 	if (buf.ack.reason == RXRPC_ACK_PING) {
-		_proto("Rx ACK %%%u PING Request", sp->hdr.serial);
+		_proto("Rx ACK %%%u PING Request", ack_serial);
 		rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
-				  sp->hdr.serial, true, true,
+				  ack_serial, true, true,
 				  rxrpc_propose_ack_respond_to_ping);
 	} else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
 		rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
-				  sp->hdr.serial, true, true,
+				  ack_serial, true, true,
 				  rxrpc_propose_ack_respond_to_ack);
 	}
 
 	/* Discard any out-of-order or duplicate ACKs (outside lock). */
 	if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
-		trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial,
+		trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
 					   first_soft_ack, call->ackr_first_seq,
 					   prev_pkt, call->ackr_prev_seq);
 		return;
@@ -904,7 +905,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 
 	/* Discard any out-of-order or duplicate ACKs (inside lock). */
 	if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
-		trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial,
+		trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
 					   first_soft_ack, call->ackr_first_seq,
 					   prev_pkt, call->ackr_prev_seq);
 		goto out;
@@ -964,7 +965,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 	    RXRPC_TX_ANNO_LAST &&
 	    summary.nr_acks == call->tx_top - hard_ack &&
 	    rxrpc_is_client_call(call))
-		rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
+		rxrpc_propose_ACK(call, RXRPC_ACK_PING, ack_serial,
 				  false, true,
 				  rxrpc_propose_ack_ping_for_lost_reply);
 
-- 
2.25.1



From sashal at kernel.org  Mon Sep  7 12:32:50 2020
From: sashal at kernel.org (Sasha Levin)
Date: Mon,  7 Sep 2020 12:32:50 -0400
Subject: [PATCH AUTOSEL 5.4 04/43] rxrpc: Keep the ACK serial in a var in
 rxrpc_input_ack()
In-Reply-To: <20200907163329.1280888-1-sashal@kernel.org>
References: <20200907163329.1280888-1-sashal@kernel.org>
Message-ID: <20200907163329.1280888-4-sashal@kernel.org>

From: David Howells <dhowells at redhat.com>

[ Upstream commit 68528d937dcd675e79973061c1a314db598162d1 ]

Keep the ACK serial number in a variable in rxrpc_input_ack() as it's used
frequently.

Signed-off-by: David Howells <dhowells at redhat.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 net/rxrpc/input.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 22dec6049e1bb..6cace43b217ee 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -844,7 +844,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 		struct rxrpc_ackinfo info;
 		u8 acks[RXRPC_MAXACKS];
 	} buf;
-	rxrpc_serial_t acked_serial;
+	rxrpc_serial_t ack_serial, acked_serial;
 	rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;
 	int nr_acks, offset, ioffset;
 
@@ -857,6 +857,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 	}
 	offset += sizeof(buf.ack);
 
+	ack_serial = sp->hdr.serial;
 	acked_serial = ntohl(buf.ack.serial);
 	first_soft_ack = ntohl(buf.ack.firstPacket);
 	prev_pkt = ntohl(buf.ack.previousPacket);
@@ -865,31 +866,31 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 	summary.ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?
 			      buf.ack.reason : RXRPC_ACK__INVALID);
 
-	trace_rxrpc_rx_ack(call, sp->hdr.serial, acked_serial,
+	trace_rxrpc_rx_ack(call, ack_serial, acked_serial,
 			   first_soft_ack, prev_pkt,
 			   summary.ack_reason, nr_acks);
 
 	if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
 		rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
-					  sp->hdr.serial);
+					  ack_serial);
 	if (buf.ack.reason == RXRPC_ACK_REQUESTED)
 		rxrpc_input_requested_ack(call, skb->tstamp, acked_serial,
-					  sp->hdr.serial);
+					  ack_serial);
 
 	if (buf.ack.reason == RXRPC_ACK_PING) {
-		_proto("Rx ACK %%%u PING Request", sp->hdr.serial);
+		_proto("Rx ACK %%%u PING Request", ack_serial);
 		rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
-				  sp->hdr.serial, true, true,
+				  ack_serial, true, true,
 				  rxrpc_propose_ack_respond_to_ping);
 	} else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
 		rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
-				  sp->hdr.serial, true, true,
+				  ack_serial, true, true,
 				  rxrpc_propose_ack_respond_to_ack);
 	}
 
 	/* Discard any out-of-order or duplicate ACKs (outside lock). */
 	if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
-		trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial,
+		trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
 					   first_soft_ack, call->ackr_first_seq,
 					   prev_pkt, call->ackr_prev_seq);
 		return;
@@ -905,7 +906,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 
 	/* Discard any out-of-order or duplicate ACKs (inside lock). */
 	if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
-		trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial,
+		trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
 					   first_soft_ack, call->ackr_first_seq,
 					   prev_pkt, call->ackr_prev_seq);
 		goto out;
@@ -965,7 +966,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 	    RXRPC_TX_ANNO_LAST &&
 	    summary.nr_acks == call->tx_top - hard_ack &&
 	    rxrpc_is_client_call(call))
-		rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
+		rxrpc_propose_ACK(call, RXRPC_ACK_PING, ack_serial,
 				  false, true,
 				  rxrpc_propose_ack_ping_for_lost_reply);
 
-- 
2.25.1



From kuba at kernel.org  Mon Sep  7 18:04:35 2020
From: kuba at kernel.org (Jakub Kicinski)
Date: Mon, 7 Sep 2020 15:04:35 -0700
Subject: [PATCH net-next] rxrpc: Remove unused macro rxrpc_min_rtt_wlen
In-Reply-To: <20200904130837.20875-1-wanghai38@huawei.com>
References: <20200904130837.20875-1-wanghai38@huawei.com>
Message-ID: <20200907150435.29dcd69f@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com>

On Fri, 4 Sep 2020 21:08:37 +0800 Wang Hai wrote:
> rxrpc_min_rtt_wlen is never used after it was introduced.
> So better to remove it.
> 
> Reported-by: Hulk Robot <hulkci at huawei.com>
> Signed-off-by: Wang Hai <wanghai38 at huawei.com>

Applied.


From dhowells at redhat.com  Tue Sep  8 16:50:51 2020
From: dhowells at redhat.com (David Howells)
Date: Tue, 08 Sep 2020 21:50:51 +0100
Subject: [PATCH net-next 0/3] rxrpc: Allow more calls to same peer
Message-ID: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>


Here are some development patches for AF_RXRPC that allow more simultaneous
calls to be made to the same peer with the same security parameters.  The
current code allows a maximum of 4 simultaneous calls, which limits the afs
filesystem to that many simultaneous threads.  This increases the limit to
16.

To make this work, the way client connections are limited has to be changed
(incoming call/connection limits are unaffected) as the current code
depends on queuing calls on a connection and then pushing the connection
through a queue.  The limit is on the number of available connections.

This is changed such that there's a limit[*] on the total number of calls
systemwide across all namespaces, but the limit on the number of client
connections is removed.

Once a call is allowed to proceed, it finds a bundle of connections and
tries to grab a call slot.  If there's a spare call slot, fine, otherwise
it will wait.  If there's already a waiter, it will try to create another
connection in the bundle, unless the limit of 4 is reached (4 calls per
connection, giving 16).

A number of things throttle someone trying to set up endless connections:

 - Calls that fail immediately have their conns deleted immediately,

 - Calls that don't fail immediately have to wait for a timeout,

 - Connections normally get automatically reaped if they haven't been used
   for 2m, but this is sped up to 2s if the number of connections rises
   over 900.  This number is tunable by sysctl.


[*] Technically two limits - kernel sockets and userspace rxrpc sockets are
    accounted separately.

The patches are tagged here:

	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
	rxrpc-next-20200908

and can also be found on this branch:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-next

David
---
David Howells (3):
      rxrpc: Impose a maximum number of client calls
      rxrpc: Rewrite the client connection manager
      rxrpc: Allow multiple client connections to the same peer


 include/trace/events/rxrpc.h |   33 +-
 net/rxrpc/ar-internal.h      |   68 +--
 net/rxrpc/conn_client.c      | 1087 +++++++++++++++-------------------
 net/rxrpc/conn_event.c       |   14 +-
 net/rxrpc/conn_object.c      |   12 +-
 net/rxrpc/conn_service.c     |    7 +
 net/rxrpc/local_object.c     |    4 +-
 net/rxrpc/net_ns.c           |    5 +-
 net/rxrpc/output.c           |    6 +
 net/rxrpc/proc.c             |    2 +-
 net/rxrpc/rxkad.c            |    8 +-
 net/rxrpc/sysctl.c           |   10 +-
 12 files changed, 565 insertions(+), 691 deletions(-)




From dhowells at redhat.com  Tue Sep  8 16:50:58 2020
From: dhowells at redhat.com (David Howells)
Date: Tue, 08 Sep 2020 21:50:58 +0100
Subject: [PATCH net-next 1/3] rxrpc: Impose a maximum number of client calls
In-Reply-To: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
References: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
Message-ID: <159959825801.645007.1776603172846633618.stgit@warthog.procyon.org.uk>

Impose a maximum on the number of client rxrpc calls that are allowed
simultaneously.  This will be in lieu of a maximum number of client
connections as this is easier to administed as, unlike connections, calls
aren't reusable (to be changed in a subsequent patch)..

This doesn't affect the limits on service calls and connections.

Signed-off-by: David Howells <dhowells at redhat.com>
---

 net/rxrpc/af_rxrpc.c    |    7 ++++---
 net/rxrpc/ar-internal.h |    2 ++
 net/rxrpc/call_object.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 186c8a889b16..0a2f4817ec6c 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -308,9 +308,10 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
 		key = NULL; /* a no-security key */
 
 	memset(&p, 0, sizeof(p));
-	p.user_call_ID = user_call_ID;
-	p.tx_total_len = tx_total_len;
-	p.interruptibility = interruptibility;
+	p.user_call_ID		= user_call_ID;
+	p.tx_total_len		= tx_total_len;
+	p.interruptibility	= interruptibility;
+	p.kernel		= true;
 
 	memset(&cp, 0, sizeof(cp));
 	cp.local		= rx->local;
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 884cff7bb169..de84198b3285 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -493,6 +493,7 @@ enum rxrpc_call_flag {
 	RXRPC_CALL_RX_HEARD,		/* The peer responded at least once to this call */
 	RXRPC_CALL_RX_UNDERRUN,		/* Got data underrun */
 	RXRPC_CALL_DISCONNECTED,	/* The call has been disconnected */
+	RXRPC_CALL_KERNEL,		/* The call was made by the kernel */
 };
 
 /*
@@ -727,6 +728,7 @@ struct rxrpc_call_params {
 		u32		normal;		/* Max time since last call packet (msec) */
 	} timeouts;
 	u8			nr_timeouts;	/* Number of timeouts specified */
+	bool			kernel;		/* T if kernel is making the call */
 	enum rxrpc_interruptibility interruptibility; /* How is interruptible is the call? */
 };
 
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index a40fae013942..c8015c76a81c 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -41,6 +41,11 @@ const char *const rxrpc_call_completions[NR__RXRPC_CALL_COMPLETIONS] = {
 
 struct kmem_cache *rxrpc_call_jar;
 
+static struct semaphore rxrpc_call_limiter =
+	__SEMAPHORE_INITIALIZER(rxrpc_call_limiter, 1000);
+static struct semaphore rxrpc_kernel_call_limiter =
+	__SEMAPHORE_INITIALIZER(rxrpc_kernel_call_limiter, 1000);
+
 static void rxrpc_call_timer_expired(struct timer_list *t)
 {
 	struct rxrpc_call *call = from_timer(call, t, timer);
@@ -209,6 +214,34 @@ static void rxrpc_start_call_timer(struct rxrpc_call *call)
 	call->timer.expires = now;
 }
 
+/*
+ * Wait for a call slot to become available.
+ */
+static struct semaphore *rxrpc_get_call_slot(struct rxrpc_call_params *p, gfp_t gfp)
+{
+	struct semaphore *limiter = &rxrpc_call_limiter;
+
+	if (p->kernel)
+		limiter = &rxrpc_kernel_call_limiter;
+	if (p->interruptibility == RXRPC_UNINTERRUPTIBLE) {
+		down(limiter);
+		return limiter;
+	}
+	return down_interruptible(limiter) < 0 ? NULL : limiter;
+}
+
+/*
+ * Release a call slot.
+ */
+static void rxrpc_put_call_slot(struct rxrpc_call *call)
+{
+	struct semaphore *limiter = &rxrpc_call_limiter;
+
+	if (test_bit(RXRPC_CALL_KERNEL, &call->flags))
+		limiter = &rxrpc_kernel_call_limiter;
+	up(limiter);
+}
+
 /*
  * Set up a call for the given parameters.
  * - Called with the socket lock held, which it must release.
@@ -225,15 +258,21 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
 {
 	struct rxrpc_call *call, *xcall;
 	struct rxrpc_net *rxnet;
+	struct semaphore *limiter;
 	struct rb_node *parent, **pp;
 	const void *here = __builtin_return_address(0);
 	int ret;
 
 	_enter("%p,%lx", rx, p->user_call_ID);
 
+	limiter = rxrpc_get_call_slot(p, gfp);
+	if (!limiter)
+		return ERR_PTR(-ERESTARTSYS);
+
 	call = rxrpc_alloc_client_call(rx, srx, gfp, debug_id);
 	if (IS_ERR(call)) {
 		release_sock(&rx->sk);
+		up(limiter);
 		_leave(" = %ld", PTR_ERR(call));
 		return call;
 	}
@@ -243,6 +282,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
 	trace_rxrpc_call(call->debug_id, rxrpc_call_new_client,
 			 atomic_read(&call->usage),
 			 here, (const void *)p->user_call_ID);
+	if (p->kernel)
+		__set_bit(RXRPC_CALL_KERNEL, &call->flags);
 
 	/* We need to protect a partially set up call against the user as we
 	 * will be acting outside the socket lock.
@@ -471,6 +512,8 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
 		BUG();
 	spin_unlock_bh(&call->lock);
 
+	rxrpc_put_call_slot(call);
+
 	del_timer_sync(&call->timer);
 
 	/* Make sure we don't get any more notifications */




From dhowells at redhat.com  Tue Sep  8 16:51:12 2020
From: dhowells at redhat.com (David Howells)
Date: Tue, 08 Sep 2020 21:51:12 +0100
Subject: [PATCH net-next 3/3] rxrpc: Allow multiple client connections to the
 same peer
In-Reply-To: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
References: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
Message-ID: <159959827240.645007.5925464824704611056.stgit@warthog.procyon.org.uk>

Allow the number of parallel connections to a machine to be expanded from a
single connection to a maximum of four.  This allows up to 16 calls to be
in progress at the same time to any particular peer instead of 4.

Signed-off-by: David Howells <dhowells at redhat.com>
---

 net/rxrpc/conn_client.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 8b41c87b3333..0e4e1879c24d 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -486,6 +486,12 @@ static void rxrpc_maybe_add_conn(struct rxrpc_bundle *bundle, gfp_t gfp)
 	if (!usable)
 		goto alloc_conn;
 
+	if (!bundle->avail_chans &&
+	    !bundle->try_upgrade &&
+	    !list_empty(&bundle->waiting_calls) &&
+	    usable < ARRAY_SIZE(bundle->conns))
+		goto alloc_conn;
+
 	spin_unlock(&bundle->channel_lock);
 	_leave("");
 	return;




From dhowells at redhat.com  Tue Sep  8 16:51:05 2020
From: dhowells at redhat.com (David Howells)
Date: Tue, 08 Sep 2020 21:51:05 +0100
Subject: [PATCH net-next 2/3] rxrpc: Rewrite the client connection manager
In-Reply-To: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
References: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
Message-ID: <159959826498.645007.18091528505219148523.stgit@warthog.procyon.org.uk>

Rewrite the rxrpc client connection manager so that it can support multiple
connections for a given security key to a peer.  The following changes are
made:

 (1) For each open socket, the code currently maintains an rbtree with the
     connections placed into it, keyed by communications parameters.  This
     is tricky to maintain as connections can be culled from the tree or
     replaced within it.  Connections can require replacement for a number
     of reasons, e.g. their IDs span too great a range for the IDR data
     type to represent efficiently, the call ID numbers on that conn would
     overflow or the conn got aborted.

     This is changed so that there's now a connection bundle object placed
     in the tree, keyed on the same parameters.  The bundle, however, does
     not need to be replaced.

 (2) An rxrpc_bundle object can now manage the available channels for a set
     of parallel connections.  The lock that manages this is moved there
     from the rxrpc_connection struct (channel_lock).

 (3) There'a a dummy bundle for all incoming connections to share so that
     they have a channel_lock too.  It might be better to give each
     incoming connection its own bundle.  This bundle is not needed to
     manage which channels incoming calls are made on because that's the
     solely at whim of the client.

 (4) The restrictions on how many client connections are around are
     removed.  Instead, a previous patch limits the number of client calls
     that can be allocated.  Ordinarily, client connections are reaped
     after 2 minutes on the idle queue, but when more than a certain number
     of connections are in existence, the reaper starts reaping them after
     2s of idleness instead to get the numbers back down.

     It could also be made such that new call allocations are forced to
     wait until the number of outstanding connections subsides.

Signed-off-by: David Howells <dhowells at redhat.com>
---

 include/trace/events/rxrpc.h |   33 -
 net/rxrpc/ar-internal.h      |   68 +--
 net/rxrpc/conn_client.c      | 1081 +++++++++++++++++++-----------------------
 net/rxrpc/conn_event.c       |   14 -
 net/rxrpc/conn_object.c      |   12 
 net/rxrpc/conn_service.c     |    7 
 net/rxrpc/local_object.c     |    4 
 net/rxrpc/net_ns.c           |    5 
 net/rxrpc/output.c           |    6 
 net/rxrpc/proc.c             |    2 
 net/rxrpc/rxkad.c            |    8 
 net/rxrpc/sysctl.c           |   10 
 12 files changed, 559 insertions(+), 691 deletions(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index c33079b986e8..3b67d5981224 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -68,21 +68,14 @@ enum rxrpc_client_trace {
 	rxrpc_client_chan_activate,
 	rxrpc_client_chan_disconnect,
 	rxrpc_client_chan_pass,
-	rxrpc_client_chan_unstarted,
 	rxrpc_client_chan_wait_failed,
 	rxrpc_client_cleanup,
-	rxrpc_client_count,
 	rxrpc_client_discard,
 	rxrpc_client_duplicate,
 	rxrpc_client_exposed,
 	rxrpc_client_replace,
 	rxrpc_client_to_active,
-	rxrpc_client_to_culled,
 	rxrpc_client_to_idle,
-	rxrpc_client_to_inactive,
-	rxrpc_client_to_upgrade,
-	rxrpc_client_to_waiting,
-	rxrpc_client_uncount,
 };
 
 enum rxrpc_call_trace {
@@ -271,29 +264,14 @@ enum rxrpc_tx_point {
 	EM(rxrpc_client_chan_activate,		"ChActv") \
 	EM(rxrpc_client_chan_disconnect,	"ChDisc") \
 	EM(rxrpc_client_chan_pass,		"ChPass") \
-	EM(rxrpc_client_chan_unstarted,		"ChUnst") \
 	EM(rxrpc_client_chan_wait_failed,	"ChWtFl") \
 	EM(rxrpc_client_cleanup,		"Clean ") \
-	EM(rxrpc_client_count,			"Count ") \
 	EM(rxrpc_client_discard,		"Discar") \
 	EM(rxrpc_client_duplicate,		"Duplic") \
 	EM(rxrpc_client_exposed,		"Expose") \
 	EM(rxrpc_client_replace,		"Replac") \
 	EM(rxrpc_client_to_active,		"->Actv") \
-	EM(rxrpc_client_to_culled,		"->Cull") \
-	EM(rxrpc_client_to_idle,		"->Idle") \
-	EM(rxrpc_client_to_inactive,		"->Inac") \
-	EM(rxrpc_client_to_upgrade,		"->Upgd") \
-	EM(rxrpc_client_to_waiting,		"->Wait") \
-	E_(rxrpc_client_uncount,		"Uncoun")
-
-#define rxrpc_conn_cache_states \
-	EM(RXRPC_CONN_CLIENT_INACTIVE,		"Inac") \
-	EM(RXRPC_CONN_CLIENT_WAITING,		"Wait") \
-	EM(RXRPC_CONN_CLIENT_ACTIVE,		"Actv") \
-	EM(RXRPC_CONN_CLIENT_UPGRADE,		"Upgd") \
-	EM(RXRPC_CONN_CLIENT_CULLED,		"Cull") \
-	E_(RXRPC_CONN_CLIENT_IDLE,		"Idle") \
+	E_(rxrpc_client_to_idle,		"->Idle")
 
 #define rxrpc_call_traces \
 	EM(rxrpc_call_connected,		"CON") \
@@ -594,23 +572,20 @@ TRACE_EVENT(rxrpc_client,
 		    __field(int,			channel		)
 		    __field(int,			usage		)
 		    __field(enum rxrpc_client_trace,	op		)
-		    __field(enum rxrpc_conn_cache_state, cs		)
 			     ),
 
 	    TP_fast_assign(
-		    __entry->conn = conn->debug_id;
+		    __entry->conn = conn ? conn->debug_id : 0;
 		    __entry->channel = channel;
-		    __entry->usage = atomic_read(&conn->usage);
+		    __entry->usage = conn ? atomic_read(&conn->usage) : -2;
 		    __entry->op = op;
 		    __entry->cid = conn->proto.cid;
-		    __entry->cs = conn->cache_state;
 			   ),
 
-	    TP_printk("C=%08x h=%2d %s %s i=%08x u=%d",
+	    TP_printk("C=%08x h=%2d %s i=%08x u=%d",
 		      __entry->conn,
 		      __entry->channel,
 		      __print_symbolic(__entry->op, rxrpc_client_traces),
-		      __print_symbolic(__entry->cs, rxrpc_conn_cache_states),
 		      __entry->cid,
 		      __entry->usage)
 	    );
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index de84198b3285..cd5a80b34738 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -76,14 +76,12 @@ struct rxrpc_net {
 	struct work_struct	service_conn_reaper;
 	struct timer_list	service_conn_reap_timer;
 
-	unsigned int		nr_client_conns;
-	unsigned int		nr_active_client_conns;
-	bool			kill_all_client_conns;
 	bool			live;
+
+	bool			kill_all_client_conns;
+	atomic_t		nr_client_conns;
 	spinlock_t		client_conn_cache_lock; /* Lock for ->*_client_conns */
 	spinlock_t		client_conn_discard_lock; /* Prevent multiple discarders */
-	struct list_head	waiting_client_conns;
-	struct list_head	active_client_conns;
 	struct list_head	idle_client_conns;
 	struct work_struct	client_conn_reaper;
 	struct timer_list	client_conn_reap_timer;
@@ -275,8 +273,8 @@ struct rxrpc_local {
 	struct rw_semaphore	defrag_sem;	/* control re-enablement of IP DF bit */
 	struct sk_buff_head	reject_queue;	/* packets awaiting rejection */
 	struct sk_buff_head	event_queue;	/* endpoint event packets awaiting processing */
-	struct rb_root		client_conns;	/* Client connections by socket params */
-	spinlock_t		client_conns_lock; /* Lock for client_conns */
+	struct rb_root		client_bundles;	/* Client connection bundles by socket params */
+	spinlock_t		client_bundles_lock; /* Lock for client_bundles */
 	spinlock_t		lock;		/* access lock */
 	rwlock_t		services_lock;	/* lock for services list */
 	int			debug_id;	/* debug ID for printks */
@@ -353,10 +351,7 @@ struct rxrpc_conn_parameters {
 enum rxrpc_conn_flag {
 	RXRPC_CONN_HAS_IDR,		/* Has a client conn ID assigned */
 	RXRPC_CONN_IN_SERVICE_CONNS,	/* Conn is in peer->service_conns */
-	RXRPC_CONN_IN_CLIENT_CONNS,	/* Conn is in local->client_conns */
-	RXRPC_CONN_EXPOSED,		/* Conn has extra ref for exposure */
 	RXRPC_CONN_DONT_REUSE,		/* Don't reuse this connection */
-	RXRPC_CONN_COUNTED,		/* Counted by rxrpc_nr_client_conns */
 	RXRPC_CONN_PROBING_FOR_UPGRADE,	/* Probing for service upgrade */
 	RXRPC_CONN_FINAL_ACK_0,		/* Need final ACK for channel 0 */
 	RXRPC_CONN_FINAL_ACK_1,		/* Need final ACK for channel 1 */
@@ -376,19 +371,6 @@ enum rxrpc_conn_event {
 	RXRPC_CONN_EV_CHALLENGE,	/* Send challenge packet */
 };
 
-/*
- * The connection cache state.
- */
-enum rxrpc_conn_cache_state {
-	RXRPC_CONN_CLIENT_INACTIVE,	/* Conn is not yet listed */
-	RXRPC_CONN_CLIENT_WAITING,	/* Conn is on wait list, waiting for capacity */
-	RXRPC_CONN_CLIENT_ACTIVE,	/* Conn is on active list, doing calls */
-	RXRPC_CONN_CLIENT_UPGRADE,	/* Conn is on active list, probing for upgrade */
-	RXRPC_CONN_CLIENT_CULLED,	/* Conn is culled and delisted, doing calls */
-	RXRPC_CONN_CLIENT_IDLE,		/* Conn is on idle list, doing mostly nothing */
-	RXRPC_CONN__NR_CACHE_STATES
-};
-
 /*
  * The connection protocol state.
  */
@@ -404,6 +386,23 @@ enum rxrpc_conn_proto_state {
 	RXRPC_CONN__NR_STATES
 };
 
+/*
+ * RxRPC client connection bundle.
+ */
+struct rxrpc_bundle {
+	struct rxrpc_conn_parameters params;
+	atomic_t		usage;
+	unsigned int		debug_id;
+	bool			try_upgrade;	/* True if the bundle is attempting upgrade */
+	bool			alloc_conn;	/* True if someone's getting a conn */
+	unsigned short		alloc_error;	/* Error from last conn allocation */
+	spinlock_t		channel_lock;
+	struct rb_node		local_node;	/* Node in local->client_conns */
+	struct list_head	waiting_calls;	/* Calls waiting for channels */
+	unsigned long		avail_chans;	/* Mask of available channels */
+	struct rxrpc_connection	*conns[4];	/* The connections in the bundle (max 4) */
+};
+
 /*
  * RxRPC connection definition
  * - matched by { local, peer, epoch, conn_id, direction }
@@ -417,10 +416,7 @@ struct rxrpc_connection {
 	struct rcu_head		rcu;
 	struct list_head	cache_link;
 
-	spinlock_t		channel_lock;
-	unsigned char		active_chans;	/* Mask of active channels */
-#define RXRPC_ACTIVE_CHANS_MASK	((1 << RXRPC_MAXCALLS) - 1)
-	struct list_head	waiting_calls;	/* Calls waiting for channels */
+	unsigned char		act_chans;	/* Mask of active channels */
 	struct rxrpc_channel {
 		unsigned long		final_ack_at;	/* Time at which to issue final ACK */
 		struct rxrpc_call __rcu	*call;		/* Active call */
@@ -437,10 +433,8 @@ struct rxrpc_connection {
 
 	struct timer_list	timer;		/* Conn event timer */
 	struct work_struct	processor;	/* connection event processor */
-	union {
-		struct rb_node	client_node;	/* Node in local->client_conns */
-		struct rb_node	service_node;	/* Node in peer->service_conns */
-	};
+	struct rxrpc_bundle	*bundle;	/* Client connection bundle */
+	struct rb_node		service_node;	/* Node in peer->service_conns */
 	struct list_head	proc_link;	/* link in procfs list */
 	struct list_head	link;		/* link in master connection list */
 	struct sk_buff_head	rx_queue;	/* received conn-level packets */
@@ -452,7 +446,6 @@ struct rxrpc_connection {
 	unsigned long		events;
 	unsigned long		idle_timestamp;	/* Time at which last became idle */
 	spinlock_t		state_lock;	/* state-change lock */
-	enum rxrpc_conn_cache_state cache_state;
 	enum rxrpc_conn_proto_state state;	/* current state of connection */
 	u32			abort_code;	/* Abort code of connection abort */
 	int			debug_id;	/* debug ID for printks */
@@ -464,6 +457,7 @@ struct rxrpc_connection {
 	u8			security_size;	/* security header size */
 	u8			security_ix;	/* security type */
 	u8			out_clientflag;	/* RXRPC_CLIENT_INITIATED if we are client */
+	u8			bundle_shift;	/* Index into bundle->avail_chans */
 	short			error;		/* Local error code */
 };
 
@@ -494,6 +488,7 @@ enum rxrpc_call_flag {
 	RXRPC_CALL_RX_UNDERRUN,		/* Got data underrun */
 	RXRPC_CALL_DISCONNECTED,	/* The call has been disconnected */
 	RXRPC_CALL_KERNEL,		/* The call was made by the kernel */
+	RXRPC_CALL_UPGRADE,		/* Service upgrade was requested for the call */
 };
 
 /*
@@ -578,7 +573,7 @@ struct rxrpc_call {
 	struct work_struct	processor;	/* Event processor */
 	rxrpc_notify_rx_t	notify_rx;	/* kernel service Rx notification function */
 	struct list_head	link;		/* link in master call list */
-	struct list_head	chan_wait_link;	/* Link in conn->waiting_calls */
+	struct list_head	chan_wait_link;	/* Link in conn->bundle->waiting_calls */
 	struct hlist_node	error_link;	/* link in error distribution list */
 	struct list_head	accept_link;	/* Link in rx->acceptq */
 	struct list_head	recvmsg_link;	/* Link in rx->recvmsg_q */
@@ -817,18 +812,19 @@ static inline bool rxrpc_is_client_call(const struct rxrpc_call *call)
 /*
  * conn_client.c
  */
-extern unsigned int rxrpc_max_client_connections;
 extern unsigned int rxrpc_reap_client_connections;
 extern unsigned long rxrpc_conn_idle_client_expiry;
 extern unsigned long rxrpc_conn_idle_client_fast_expiry;
 extern struct idr rxrpc_client_conn_ids;
 
 void rxrpc_destroy_client_conn_ids(void);
+struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *);
+void rxrpc_put_bundle(struct rxrpc_bundle *);
 int rxrpc_connect_call(struct rxrpc_sock *, struct rxrpc_call *,
 		       struct rxrpc_conn_parameters *, struct sockaddr_rxrpc *,
 		       gfp_t);
 void rxrpc_expose_client_call(struct rxrpc_call *);
-void rxrpc_disconnect_client_call(struct rxrpc_call *);
+void rxrpc_disconnect_client_call(struct rxrpc_bundle *, struct rxrpc_call *);
 void rxrpc_put_client_conn(struct rxrpc_connection *);
 void rxrpc_discard_expired_client_conns(struct work_struct *);
 void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
@@ -854,7 +850,7 @@ void rxrpc_disconnect_call(struct rxrpc_call *);
 void rxrpc_kill_connection(struct rxrpc_connection *);
 bool rxrpc_queue_conn(struct rxrpc_connection *);
 void rxrpc_see_connection(struct rxrpc_connection *);
-void rxrpc_get_connection(struct rxrpc_connection *);
+struct rxrpc_connection *rxrpc_get_connection(struct rxrpc_connection *);
 struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *);
 void rxrpc_put_service_conn(struct rxrpc_connection *);
 void rxrpc_service_connection_reaper(struct work_struct *);
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 159e3eda7914..8b41c87b3333 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -1,63 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /* Client connection-specific management code.
  *
- * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2016, 2020 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells at redhat.com)
  *
  * Client connections need to be cached for a little while after they've made a
  * call so as to handle retransmitted DATA packets in case the server didn't
  * receive the final ACK or terminating ABORT we sent it.
  *
- * Client connections can be in one of a number of cache states:
- *
- *  (1) INACTIVE - The connection is not held in any list and may not have been
- *      exposed to the world.  If it has been previously exposed, it was
- *      discarded from the idle list after expiring.
- *
- *  (2) WAITING - The connection is waiting for the number of client conns to
- *      drop below the maximum capacity.  Calls may be in progress upon it from
- *      when it was active and got culled.
- *
- *	The connection is on the rxrpc_waiting_client_conns list which is kept
- *	in to-be-granted order.  Culled conns with waiters go to the back of
- *	the queue just like new conns.
- *
- *  (3) ACTIVE - The connection has at least one call in progress upon it, it
- *      may freely grant available channels to new calls and calls may be
- *      waiting on it for channels to become available.
- *
- *	The connection is on the rxnet->active_client_conns list which is kept
- *	in activation order for culling purposes.
- *
- *	rxrpc_nr_active_client_conns is held incremented also.
- *
- *  (4) UPGRADE - As for ACTIVE, but only one call may be in progress and is
- *      being used to probe for service upgrade.
- *
- *  (5) CULLED - The connection got summarily culled to try and free up
- *      capacity.  Calls currently in progress on the connection are allowed to
- *      continue, but new calls will have to wait.  There can be no waiters in
- *      this state - the conn would have to go to the WAITING state instead.
- *
- *  (6) IDLE - The connection has no calls in progress upon it and must have
- *      been exposed to the world (ie. the EXPOSED flag must be set).  When it
- *      expires, the EXPOSED flag is cleared and the connection transitions to
- *      the INACTIVE state.
- *
- *	The connection is on the rxnet->idle_client_conns list which is kept in
- *	order of how soon they'll expire.
- *
  * There are flags of relevance to the cache:
  *
- *  (1) EXPOSED - The connection ID got exposed to the world.  If this flag is
- *      set, an extra ref is added to the connection preventing it from being
- *      reaped when it has no calls outstanding.  This flag is cleared and the
- *      ref dropped when a conn is discarded from the idle list.
- *
- *      This allows us to move terminal call state retransmission to the
- *      connection and to discard the call immediately we think it is done
- *      with.  It also give us a chance to reuse the connection.
- *
  *  (2) DONT_REUSE - The connection should be discarded as soon as possible and
  *      should not be reused.  This is set when an exclusive connection is used
  *      or a call ID counter overflows.
@@ -78,7 +30,6 @@
 
 #include "ar-internal.h"
 
-__read_mostly unsigned int rxrpc_max_client_connections = 1000;
 __read_mostly unsigned int rxrpc_reap_client_connections = 900;
 __read_mostly unsigned long rxrpc_conn_idle_client_expiry = 2 * 60 * HZ;
 __read_mostly unsigned long rxrpc_conn_idle_client_fast_expiry = 2 * HZ;
@@ -89,8 +40,6 @@ __read_mostly unsigned long rxrpc_conn_idle_client_fast_expiry = 2 * HZ;
 DEFINE_IDR(rxrpc_client_conn_ids);
 static DEFINE_SPINLOCK(rxrpc_conn_id_lock);
 
-static void rxrpc_cull_active_client_conns(struct rxrpc_net *);
-
 /*
  * Get a connection ID and epoch for a client connection from the global pool.
  * The connection struct pointer is then recorded in the idr radix tree.  The
@@ -161,14 +110,51 @@ void rxrpc_destroy_client_conn_ids(void)
 	idr_destroy(&rxrpc_client_conn_ids);
 }
 
+/*
+ * Allocate a connection bundle.
+ */
+static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp,
+					       gfp_t gfp)
+{
+	struct rxrpc_bundle *bundle;
+
+	bundle = kzalloc(sizeof(*bundle), gfp);
+	if (bundle) {
+		bundle->params = *cp;
+		rxrpc_get_peer(bundle->params.peer);
+		atomic_set(&bundle->usage, 1);
+		spin_lock_init(&bundle->channel_lock);
+		INIT_LIST_HEAD(&bundle->waiting_calls);
+	}
+	return bundle;
+}
+
+struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle)
+{
+	atomic_inc(&bundle->usage);
+	return bundle;
+}
+
+void rxrpc_put_bundle(struct rxrpc_bundle *bundle)
+{
+	unsigned int d = bundle->debug_id;
+	unsigned int u = atomic_dec_return(&bundle->usage);
+
+	_debug("PUT B=%x %u", d, u);
+	if (u == 0) {
+		rxrpc_put_peer(bundle->params.peer);
+		kfree(bundle);
+	}
+}
+
 /*
  * Allocate a client connection.
  */
 static struct rxrpc_connection *
-rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
+rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp)
 {
 	struct rxrpc_connection *conn;
-	struct rxrpc_net *rxnet = cp->local->rxnet;
+	struct rxrpc_net *rxnet = bundle->params.local->rxnet;
 	int ret;
 
 	_enter("");
@@ -180,15 +166,11 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
 	}
 
 	atomic_set(&conn->usage, 1);
-	if (cp->exclusive)
-		__set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
-	if (cp->upgrade)
-		__set_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags);
-
-	conn->params		= *cp;
+	conn->bundle		= bundle;
+	conn->params		= bundle->params;
 	conn->out_clientflag	= RXRPC_CLIENT_INITIATED;
 	conn->state		= RXRPC_CONN_CLIENT;
-	conn->service_id	= cp->service_id;
+	conn->service_id	= conn->params.service_id;
 
 	ret = rxrpc_get_client_connection_id(conn, gfp);
 	if (ret < 0)
@@ -207,14 +189,16 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
 	list_add_tail(&conn->proc_link, &rxnet->conn_proc_list);
 	write_unlock(&rxnet->conn_lock);
 
-	/* We steal the caller's peer ref. */
-	cp->peer = NULL;
+	rxrpc_get_bundle(bundle);
+	rxrpc_get_peer(conn->params.peer);
 	rxrpc_get_local(conn->params.local);
 	key_get(conn->params.key);
 
 	trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_client,
 			 atomic_read(&conn->usage),
 			 __builtin_return_address(0));
+
+	atomic_inc(&rxnet->nr_client_conns);
 	trace_rxrpc_client(conn, -1, rxrpc_client_alloc);
 	_leave(" = %p", conn);
 	return conn;
@@ -234,13 +218,18 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
  */
 static bool rxrpc_may_reuse_conn(struct rxrpc_connection *conn)
 {
-	struct rxrpc_net *rxnet = conn->params.local->rxnet;
+	struct rxrpc_net *rxnet;
 	int id_cursor, id, distance, limit;
 
+	if (!conn)
+		goto dont_reuse;
+
+	rxnet = conn->params.local->rxnet;
 	if (test_bit(RXRPC_CONN_DONT_REUSE, &conn->flags))
 		goto dont_reuse;
 
-	if (conn->proto.epoch != rxnet->epoch)
+	if (conn->state != RXRPC_CONN_CLIENT ||
+	    conn->proto.epoch != rxnet->epoch)
 		goto mark_dont_reuse;
 
 	/* The IDR tree gets very expensive on memory if the connection IDs are
@@ -254,7 +243,7 @@ static bool rxrpc_may_reuse_conn(struct rxrpc_connection *conn)
 	distance = id - id_cursor;
 	if (distance < 0)
 		distance = -distance;
-	limit = max(rxrpc_max_client_connections * 4, 1024U);
+	limit = max_t(unsigned long, atomic_read(&rxnet->nr_conns) * 4, 1024);
 	if (distance > limit)
 		goto mark_dont_reuse;
 
@@ -267,277 +256,242 @@ static bool rxrpc_may_reuse_conn(struct rxrpc_connection *conn)
 }
 
 /*
- * Create or find a client connection to use for a call.
- *
- * If we return with a connection, the call will be on its waiting list.  It's
- * left to the caller to assign a channel and wake up the call.
+ * Look up the conn bundle that matches the connection parameters, adding it if
+ * it doesn't yet exist.
  */
-static int rxrpc_get_client_conn(struct rxrpc_sock *rx,
-				 struct rxrpc_call *call,
-				 struct rxrpc_conn_parameters *cp,
-				 struct sockaddr_rxrpc *srx,
-				 gfp_t gfp)
+static struct rxrpc_bundle *rxrpc_look_up_bundle(struct rxrpc_conn_parameters *cp,
+						 gfp_t gfp)
 {
-	struct rxrpc_connection *conn, *candidate = NULL;
+	static atomic_t rxrpc_bundle_id;
+	struct rxrpc_bundle *bundle, *candidate;
 	struct rxrpc_local *local = cp->local;
 	struct rb_node *p, **pp, *parent;
 	long diff;
-	int ret = -ENOMEM;
 
-	_enter("{%d,%lx},", call->debug_id, call->user_call_ID);
+	_enter("{%px,%x,%u,%u}",
+	       cp->peer, key_serial(cp->key), cp->security_level, cp->upgrade);
 
-	cp->peer = rxrpc_lookup_peer(rx, cp->local, srx, gfp);
-	if (!cp->peer)
-		goto error;
+	if (cp->exclusive)
+		return rxrpc_alloc_bundle(cp, gfp);
 
-	call->cong_cwnd = cp->peer->cong_cwnd;
-	if (call->cong_cwnd >= call->cong_ssthresh)
-		call->cong_mode = RXRPC_CALL_CONGEST_AVOIDANCE;
-	else
-		call->cong_mode = RXRPC_CALL_SLOW_START;
+	/* First, see if the bundle is already there. */
+	_debug("search 1");
+	spin_lock(&local->client_bundles_lock);
+	p = local->client_bundles.rb_node;
+	while (p) {
+		bundle = rb_entry(p, struct rxrpc_bundle, local_node);
 
-	/* If the connection is not meant to be exclusive, search the available
-	 * connections to see if the connection we want to use already exists.
-	 */
-	if (!cp->exclusive) {
-		_debug("search 1");
-		spin_lock(&local->client_conns_lock);
-		p = local->client_conns.rb_node;
-		while (p) {
-			conn = rb_entry(p, struct rxrpc_connection, client_node);
-
-#define cmp(X) ((long)conn->params.X - (long)cp->X)
-			diff = (cmp(peer) ?:
-				cmp(key) ?:
-				cmp(security_level) ?:
-				cmp(upgrade));
+#define cmp(X) ((long)bundle->params.X - (long)cp->X)
+		diff = (cmp(peer) ?:
+			cmp(key) ?:
+			cmp(security_level) ?:
+			cmp(upgrade));
 #undef cmp
-			if (diff < 0) {
-				p = p->rb_left;
-			} else if (diff > 0) {
-				p = p->rb_right;
-			} else {
-				if (rxrpc_may_reuse_conn(conn) &&
-				    rxrpc_get_connection_maybe(conn))
-					goto found_extant_conn;
-				/* The connection needs replacing.  It's better
-				 * to effect that when we have something to
-				 * replace it with so that we don't have to
-				 * rebalance the tree twice.
-				 */
-				break;
-			}
-		}
-		spin_unlock(&local->client_conns_lock);
-	}
-
-	/* There wasn't a connection yet or we need an exclusive connection.
-	 * We need to create a candidate and then potentially redo the search
-	 * in case we're racing with another thread also trying to connect on a
-	 * shareable connection.
-	 */
-	_debug("new conn");
-	candidate = rxrpc_alloc_client_connection(cp, gfp);
-	if (IS_ERR(candidate)) {
-		ret = PTR_ERR(candidate);
-		goto error_peer;
+		if (diff < 0)
+			p = p->rb_left;
+		else if (diff > 0)
+			p = p->rb_right;
+		else
+			goto found_bundle;
 	}
+	spin_unlock(&local->client_bundles_lock);
+	_debug("not found");
 
-	/* Add the call to the new connection's waiting list in case we're
-	 * going to have to wait for the connection to come live.  It's our
-	 * connection, so we want first dibs on the channel slots.  We would
-	 * normally have to take channel_lock but we do this before anyone else
-	 * can see the connection.
-	 */
-	list_add(&call->chan_wait_link, &candidate->waiting_calls);
-
-	if (cp->exclusive) {
-		call->conn = candidate;
-		call->security = candidate->security;
-		call->security_ix = candidate->security_ix;
-		call->service_id = candidate->service_id;
-		_leave(" = 0 [exclusive %d]", candidate->debug_id);
-		return 0;
-	}
+	/* It wasn't.  We need to add one. */
+	candidate = rxrpc_alloc_bundle(cp, gfp);
+	if (!candidate)
+		return NULL;
 
-	/* Publish the new connection for userspace to find.  We need to redo
-	 * the search before doing this lest we race with someone else adding a
-	 * conflicting instance.
-	 */
 	_debug("search 2");
-	spin_lock(&local->client_conns_lock);
-
-	pp = &local->client_conns.rb_node;
+	spin_lock(&local->client_bundles_lock);
+	pp = &local->client_bundles.rb_node;
 	parent = NULL;
 	while (*pp) {
 		parent = *pp;
-		conn = rb_entry(parent, struct rxrpc_connection, client_node);
+		bundle = rb_entry(parent, struct rxrpc_bundle, local_node);
 
-#define cmp(X) ((long)conn->params.X - (long)candidate->params.X)
+#define cmp(X) ((long)bundle->params.X - (long)cp->X)
 		diff = (cmp(peer) ?:
 			cmp(key) ?:
 			cmp(security_level) ?:
 			cmp(upgrade));
 #undef cmp
-		if (diff < 0) {
+		if (diff < 0)
 			pp = &(*pp)->rb_left;
-		} else if (diff > 0) {
+		else if (diff > 0)
 			pp = &(*pp)->rb_right;
-		} else {
-			if (rxrpc_may_reuse_conn(conn) &&
-			    rxrpc_get_connection_maybe(conn))
-				goto found_extant_conn;
-			/* The old connection is from an outdated epoch. */
-			_debug("replace conn");
-			clear_bit(RXRPC_CONN_IN_CLIENT_CONNS, &conn->flags);
-			rb_replace_node(&conn->client_node,
-					&candidate->client_node,
-					&local->client_conns);
-			trace_rxrpc_client(conn, -1, rxrpc_client_replace);
-			goto candidate_published;
-		}
+		else
+			goto found_bundle_free;
 	}
 
-	_debug("new conn");
-	rb_link_node(&candidate->client_node, parent, pp);
-	rb_insert_color(&candidate->client_node, &local->client_conns);
-
-candidate_published:
-	set_bit(RXRPC_CONN_IN_CLIENT_CONNS, &candidate->flags);
-	call->conn = candidate;
-	call->security = candidate->security;
-	call->security_ix = candidate->security_ix;
-	call->service_id = candidate->service_id;
-	spin_unlock(&local->client_conns_lock);
-	_leave(" = 0 [new %d]", candidate->debug_id);
-	return 0;
+	_debug("new bundle");
+	candidate->debug_id = atomic_inc_return(&rxrpc_bundle_id);
+	rb_link_node(&candidate->local_node, parent, pp);
+	rb_insert_color(&candidate->local_node, &local->client_bundles);
+	rxrpc_get_bundle(candidate);
+	spin_unlock(&local->client_bundles_lock);
+	_leave(" = %u [new]", candidate->debug_id);
+	return candidate;
+
+found_bundle_free:
+	kfree(candidate);
+found_bundle:
+	rxrpc_get_bundle(bundle);
+	spin_unlock(&local->client_bundles_lock);
+	_leave(" = %u [found]", bundle->debug_id);
+	return bundle;
+}
 
-	/* We come here if we found a suitable connection already in existence.
-	 * Discard any candidate we may have allocated, and try to get a
-	 * channel on this one.
-	 */
-found_extant_conn:
-	_debug("found conn");
-	spin_unlock(&local->client_conns_lock);
+/*
+ * Create or find a client bundle to use for a call.
+ *
+ * If we return with a connection, the call will be on its waiting list.  It's
+ * left to the caller to assign a channel and wake up the call.
+ */
+static struct rxrpc_bundle *rxrpc_prep_call(struct rxrpc_sock *rx,
+					    struct rxrpc_call *call,
+					    struct rxrpc_conn_parameters *cp,
+					    struct sockaddr_rxrpc *srx,
+					    gfp_t gfp)
+{
+	struct rxrpc_bundle *bundle;
 
-	if (candidate) {
-		trace_rxrpc_client(candidate, -1, rxrpc_client_duplicate);
-		rxrpc_put_connection(candidate);
-		candidate = NULL;
-	}
+	_enter("{%d,%lx},", call->debug_id, call->user_call_ID);
 
-	spin_lock(&conn->channel_lock);
-	call->conn = conn;
-	call->security = conn->security;
-	call->security_ix = conn->security_ix;
-	call->service_id = conn->service_id;
-	list_add_tail(&call->chan_wait_link, &conn->waiting_calls);
-	spin_unlock(&conn->channel_lock);
-	_leave(" = 0 [extant %d]", conn->debug_id);
-	return 0;
+	cp->peer = rxrpc_lookup_peer(rx, cp->local, srx, gfp);
+	if (!cp->peer)
+		goto error;
+
+	call->cong_cwnd = cp->peer->cong_cwnd;
+	if (call->cong_cwnd >= call->cong_ssthresh)
+		call->cong_mode = RXRPC_CALL_CONGEST_AVOIDANCE;
+	else
+		call->cong_mode = RXRPC_CALL_SLOW_START;
+	if (cp->upgrade)
+		__set_bit(RXRPC_CALL_UPGRADE, &call->flags);
+
+	/* Find the client connection bundle. */
+	bundle = rxrpc_look_up_bundle(cp, gfp);
+	if (!bundle)
+		goto error;
+
+	/* Get this call queued.  Someone else may activate it whilst we're
+	 * lining up a new connection, but that's fine.
+	 */
+	spin_lock(&bundle->channel_lock);
+	list_add_tail(&call->chan_wait_link, &bundle->waiting_calls);
+	spin_unlock(&bundle->channel_lock);
+
+	_leave(" = [B=%x]", bundle->debug_id);
+	return bundle;
 
-error_peer:
-	rxrpc_put_peer(cp->peer);
-	cp->peer = NULL;
 error:
-	_leave(" = %d", ret);
-	return ret;
+	_leave(" = -ENOMEM");
+	return ERR_PTR(-ENOMEM);
 }
 
 /*
- * Activate a connection.
+ * Allocate a new connection and add it into a bundle.
  */
-static void rxrpc_activate_conn(struct rxrpc_net *rxnet,
-				struct rxrpc_connection *conn)
+static void rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle, gfp_t gfp)
+	__releases(bundle->channel_lock)
 {
-	if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags)) {
-		trace_rxrpc_client(conn, -1, rxrpc_client_to_upgrade);
-		conn->cache_state = RXRPC_CONN_CLIENT_UPGRADE;
-	} else {
-		trace_rxrpc_client(conn, -1, rxrpc_client_to_active);
-		conn->cache_state = RXRPC_CONN_CLIENT_ACTIVE;
-	}
-	rxnet->nr_active_client_conns++;
-	list_move_tail(&conn->cache_link, &rxnet->active_client_conns);
-}
+	struct rxrpc_connection *candidate = NULL, *old = NULL;
+	bool conflict;
+	int i;
 
-/*
- * Attempt to animate a connection for a new call.
- *
- * If it's not exclusive, the connection is in the endpoint tree, and we're in
- * the conn's list of those waiting to grab a channel.  There is, however, a
- * limit on the number of live connections allowed at any one time, so we may
- * have to wait for capacity to become available.
- *
- * Note that a connection on the waiting queue might *also* have active
- * channels if it has been culled to make space and then re-requested by a new
- * call.
- */
-static void rxrpc_animate_client_conn(struct rxrpc_net *rxnet,
-				      struct rxrpc_connection *conn)
-{
-	unsigned int nr_conns;
+	_enter("");
 
-	_enter("%d,%d", conn->debug_id, conn->cache_state);
+	conflict = bundle->alloc_conn;
+	if (!conflict)
+		bundle->alloc_conn = true;
+	spin_unlock(&bundle->channel_lock);
+	if (conflict) {
+		_leave(" [conf]");
+		return;
+	}
 
-	if (conn->cache_state == RXRPC_CONN_CLIENT_ACTIVE ||
-	    conn->cache_state == RXRPC_CONN_CLIENT_UPGRADE)
-		goto out;
+	candidate = rxrpc_alloc_client_connection(bundle, gfp);
 
-	spin_lock(&rxnet->client_conn_cache_lock);
+	spin_lock(&bundle->channel_lock);
+	bundle->alloc_conn = false;
 
-	nr_conns = rxnet->nr_client_conns;
-	if (!test_and_set_bit(RXRPC_CONN_COUNTED, &conn->flags)) {
-		trace_rxrpc_client(conn, -1, rxrpc_client_count);
-		rxnet->nr_client_conns = nr_conns + 1;
+	if (IS_ERR(candidate)) {
+		bundle->alloc_error = PTR_ERR(candidate);
+		spin_unlock(&bundle->channel_lock);
+		_leave(" [err %ld]", PTR_ERR(candidate));
+		return;
 	}
 
-	switch (conn->cache_state) {
-	case RXRPC_CONN_CLIENT_ACTIVE:
-	case RXRPC_CONN_CLIENT_UPGRADE:
-	case RXRPC_CONN_CLIENT_WAITING:
-		break;
-
-	case RXRPC_CONN_CLIENT_INACTIVE:
-	case RXRPC_CONN_CLIENT_CULLED:
-	case RXRPC_CONN_CLIENT_IDLE:
-		if (nr_conns >= rxrpc_max_client_connections)
-			goto wait_for_capacity;
-		goto activate_conn;
+	bundle->alloc_error = 0;
+
+	for (i = 0; i < ARRAY_SIZE(bundle->conns); i++) {
+		unsigned int shift = i * RXRPC_MAXCALLS;
+		int j;
+
+		old = bundle->conns[i];
+		if (!rxrpc_may_reuse_conn(old)) {
+			if (old)
+				trace_rxrpc_client(old, -1, rxrpc_client_replace);
+			candidate->bundle = rxrpc_get_bundle(bundle);
+			candidate->bundle_shift = shift;
+			bundle->conns[i] = candidate;
+			for (j = 0; j < RXRPC_MAXCALLS; j++)
+				set_bit(shift + j, &bundle->avail_chans);
+			candidate = NULL;
+			break;
+		}
 
-	default:
-		BUG();
+		old = NULL;
 	}
 
-out_unlock:
-	spin_unlock(&rxnet->client_conn_cache_lock);
-out:
-	_leave(" [%d]", conn->cache_state);
-	return;
+	spin_unlock(&bundle->channel_lock);
 
-activate_conn:
-	_debug("activate");
-	rxrpc_activate_conn(rxnet, conn);
-	goto out_unlock;
-
-wait_for_capacity:
-	_debug("wait");
-	trace_rxrpc_client(conn, -1, rxrpc_client_to_waiting);
-	conn->cache_state = RXRPC_CONN_CLIENT_WAITING;
-	list_move_tail(&conn->cache_link, &rxnet->waiting_client_conns);
-	goto out_unlock;
+	if (candidate) {
+		_debug("discard C=%x", candidate->debug_id);
+		trace_rxrpc_client(candidate, -1, rxrpc_client_duplicate);
+		rxrpc_put_connection(candidate);
+	}
+
+	rxrpc_put_connection(old);
+	_leave("");
 }
 
 /*
- * Deactivate a channel.
+ * Add a connection to a bundle if there are no usable connections or we have
+ * connections waiting for extra capacity.
  */
-static void rxrpc_deactivate_one_channel(struct rxrpc_connection *conn,
-					 unsigned int channel)
+static void rxrpc_maybe_add_conn(struct rxrpc_bundle *bundle, gfp_t gfp)
 {
-	struct rxrpc_channel *chan = &conn->channels[channel];
+	struct rxrpc_call *call;
+	int i, usable;
 
-	rcu_assign_pointer(chan->call, NULL);
-	conn->active_chans &= ~(1 << channel);
+	_enter("");
+
+	spin_lock(&bundle->channel_lock);
+
+	/* See if there are any usable connections. */
+	usable = 0;
+	for (i = 0; i < ARRAY_SIZE(bundle->conns); i++)
+		if (rxrpc_may_reuse_conn(bundle->conns[i]))
+			usable++;
+
+	if (!usable && !list_empty(&bundle->waiting_calls)) {
+		call = list_first_entry(&bundle->waiting_calls,
+					struct rxrpc_call, chan_wait_link);
+		if (test_bit(RXRPC_CALL_UPGRADE, &call->flags))
+			bundle->try_upgrade = true;
+	}
+
+	if (!usable)
+		goto alloc_conn;
+
+	spin_unlock(&bundle->channel_lock);
+	_leave("");
+	return;
+
+alloc_conn:
+	return rxrpc_add_conn_to_bundle(bundle, gfp);
 }
 
 /*
@@ -549,35 +503,42 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
 				       unsigned int channel)
 {
 	struct rxrpc_channel *chan = &conn->channels[channel];
-	struct rxrpc_call *call = list_entry(conn->waiting_calls.next,
+	struct rxrpc_bundle *bundle = conn->bundle;
+	struct rxrpc_call *call = list_entry(bundle->waiting_calls.next,
 					     struct rxrpc_call, chan_wait_link);
 	u32 call_id = chan->call_counter + 1;
 
+	_enter("C=%x,%u", conn->debug_id, channel);
+
 	trace_rxrpc_client(conn, channel, rxrpc_client_chan_activate);
 
 	/* Cancel the final ACK on the previous call if it hasn't been sent yet
 	 * as the DATA packet will implicitly ACK it.
 	 */
 	clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
-
-	write_lock_bh(&call->state_lock);
-	call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
-	write_unlock_bh(&call->state_lock);
+	clear_bit(conn->bundle_shift + channel, &bundle->avail_chans);
 
 	rxrpc_see_call(call);
 	list_del_init(&call->chan_wait_link);
-	conn->active_chans |= 1 << channel;
 	call->peer	= rxrpc_get_peer(conn->params.peer);
+	call->conn	= rxrpc_get_connection(conn);
 	call->cid	= conn->proto.cid | channel;
 	call->call_id	= call_id;
+	call->security	= conn->security;
+	call->security_ix = conn->security_ix;
+	call->service_id = conn->service_id;
 
 	trace_rxrpc_connect_call(call);
 	_net("CONNECT call %08x:%08x as call %d on conn %d",
 	     call->cid, call->call_id, call->debug_id, conn->debug_id);
 
-	/* Paired with the read barrier in rxrpc_wait_for_channel().  This
-	 * orders cid and epoch in the connection wrt to call_id without the
-	 * need to take the channel_lock.
+	write_lock_bh(&call->state_lock);
+	call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
+	write_unlock_bh(&call->state_lock);
+
+	/* Paired with the read barrier in rxrpc_connect_call().  This orders
+	 * cid and epoch in the connection wrt to call_id without the need to
+	 * take the channel_lock.
 	 *
 	 * We provisionally assign a callNumber at this point, but we don't
 	 * confirm it until the call is about to be exposed.
@@ -586,101 +547,137 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
 	 * at the call ID through a connection channel.
 	 */
 	smp_wmb();
-	chan->call_id	= call_id;
-	chan->call_debug_id = call->debug_id;
+
+	chan->call_id		= call_id;
+	chan->call_debug_id	= call->debug_id;
 	rcu_assign_pointer(chan->call, call);
 	wake_up(&call->waitq);
 }
 
+/*
+ * Remove a connection from the idle list if it's on it.
+ */
+static void rxrpc_unidle_conn(struct rxrpc_bundle *bundle, struct rxrpc_connection *conn)
+{
+	struct rxrpc_net *rxnet = bundle->params.local->rxnet;
+	bool drop_ref;
+
+	if (!list_empty(&conn->cache_link)) {
+		drop_ref = false;
+		spin_lock(&rxnet->client_conn_cache_lock);
+		if (!list_empty(&conn->cache_link)) {
+			list_del_init(&conn->cache_link);
+			drop_ref = true;
+		}
+		spin_unlock(&rxnet->client_conn_cache_lock);
+		if (drop_ref)
+			rxrpc_put_connection(conn);
+	}
+}
+
 /*
  * Assign channels and callNumbers to waiting calls with channel_lock
  * held by caller.
  */
-static void rxrpc_activate_channels_locked(struct rxrpc_connection *conn)
+static void rxrpc_activate_channels_locked(struct rxrpc_bundle *bundle)
 {
-	u8 avail, mask;
-
-	switch (conn->cache_state) {
-	case RXRPC_CONN_CLIENT_ACTIVE:
-		mask = RXRPC_ACTIVE_CHANS_MASK;
-		break;
-	case RXRPC_CONN_CLIENT_UPGRADE:
-		mask = 0x01;
-		break;
-	default:
-		return;
-	}
+	struct rxrpc_connection *conn;
+	unsigned long avail, mask;
+	unsigned int channel, slot;
 
-	while (!list_empty(&conn->waiting_calls) &&
-	       (avail = ~conn->active_chans,
-		avail &= mask,
-		avail != 0))
-		rxrpc_activate_one_channel(conn, __ffs(avail));
+	if (bundle->try_upgrade)
+		mask = 1;
+	else
+		mask = ULONG_MAX;
+
+	while (!list_empty(&bundle->waiting_calls)) {
+		avail = bundle->avail_chans & mask;
+		if (!avail)
+			break;
+		channel = __ffs(avail);
+		clear_bit(channel, &bundle->avail_chans);
+
+		slot = channel / RXRPC_MAXCALLS;
+		conn = bundle->conns[slot];
+		if (!conn)
+			break;
+
+		if (bundle->try_upgrade)
+			set_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags);
+		rxrpc_unidle_conn(bundle, conn);
+
+		channel &= (RXRPC_MAXCALLS - 1);
+		conn->act_chans	|= 1 << channel;
+		rxrpc_activate_one_channel(conn, channel);
+	}
 }
 
 /*
  * Assign channels and callNumbers to waiting calls.
  */
-static void rxrpc_activate_channels(struct rxrpc_connection *conn)
+static void rxrpc_activate_channels(struct rxrpc_bundle *bundle)
 {
-	_enter("%d", conn->debug_id);
+	_enter("B=%x", bundle->debug_id);
 
-	trace_rxrpc_client(conn, -1, rxrpc_client_activate_chans);
+	trace_rxrpc_client(NULL, -1, rxrpc_client_activate_chans);
 
-	if (conn->active_chans == RXRPC_ACTIVE_CHANS_MASK)
+	if (!bundle->avail_chans)
 		return;
 
-	spin_lock(&conn->channel_lock);
-	rxrpc_activate_channels_locked(conn);
-	spin_unlock(&conn->channel_lock);
+	spin_lock(&bundle->channel_lock);
+	rxrpc_activate_channels_locked(bundle);
+	spin_unlock(&bundle->channel_lock);
 	_leave("");
 }
 
 /*
  * Wait for a callNumber and a channel to be granted to a call.
  */
-static int rxrpc_wait_for_channel(struct rxrpc_call *call, gfp_t gfp)
+static int rxrpc_wait_for_channel(struct rxrpc_bundle *bundle,
+				  struct rxrpc_call *call, gfp_t gfp)
 {
+	DECLARE_WAITQUEUE(myself, current);
 	int ret = 0;
 
 	_enter("%d", call->debug_id);
 
-	if (!call->call_id) {
-		DECLARE_WAITQUEUE(myself, current);
+	if (!gfpflags_allow_blocking(gfp)) {
+		rxrpc_maybe_add_conn(bundle, gfp);
+		rxrpc_activate_channels(bundle);
+		ret = bundle->alloc_error ?: -EAGAIN;
+		goto out;
+	}
 
-		if (!gfpflags_allow_blocking(gfp)) {
-			ret = -EAGAIN;
-			goto out;
+	add_wait_queue_exclusive(&call->waitq, &myself);
+	for (;;) {
+		rxrpc_maybe_add_conn(bundle, gfp);
+		rxrpc_activate_channels(bundle);
+		ret = bundle->alloc_error;
+		if (ret < 0)
+			break;
+
+		switch (call->interruptibility) {
+		case RXRPC_INTERRUPTIBLE:
+		case RXRPC_PREINTERRUPTIBLE:
+			set_current_state(TASK_INTERRUPTIBLE);
+			break;
+		case RXRPC_UNINTERRUPTIBLE:
+		default:
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			break;
 		}
-
-		add_wait_queue_exclusive(&call->waitq, &myself);
-		for (;;) {
-			switch (call->interruptibility) {
-			case RXRPC_INTERRUPTIBLE:
-			case RXRPC_PREINTERRUPTIBLE:
-				set_current_state(TASK_INTERRUPTIBLE);
-				break;
-			case RXRPC_UNINTERRUPTIBLE:
-			default:
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				break;
-			}
-			if (call->call_id)
-				break;
-			if ((call->interruptibility == RXRPC_INTERRUPTIBLE ||
-			     call->interruptibility == RXRPC_PREINTERRUPTIBLE) &&
-			    signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-			schedule();
+		if (READ_ONCE(call->state) != RXRPC_CALL_CLIENT_AWAIT_CONN)
+			break;
+		if ((call->interruptibility == RXRPC_INTERRUPTIBLE ||
+		     call->interruptibility == RXRPC_PREINTERRUPTIBLE) &&
+		    signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
 		}
-		remove_wait_queue(&call->waitq, &myself);
-		__set_current_state(TASK_RUNNING);
+		schedule();
 	}
-
-	/* Paired with the write barrier in rxrpc_activate_one_channel(). */
-	smp_rmb();
+	remove_wait_queue(&call->waitq, &myself);
+	__set_current_state(TASK_RUNNING);
 
 out:
 	_leave(" = %d", ret);
@@ -697,52 +694,49 @@ int rxrpc_connect_call(struct rxrpc_sock *rx,
 		       struct sockaddr_rxrpc *srx,
 		       gfp_t gfp)
 {
+	struct rxrpc_bundle *bundle;
 	struct rxrpc_net *rxnet = cp->local->rxnet;
-	int ret;
+	int ret = 0;
 
 	_enter("{%d,%lx},", call->debug_id, call->user_call_ID);
 
 	rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper);
-	rxrpc_cull_active_client_conns(rxnet);
 
-	ret = rxrpc_get_client_conn(rx, call, cp, srx, gfp);
-	if (ret < 0)
+	bundle = rxrpc_prep_call(rx, call, cp, srx, gfp);
+	if (IS_ERR(bundle)) {
+		ret = PTR_ERR(bundle);
 		goto out;
+	}
 
-	rxrpc_animate_client_conn(rxnet, call->conn);
-	rxrpc_activate_channels(call->conn);
-
-	ret = rxrpc_wait_for_channel(call, gfp);
-	if (ret < 0) {
-		trace_rxrpc_client(call->conn, ret, rxrpc_client_chan_wait_failed);
-		rxrpc_disconnect_client_call(call);
-		goto out;
+	if (call->state == RXRPC_CALL_CLIENT_AWAIT_CONN) {
+		ret = rxrpc_wait_for_channel(bundle, call, gfp);
+		if (ret < 0)
+			goto wait_failed;
 	}
 
-	spin_lock_bh(&call->conn->params.peer->lock);
-	hlist_add_head_rcu(&call->error_link,
-			   &call->conn->params.peer->error_targets);
-	spin_unlock_bh(&call->conn->params.peer->lock);
+granted_channel:
+	/* Paired with the write barrier in rxrpc_activate_one_channel(). */
+	smp_rmb();
 
 out:
+	rxrpc_put_bundle(bundle);
 	_leave(" = %d", ret);
 	return ret;
-}
 
-/*
- * Note that a connection is about to be exposed to the world.  Once it is
- * exposed, we maintain an extra ref on it that stops it from being summarily
- * discarded before it's (a) had a chance to deal with retransmission and (b)
- * had a chance at re-use (the per-connection security negotiation is
- * expensive).
- */
-static void rxrpc_expose_client_conn(struct rxrpc_connection *conn,
-				     unsigned int channel)
-{
-	if (!test_and_set_bit(RXRPC_CONN_EXPOSED, &conn->flags)) {
-		trace_rxrpc_client(conn, channel, rxrpc_client_exposed);
-		rxrpc_get_connection(conn);
+wait_failed:
+	spin_lock(&bundle->channel_lock);
+	list_del_init(&call->chan_wait_link);
+	spin_unlock(&bundle->channel_lock);
+
+	if (call->state != RXRPC_CALL_CLIENT_AWAIT_CONN) {
+		ret = 0;
+		goto granted_channel;
 	}
+
+	trace_rxrpc_client(call->conn, ret, rxrpc_client_chan_wait_failed);
+	rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 0, ret);
+	rxrpc_disconnect_client_call(bundle, call);
+	goto out;
 }
 
 /*
@@ -764,7 +758,7 @@ void rxrpc_expose_client_call(struct rxrpc_call *call)
 		chan->call_counter++;
 		if (chan->call_counter >= INT_MAX)
 			set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
-		rxrpc_expose_client_conn(conn, channel);
+		trace_rxrpc_client(conn, channel, rxrpc_client_exposed);
 	}
 }
 
@@ -773,62 +767,56 @@ void rxrpc_expose_client_call(struct rxrpc_call *call)
  */
 static void rxrpc_set_client_reap_timer(struct rxrpc_net *rxnet)
 {
-	unsigned long now = jiffies;
-	unsigned long reap_at = now + rxrpc_conn_idle_client_expiry;
+	if (!rxnet->kill_all_client_conns) {
+		unsigned long now = jiffies;
+		unsigned long reap_at = now + rxrpc_conn_idle_client_expiry;
 
-	if (rxnet->live)
-		timer_reduce(&rxnet->client_conn_reap_timer, reap_at);
+		if (rxnet->live)
+			timer_reduce(&rxnet->client_conn_reap_timer, reap_at);
+	}
 }
 
 /*
  * Disconnect a client call.
  */
-void rxrpc_disconnect_client_call(struct rxrpc_call *call)
+void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call *call)
 {
-	struct rxrpc_connection *conn = call->conn;
+	struct rxrpc_connection *conn;
 	struct rxrpc_channel *chan = NULL;
-	struct rxrpc_net *rxnet = conn->params.local->rxnet;
-	unsigned int channel = -1;
+	struct rxrpc_net *rxnet = bundle->params.local->rxnet;
+	unsigned int channel;
+	bool may_reuse;
 	u32 cid;
 
-	spin_lock(&conn->channel_lock);
-	set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
+	_enter("c=%x", call->debug_id);
 
-	cid = call->cid;
-	if (cid) {
-		channel = cid & RXRPC_CHANNELMASK;
-		chan = &conn->channels[channel];
-	}
-	trace_rxrpc_client(conn, channel, rxrpc_client_chan_disconnect);
+	spin_lock(&bundle->channel_lock);
+	set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
 
 	/* Calls that have never actually been assigned a channel can simply be
-	 * discarded.  If the conn didn't get used either, it will follow
-	 * immediately unless someone else grabs it in the meantime.
+	 * discarded.
 	 */
-	if (!list_empty(&call->chan_wait_link)) {
+	conn = call->conn;
+	if (!conn) {
 		_debug("call is waiting");
 		ASSERTCMP(call->call_id, ==, 0);
 		ASSERT(!test_bit(RXRPC_CALL_EXPOSED, &call->flags));
 		list_del_init(&call->chan_wait_link);
-
-		trace_rxrpc_client(conn, channel, rxrpc_client_chan_unstarted);
-
-		/* We must deactivate or idle the connection if it's now
-		 * waiting for nothing.
-		 */
-		spin_lock(&rxnet->client_conn_cache_lock);
-		if (conn->cache_state == RXRPC_CONN_CLIENT_WAITING &&
-		    list_empty(&conn->waiting_calls) &&
-		    !conn->active_chans)
-			goto idle_connection;
 		goto out;
 	}
 
+	cid = call->cid;
+	channel = cid & RXRPC_CHANNELMASK;
+	chan = &conn->channels[channel];
+	trace_rxrpc_client(conn, channel, rxrpc_client_chan_disconnect);
+
 	if (rcu_access_pointer(chan->call) != call) {
-		spin_unlock(&conn->channel_lock);
+		spin_unlock(&bundle->channel_lock);
 		BUG();
 	}
 
+	may_reuse = rxrpc_may_reuse_conn(conn);
+
 	/* If a client call was exposed to the world, we save the result for
 	 * retransmission.
 	 *
@@ -841,14 +829,21 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
 	if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
 		_debug("exposed %u,%u", call->call_id, call->abort_code);
 		__rxrpc_disconnect_call(conn, call);
+
+		if (test_and_clear_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags)) {
+			trace_rxrpc_client(conn, channel, rxrpc_client_to_active);
+			bundle->try_upgrade = false;
+			if (may_reuse)
+				rxrpc_activate_channels_locked(bundle);
+		}
+
 	}
 
 	/* See if we can pass the channel directly to another call. */
-	if (conn->cache_state == RXRPC_CONN_CLIENT_ACTIVE &&
-	    !list_empty(&conn->waiting_calls)) {
+	if (may_reuse && !list_empty(&bundle->waiting_calls)) {
 		trace_rxrpc_client(conn, channel, rxrpc_client_chan_pass);
 		rxrpc_activate_one_channel(conn, channel);
-		goto out_2;
+		goto out;
 	}
 
 	/* Schedule the final ACK to be transmitted in a short while so that it
@@ -865,128 +860,95 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
 		rxrpc_reduce_conn_timer(conn, final_ack_at);
 	}
 
-	/* Things are more complex and we need the cache lock.  We might be
-	 * able to simply idle the conn or it might now be lurking on the wait
-	 * list.  It might even get moved back to the active list whilst we're
-	 * waiting for the lock.
-	 */
-	spin_lock(&rxnet->client_conn_cache_lock);
-
-	switch (conn->cache_state) {
-	case RXRPC_CONN_CLIENT_UPGRADE:
-		/* Deal with termination of a service upgrade probe. */
-		if (test_bit(RXRPC_CONN_EXPOSED, &conn->flags)) {
-			clear_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags);
-			trace_rxrpc_client(conn, channel, rxrpc_client_to_active);
-			conn->cache_state = RXRPC_CONN_CLIENT_ACTIVE;
-			rxrpc_activate_channels_locked(conn);
-		}
-		fallthrough;
-	case RXRPC_CONN_CLIENT_ACTIVE:
-		if (list_empty(&conn->waiting_calls)) {
-			rxrpc_deactivate_one_channel(conn, channel);
-			if (!conn->active_chans) {
-				rxnet->nr_active_client_conns--;
-				goto idle_connection;
-			}
-			goto out;
-		}
-
-		trace_rxrpc_client(conn, channel, rxrpc_client_chan_pass);
-		rxrpc_activate_one_channel(conn, channel);
-		goto out;
+	/* Deactivate the channel. */
+	rcu_assign_pointer(chan->call, NULL);
+	set_bit(conn->bundle_shift + channel, &conn->bundle->avail_chans);
+	conn->act_chans	&= ~(1 << channel);
 
-	case RXRPC_CONN_CLIENT_CULLED:
-		rxrpc_deactivate_one_channel(conn, channel);
-		ASSERT(list_empty(&conn->waiting_calls));
-		if (!conn->active_chans)
-			goto idle_connection;
-		goto out;
+	/* If no channels remain active, then put the connection on the idle
+	 * list for a short while.  Give it a ref to stop it going away if it
+	 * becomes unbundled.
+	 */
+	if (!conn->act_chans) {
+		trace_rxrpc_client(conn, channel, rxrpc_client_to_idle);
+		conn->idle_timestamp = jiffies;
 
-	case RXRPC_CONN_CLIENT_WAITING:
-		rxrpc_deactivate_one_channel(conn, channel);
-		goto out;
+		rxrpc_get_connection(conn);
+		spin_lock(&rxnet->client_conn_cache_lock);
+		list_move_tail(&conn->cache_link, &rxnet->idle_client_conns);
+		spin_unlock(&rxnet->client_conn_cache_lock);
 
-	default:
-		BUG();
+		rxrpc_set_client_reap_timer(rxnet);
 	}
 
 out:
-	spin_unlock(&rxnet->client_conn_cache_lock);
-out_2:
-	spin_unlock(&conn->channel_lock);
+	spin_unlock(&bundle->channel_lock);
 	_leave("");
 	return;
+}
 
-idle_connection:
-	/* As no channels remain active, the connection gets deactivated
-	 * immediately or moved to the idle list for a short while.
-	 */
-	if (test_bit(RXRPC_CONN_EXPOSED, &conn->flags)) {
-		trace_rxrpc_client(conn, channel, rxrpc_client_to_idle);
-		conn->idle_timestamp = jiffies;
-		conn->cache_state = RXRPC_CONN_CLIENT_IDLE;
-		list_move_tail(&conn->cache_link, &rxnet->idle_client_conns);
-		if (rxnet->idle_client_conns.next == &conn->cache_link &&
-		    !rxnet->kill_all_client_conns)
-			rxrpc_set_client_reap_timer(rxnet);
-	} else {
-		trace_rxrpc_client(conn, channel, rxrpc_client_to_inactive);
-		conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
-		list_del_init(&conn->cache_link);
+/*
+ * Remove a connection from a bundle.
+ */
+static void rxrpc_unbundle_conn(struct rxrpc_connection *conn)
+{
+	struct rxrpc_bundle *bundle = conn->bundle;
+	struct rxrpc_local *local = bundle->params.local;
+	unsigned int bindex;
+	bool need_drop = false;
+	int i;
+
+	_enter("C=%x", conn->debug_id);
+
+	spin_lock(&bundle->channel_lock);
+	bindex = conn->bundle_shift / RXRPC_MAXCALLS;
+	if (bundle->conns[bindex] == conn) {
+		_debug("clear slot %u", bindex);
+		bundle->conns[bindex] = NULL;
+		for (i = 0; i < RXRPC_MAXCALLS; i++)
+			clear_bit(conn->bundle_shift + i, &bundle->avail_chans);
+		need_drop = true;
 	}
-	goto out;
+	spin_unlock(&bundle->channel_lock);
+
+	/* If there are no more connections, remove the bundle */
+	if (!bundle->avail_chans) {
+		_debug("maybe unbundle");
+		spin_lock(&local->client_bundles_lock);
+
+		for (i = 0; i < ARRAY_SIZE(bundle->conns); i++)
+			if (bundle->conns[i])
+				break;
+		if (i == ARRAY_SIZE(bundle->conns) && !bundle->params.exclusive) {
+			_debug("erase bundle");
+			rb_erase(&bundle->local_node, &local->client_bundles);
+		}
+
+		spin_unlock(&local->client_bundles_lock);
+		if (i == ARRAY_SIZE(bundle->conns))
+			rxrpc_put_bundle(bundle);
+	}
+
+	if (need_drop)
+		rxrpc_put_connection(conn);
+	_leave("");
 }
 
 /*
  * Clean up a dead client connection.
  */
-static struct rxrpc_connection *
-rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
+static void rxrpc_kill_client_conn(struct rxrpc_connection *conn)
 {
-	struct rxrpc_connection *next = NULL;
 	struct rxrpc_local *local = conn->params.local;
 	struct rxrpc_net *rxnet = local->rxnet;
-	unsigned int nr_conns;
 
-	trace_rxrpc_client(conn, -1, rxrpc_client_cleanup);
+	_enter("C=%x", conn->debug_id);
 
-	if (test_bit(RXRPC_CONN_IN_CLIENT_CONNS, &conn->flags)) {
-		spin_lock(&local->client_conns_lock);
-		if (test_and_clear_bit(RXRPC_CONN_IN_CLIENT_CONNS,
-				       &conn->flags))
-			rb_erase(&conn->client_node, &local->client_conns);
-		spin_unlock(&local->client_conns_lock);
-	}
+	trace_rxrpc_client(conn, -1, rxrpc_client_cleanup);
+	atomic_dec(&rxnet->nr_client_conns);
 
 	rxrpc_put_client_connection_id(conn);
-
-	ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_INACTIVE);
-
-	if (test_bit(RXRPC_CONN_COUNTED, &conn->flags)) {
-		trace_rxrpc_client(conn, -1, rxrpc_client_uncount);
-		spin_lock(&rxnet->client_conn_cache_lock);
-		nr_conns = --rxnet->nr_client_conns;
-
-		if (nr_conns < rxrpc_max_client_connections &&
-		    !list_empty(&rxnet->waiting_client_conns)) {
-			next = list_entry(rxnet->waiting_client_conns.next,
-					  struct rxrpc_connection, cache_link);
-			rxrpc_get_connection(next);
-			rxrpc_activate_conn(rxnet, next);
-		}
-
-		spin_unlock(&rxnet->client_conn_cache_lock);
-	}
-
 	rxrpc_kill_connection(conn);
-	if (next)
-		rxrpc_activate_channels(next);
-
-	/* We need to get rid of the temporary ref we took upon next, but we
-	 * can't call rxrpc_put_connection() recursively.
-	 */
-	return next;
 }
 
 /*
@@ -998,63 +960,12 @@ void rxrpc_put_client_conn(struct rxrpc_connection *conn)
 	unsigned int debug_id = conn->debug_id;
 	int n;
 
-	do {
-		n = atomic_dec_return(&conn->usage);
-		trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, n, here);
-		if (n > 0)
-			return;
+	n = atomic_dec_return(&conn->usage);
+	trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, n, here);
+	if (n <= 0) {
 		ASSERTCMP(n, >=, 0);
-
-		conn = rxrpc_put_one_client_conn(conn);
-	} while (conn);
-}
-
-/*
- * Kill the longest-active client connections to make room for new ones.
- */
-static void rxrpc_cull_active_client_conns(struct rxrpc_net *rxnet)
-{
-	struct rxrpc_connection *conn;
-	unsigned int nr_conns = rxnet->nr_client_conns;
-	unsigned int nr_active, limit;
-
-	_enter("");
-
-	ASSERTCMP(nr_conns, >=, 0);
-	if (nr_conns < rxrpc_max_client_connections) {
-		_leave(" [ok]");
-		return;
+		rxrpc_kill_client_conn(conn);
 	}
-	limit = rxrpc_reap_client_connections;
-
-	spin_lock(&rxnet->client_conn_cache_lock);
-	nr_active = rxnet->nr_active_client_conns;
-
-	while (nr_active > limit) {
-		ASSERT(!list_empty(&rxnet->active_client_conns));
-		conn = list_entry(rxnet->active_client_conns.next,
-				  struct rxrpc_connection, cache_link);
-		ASSERTIFCMP(conn->cache_state != RXRPC_CONN_CLIENT_ACTIVE,
-			    conn->cache_state, ==, RXRPC_CONN_CLIENT_UPGRADE);
-
-		if (list_empty(&conn->waiting_calls)) {
-			trace_rxrpc_client(conn, -1, rxrpc_client_to_culled);
-			conn->cache_state = RXRPC_CONN_CLIENT_CULLED;
-			list_del_init(&conn->cache_link);
-		} else {
-			trace_rxrpc_client(conn, -1, rxrpc_client_to_waiting);
-			conn->cache_state = RXRPC_CONN_CLIENT_WAITING;
-			list_move_tail(&conn->cache_link,
-				       &rxnet->waiting_client_conns);
-		}
-
-		nr_active--;
-	}
-
-	rxnet->nr_active_client_conns = nr_active;
-	spin_unlock(&rxnet->client_conn_cache_lock);
-	ASSERTCMP(nr_active, >=, 0);
-	_leave(" [culled]");
 }
 
 /*
@@ -1088,7 +999,7 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 	/* We keep an estimate of what the number of conns ought to be after
 	 * we've discarded some so that we don't overdo the discarding.
 	 */
-	nr_conns = rxnet->nr_client_conns;
+	nr_conns = atomic_read(&rxnet->nr_client_conns);
 
 next:
 	spin_lock(&rxnet->client_conn_cache_lock);
@@ -1098,7 +1009,6 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 
 	conn = list_entry(rxnet->idle_client_conns.next,
 			  struct rxrpc_connection, cache_link);
-	ASSERT(test_bit(RXRPC_CONN_EXPOSED, &conn->flags));
 
 	if (!rxnet->kill_all_client_conns) {
 		/* If the number of connections is over the reap limit, we
@@ -1120,18 +1030,13 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 	}
 
 	trace_rxrpc_client(conn, -1, rxrpc_client_discard);
-	if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags))
-		BUG();
-	conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
 	list_del_init(&conn->cache_link);
 
 	spin_unlock(&rxnet->client_conn_cache_lock);
 
-	/* When we cleared the EXPOSED flag, we took on responsibility for the
-	 * reference that that had on the usage count.  We deal with that here.
-	 * If someone re-sets the flag and re-gets the ref, that's fine.
-	 */
-	rxrpc_put_connection(conn);
+	rxrpc_unbundle_conn(conn);
+	rxrpc_put_connection(conn); /* Drop the ->cache_link ref */
+
 	nr_conns--;
 	goto next;
 
@@ -1145,8 +1050,7 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 	 */
 	_debug("not yet");
 	if (!rxnet->kill_all_client_conns)
-		timer_reduce(&rxnet->client_conn_reap_timer,
-			     conn_expires_at);
+		timer_reduce(&rxnet->client_conn_reap_timer, conn_expires_at);
 
 out:
 	spin_unlock(&rxnet->client_conn_cache_lock);
@@ -1181,37 +1085,26 @@ void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
 {
 	struct rxrpc_connection *conn, *tmp;
 	struct rxrpc_net *rxnet = local->rxnet;
-	unsigned int nr_active;
 	LIST_HEAD(graveyard);
 
 	_enter("");
 
 	spin_lock(&rxnet->client_conn_cache_lock);
-	nr_active = rxnet->nr_active_client_conns;
 
 	list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns,
 				 cache_link) {
 		if (conn->params.local == local) {
-			ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE);
-
 			trace_rxrpc_client(conn, -1, rxrpc_client_discard);
-			if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags))
-				BUG();
-			conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
 			list_move(&conn->cache_link, &graveyard);
-			nr_active--;
 		}
 	}
 
-	rxnet->nr_active_client_conns = nr_active;
 	spin_unlock(&rxnet->client_conn_cache_lock);
-	ASSERTCMP(nr_active, >=, 0);
 
 	while (!list_empty(&graveyard)) {
 		conn = list_entry(graveyard.next,
 				  struct rxrpc_connection, cache_link);
 		list_del_init(&conn->cache_link);
-
 		rxrpc_put_connection(conn);
 	}
 
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 447f55ca6886..0628dad2bdea 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -157,12 +157,12 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
 
 	_enter("{%d},%x", conn->debug_id, conn->abort_code);
 
-	spin_lock(&conn->channel_lock);
+	spin_lock(&conn->bundle->channel_lock);
 
 	for (i = 0; i < RXRPC_MAXCALLS; i++) {
 		call = rcu_dereference_protected(
 			conn->channels[i].call,
-			lockdep_is_held(&conn->channel_lock));
+			lockdep_is_held(&conn->bundle->channel_lock));
 		if (call) {
 			if (compl == RXRPC_CALL_LOCALLY_ABORTED)
 				trace_rxrpc_abort(call->debug_id,
@@ -179,7 +179,7 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
 		}
 	}
 
-	spin_unlock(&conn->channel_lock);
+	spin_unlock(&conn->bundle->channel_lock);
 	_leave("");
 }
 
@@ -210,6 +210,7 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
 	conn->error = error;
 	conn->abort_code = abort_code;
 	conn->state = RXRPC_CONN_LOCALLY_ABORTED;
+	set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
 	spin_unlock_bh(&conn->state_lock);
 
 	msg.msg_name	= &conn->params.peer->srx.transport;
@@ -319,6 +320,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
 		conn->error = -ECONNABORTED;
 		conn->abort_code = abort_code;
 		conn->state = RXRPC_CONN_REMOTELY_ABORTED;
+		set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
 		rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED, sp->hdr.serial);
 		return -ECONNABORTED;
 
@@ -339,7 +341,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
 		if (ret < 0)
 			return ret;
 
-		spin_lock(&conn->channel_lock);
+		spin_lock(&conn->bundle->channel_lock);
 		spin_lock(&conn->state_lock);
 
 		if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
@@ -349,12 +351,12 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
 				rxrpc_call_is_secure(
 					rcu_dereference_protected(
 						conn->channels[loop].call,
-						lockdep_is_held(&conn->channel_lock)));
+						lockdep_is_held(&conn->bundle->channel_lock)));
 		} else {
 			spin_unlock(&conn->state_lock);
 		}
 
-		spin_unlock(&conn->channel_lock);
+		spin_unlock(&conn->bundle->channel_lock);
 		return 0;
 
 	default:
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 8cbe0bf20ed5..3bcbe0665f91 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -41,8 +41,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
 	conn = kzalloc(sizeof(struct rxrpc_connection), gfp);
 	if (conn) {
 		INIT_LIST_HEAD(&conn->cache_link);
-		spin_lock_init(&conn->channel_lock);
-		INIT_LIST_HEAD(&conn->waiting_calls);
 		timer_setup(&conn->timer, &rxrpc_connection_timer, 0);
 		INIT_WORK(&conn->processor, &rxrpc_process_connection);
 		INIT_LIST_HEAD(&conn->proc_link);
@@ -219,11 +217,11 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
 	}
 
 	if (rxrpc_is_client_call(call))
-		return rxrpc_disconnect_client_call(call);
+		return rxrpc_disconnect_client_call(conn->bundle, call);
 
-	spin_lock(&conn->channel_lock);
+	spin_lock(&conn->bundle->channel_lock);
 	__rxrpc_disconnect_call(conn, call);
-	spin_unlock(&conn->channel_lock);
+	spin_unlock(&conn->bundle->channel_lock);
 
 	set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
 	conn->idle_timestamp = jiffies;
@@ -292,12 +290,13 @@ void rxrpc_see_connection(struct rxrpc_connection *conn)
 /*
  * Get a ref on a connection.
  */
-void rxrpc_get_connection(struct rxrpc_connection *conn)
+struct rxrpc_connection *rxrpc_get_connection(struct rxrpc_connection *conn)
 {
 	const void *here = __builtin_return_address(0);
 	int n = atomic_inc_return(&conn->usage);
 
 	trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n, here);
+	return conn;
 }
 
 /*
@@ -365,6 +364,7 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
 	conn->security->clear(conn);
 	key_put(conn->params.key);
 	key_put(conn->server_key);
+	rxrpc_put_bundle(conn->bundle);
 	rxrpc_put_peer(conn->params.peer);
 
 	if (atomic_dec_and_test(&conn->params.local->rxnet->nr_conns))
diff --git a/net/rxrpc/conn_service.c b/net/rxrpc/conn_service.c
index 21da48e3d2e5..6c847720494f 100644
--- a/net/rxrpc/conn_service.c
+++ b/net/rxrpc/conn_service.c
@@ -8,6 +8,12 @@
 #include <linux/slab.h>
 #include "ar-internal.h"
 
+static struct rxrpc_bundle rxrpc_service_dummy_bundle = {
+	.usage		= ATOMIC_INIT(1),
+	.debug_id	= UINT_MAX,
+	.channel_lock	= __SPIN_LOCK_UNLOCKED(&rxrpc_service_dummy_bundle.channel_lock),
+};
+
 /*
  * Find a service connection under RCU conditions.
  *
@@ -127,6 +133,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
 		 */
 		conn->state = RXRPC_CONN_SERVICE_PREALLOC;
 		atomic_set(&conn->usage, 2);
+		conn->bundle = rxrpc_get_bundle(&rxrpc_service_dummy_bundle);
 
 		atomic_inc(&rxnet->nr_conns);
 		write_lock(&rxnet->conn_lock);
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index ede058f9cc15..8c2881054266 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -86,8 +86,8 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
 		init_rwsem(&local->defrag_sem);
 		skb_queue_head_init(&local->reject_queue);
 		skb_queue_head_init(&local->event_queue);
-		local->client_conns = RB_ROOT;
-		spin_lock_init(&local->client_conns_lock);
+		local->client_bundles = RB_ROOT;
+		spin_lock_init(&local->client_bundles_lock);
 		spin_lock_init(&local->lock);
 		rwlock_init(&local->services_lock);
 		local->debug_id = atomic_inc_return(&rxrpc_debug_id);
diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c
index b312aab80fed..25bbc4cc8b13 100644
--- a/net/rxrpc/net_ns.c
+++ b/net/rxrpc/net_ns.c
@@ -62,13 +62,10 @@ static __net_init int rxrpc_init_net(struct net *net)
 	timer_setup(&rxnet->service_conn_reap_timer,
 		    rxrpc_service_conn_reap_timeout, 0);
 
-	rxnet->nr_client_conns = 0;
-	rxnet->nr_active_client_conns = 0;
+	atomic_set(&rxnet->nr_client_conns, 0);
 	rxnet->kill_all_client_conns = false;
 	spin_lock_init(&rxnet->client_conn_cache_lock);
 	spin_lock_init(&rxnet->client_conn_discard_lock);
-	INIT_LIST_HEAD(&rxnet->waiting_client_conns);
-	INIT_LIST_HEAD(&rxnet->active_client_conns);
 	INIT_LIST_HEAD(&rxnet->idle_client_conns);
 	INIT_WORK(&rxnet->client_conn_reaper,
 		  rxrpc_discard_expired_client_conns);
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 3cfff7922ba8..10f2bf2e9068 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -357,6 +357,12 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
 
 	_enter(",{%d}", skb->len);
 
+	if (hlist_unhashed(&call->error_link)) {
+		spin_lock_bh(&call->peer->lock);
+		hlist_add_head_rcu(&call->error_link, &call->peer->error_targets);
+		spin_unlock_bh(&call->peer->lock);
+	}
+
 	/* Each transmission of a Tx packet needs a new serial number */
 	serial = atomic_inc_return(&conn->serial);
 
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 543afd9bd664..e2f990754f88 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -165,7 +165,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
 			 "Proto Local                                          "
 			 " Remote                                         "
 			 " SvID ConnID   End Use State    Key     "
-			 " Serial   ISerial\n"
+			 " Serial   ISerial  CallId0  CallId1  CallId2  CallId3\n"
 			 );
 		return 0;
 	}
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index e08130e5746b..f114dc2af5cf 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -1169,7 +1169,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
 	if (response->encrypted.checksum != csum)
 		goto protocol_error_free;
 
-	spin_lock(&conn->channel_lock);
+	spin_lock(&conn->bundle->channel_lock);
 	for (i = 0; i < RXRPC_MAXCALLS; i++) {
 		struct rxrpc_call *call;
 		u32 call_id = ntohl(response->encrypted.call_id[i]);
@@ -1186,13 +1186,13 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
 		if (call_id > conn->channels[i].call_counter) {
 			call = rcu_dereference_protected(
 				conn->channels[i].call,
-				lockdep_is_held(&conn->channel_lock));
+				lockdep_is_held(&conn->bundle->channel_lock));
 			if (call && call->state < RXRPC_CALL_COMPLETE)
 				goto protocol_error_unlock;
 			conn->channels[i].call_counter = call_id;
 		}
 	}
-	spin_unlock(&conn->channel_lock);
+	spin_unlock(&conn->bundle->channel_lock);
 
 	eproto = tracepoint_string("rxkad_rsp_seq");
 	abort_code = RXKADOUTOFSEQUENCE;
@@ -1219,7 +1219,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
 	return 0;
 
 protocol_error_unlock:
-	spin_unlock(&conn->channel_lock);
+	spin_unlock(&conn->bundle->channel_lock);
 protocol_error_free:
 	kfree(ticket);
 protocol_error:
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c
index e91acc95ff28..540351d6a5f4 100644
--- a/net/rxrpc/sysctl.c
+++ b/net/rxrpc/sysctl.c
@@ -73,14 +73,6 @@ static struct ctl_table rxrpc_sysctl_table[] = {
 	},
 
 	/* Non-time values */
-	{
-		.procname	= "max_client_conns",
-		.data		= &rxrpc_max_client_connections,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= (void *)&rxrpc_reap_client_connections,
-	},
 	{
 		.procname	= "reap_client_conns",
 		.data		= &rxrpc_reap_client_connections,
@@ -88,7 +80,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_minmax,
 		.extra1		= (void *)SYSCTL_ONE,
-		.extra2		= (void *)&rxrpc_max_client_connections,
+		.extra2		= (void *)&n_65535,
 	},
 	{
 		.procname	= "max_backlog",




From davem at davemloft.net  Tue Sep  8 23:18:38 2020
From: davem at davemloft.net (David Miller)
Date: Tue, 08 Sep 2020 20:18:38 -0700 (PDT)
Subject: [PATCH net-next 0/3] rxrpc: Allow more calls to same peer
In-Reply-To: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
References: <159959825107.645007.502549394334535916.stgit@warthog.procyon.org.uk>
Message-ID: <20200908.201838.1474174755046579625.davem@davemloft.net>

From: David Howells <dhowells at redhat.com>
Date: Tue, 08 Sep 2020 21:50:51 +0100

> Here are some development patches for AF_RXRPC that allow more simultaneous
> calls to be made to the same peer with the same security parameters.  The
> current code allows a maximum of 4 simultaneous calls, which limits the afs
> filesystem to that many simultaneous threads.  This increases the limit to
> 16.
> 
> To make this work, the way client connections are limited has to be changed
> (incoming call/connection limits are unaffected) as the current code
> depends on queuing calls on a connection and then pushing the connection
> through a queue.  The limit is on the number of available connections.
> 
> This is changed such that there's a limit[*] on the total number of calls
> systemwide across all namespaces, but the limit on the number of client
> connections is removed.
> 
> Once a call is allowed to proceed, it finds a bundle of connections and
> tries to grab a call slot.  If there's a spare call slot, fine, otherwise
> it will wait.  If there's already a waiter, it will try to create another
> connection in the bundle, unless the limit of 4 is reached (4 calls per
> connection, giving 16).
> 
> A number of things throttle someone trying to set up endless connections:
> 
>  - Calls that fail immediately have their conns deleted immediately,
> 
>  - Calls that don't fail immediately have to wait for a timeout,
> 
>  - Connections normally get automatically reaped if they haven't been used
>    for 2m, but this is sped up to 2s if the number of connections rises
>    over 900.  This number is tunable by sysctl.
> 
> 
> [*] Technically two limits - kernel sockets and userspace rxrpc sockets are
>     accounted separately.
> 
> The patches are tagged here:
> 
> 	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
> 	rxrpc-next-20200908

Pulled, thanks David.


From syzbot+52071f826a617b9c76ed at syzkaller.appspotmail.com  Thu Sep 10 04:48:21 2020
From: syzbot+52071f826a617b9c76ed at syzkaller.appspotmail.com (syzbot)
Date: Thu, 10 Sep 2020 01:48:21 -0700
Subject: kernel BUG at net/rxrpc/conn_object.c:LINE!
Message-ID: <000000000000610c6805aef1a1b8@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    f5499c67 nfc: pn533/usb.c: fix spelling of "functions"
git tree:       net-next
console output: https://syzkaller.appspot.com/x/log.txt?x=16415055900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=2b946b3cd0adc99
dashboard link: https://syzkaller.appspot.com/bug?extid=52071f826a617b9c76ed
compiler:       gcc (GCC) 10.1.0-syz 20200507
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=16be260d900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=100b7cdd900000

The issue was bisected to:

commit 245500d853e9f20036cec7df4f6984ece4c6bf26
Author: David Howells <dhowells at redhat.com>
Date:   Wed Jul 1 10:15:32 2020 +0000

    rxrpc: Rewrite the client connection manager

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=11950759900000
final oops:     https://syzkaller.appspot.com/x/report.txt?x=13950759900000
console output: https://syzkaller.appspot.com/x/log.txt?x=15950759900000

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+52071f826a617b9c76ed at syzkaller.appspotmail.com
Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")

rxrpc: Assertion failed
------------[ cut here ]------------
kernel BUG at net/rxrpc/conn_object.c:481!
invalid opcode: 0000 [#1] PREEMPT SMP KASAN
CPU: 1 PID: 234 Comm: kworker/u4:5 Not tainted 5.9.0-rc3-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: netns cleanup_net
RIP: 0010:rxrpc_destroy_all_connections.cold+0x11/0x13 net/rxrpc/conn_object.c:481
Code: c0 48 c7 c1 00 b0 14 89 48 89 f2 48 c7 c7 80 ac 14 89 e8 04 4d 0c fa 0f 0b e8 be 15 23 fa 48 c7 c7 80 af 14 89 e8 f1 4c 0c fa <0f> 0b 41 57 41 56 41 55 41 54 55 53 48 89 f3 48 83 ec 20 48 89 3c
RSP: 0018:ffffc90000f57b18 EFLAGS: 00010282
RAX: 0000000000000017 RBX: ffff8880945a8000 RCX: 0000000000000000
RDX: ffff8880a85ca200 RSI: ffffffff815dbd97 RDI: fffff520001eaf55
RBP: ffff8880945a8064 R08: 0000000000000017 R09: ffff8880ae731927
R10: 0000000000000000 R11: 0000000034333254 R12: ffff8880945a8068
R13: ffff8880945a8078 R14: ffff8880945a8078 R15: ffff8880945a7eb8
FS:  0000000000000000(0000) GS:ffff8880ae700000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdbae898020 CR3: 00000000963ae000 CR4: 00000000001506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 rxrpc_exit_net+0x1a4/0x2e0 net/rxrpc/net_ns.c:119
 ops_exit_list+0xb0/0x160 net/core/net_namespace.c:186
 cleanup_net+0x4ea/0xa00 net/core/net_namespace.c:603
 process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
Modules linked in:
---[ end trace b82f4cc98146655f ]---
RIP: 0010:rxrpc_destroy_all_connections.cold+0x11/0x13 net/rxrpc/conn_object.c:481
Code: c0 48 c7 c1 00 b0 14 89 48 89 f2 48 c7 c7 80 ac 14 89 e8 04 4d 0c fa 0f 0b e8 be 15 23 fa 48 c7 c7 80 af 14 89 e8 f1 4c 0c fa <0f> 0b 41 57 41 56 41 55 41 54 55 53 48 89 f3 48 83 ec 20 48 89 3c
RSP: 0018:ffffc90000f57b18 EFLAGS: 00010282
RAX: 0000000000000017 RBX: ffff8880945a8000 RCX: 0000000000000000
RDX: ffff8880a85ca200 RSI: ffffffff815dbd97 RDI: fffff520001eaf55
RBP: ffff8880945a8064 R08: 0000000000000017 R09: ffff8880ae731927
R10: 0000000000000000 R11: 0000000034333254 R12: ffff8880945a8068
R13: ffff8880945a8078 R14: ffff8880945a8078 R15: ffff8880945a7eb8
FS:  0000000000000000(0000) GS:ffff8880ae700000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdbae89e000 CR3: 0000000093fd8000 CR4: 00000000001506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
syzbot can test patches for this issue, for details see:
https://goo.gl/tpsmEJ#testing-patches


From gustavo at embeddedor.com  Wed Sep  9 16:38:45 2020
From: gustavo at embeddedor.com (Gustavo A. R. Silva)
Date: Wed, 9 Sep 2020 15:38:45 -0500
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <645bbaaf-984f-315f-1257-446651393925@embeddedor.com>



On 9/9/20 15:06, Joe Perches wrote:
> fallthrough to a separate case/default label break; isn't very readable.
> 
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
> 
> Found using:
> 
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> 
> Miscellanea:
> 
> o Move or coalesce a couple label blocks above a default: block.
> 
> Signed-off-by: Joe Perches <joe at perches.com>

Acked-by: Gustavo A. R. Silva <gustavoars at kernel.org>

Thanks
--
Gustavo

> ---
> 
> Compiled allyesconfig x86-64 only.
> A few files for other arches were not compiled.
> 
>  arch/arm/mach-mmp/pm-pxa910.c                             |  2 +-
>  arch/arm64/kvm/handle_exit.c                              |  2 +-
>  arch/mips/kernel/cpu-probe.c                              |  2 +-
>  arch/mips/math-emu/cp1emu.c                               |  2 +-
>  arch/s390/pci/pci.c                                       |  2 +-
>  crypto/tcrypt.c                                           |  4 ++--
>  drivers/ata/sata_mv.c                                     |  2 +-
>  drivers/atm/lanai.c                                       |  2 +-
>  drivers/gpu/drm/i915/display/intel_sprite.c               |  2 +-
>  drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c           |  2 +-
>  drivers/hid/wacom_wac.c                                   |  2 +-
>  drivers/i2c/busses/i2c-i801.c                             |  2 +-
>  drivers/infiniband/ulp/rtrs/rtrs-clt.c                    | 14 +++++++-------
>  drivers/infiniband/ulp/rtrs/rtrs-srv.c                    |  6 +++---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c               |  2 +-
>  drivers/irqchip/irq-vic.c                                 |  4 ++--
>  drivers/md/dm.c                                           |  2 +-
>  drivers/media/dvb-frontends/drxd_hard.c                   |  2 +-
>  drivers/media/i2c/ov5640.c                                |  2 +-
>  drivers/media/i2c/ov6650.c                                |  5 ++---
>  drivers/media/i2c/smiapp/smiapp-core.c                    |  2 +-
>  drivers/media/i2c/tvp5150.c                               |  2 +-
>  drivers/media/pci/ddbridge/ddbridge-core.c                |  2 +-
>  drivers/media/usb/cpia2/cpia2_core.c                      |  2 +-
>  drivers/mfd/iqs62x.c                                      |  3 +--
>  drivers/mmc/host/atmel-mci.c                              |  2 +-
>  drivers/mtd/nand/raw/nandsim.c                            |  2 +-
>  drivers/net/ethernet/intel/e1000e/phy.c                   |  2 +-
>  drivers/net/ethernet/intel/fm10k/fm10k_pf.c               |  2 +-
>  drivers/net/ethernet/intel/i40e/i40e_adminq.c             |  2 +-
>  drivers/net/ethernet/intel/i40e/i40e_txrx.c               |  2 +-
>  drivers/net/ethernet/intel/iavf/iavf_txrx.c               |  2 +-
>  drivers/net/ethernet/intel/igb/e1000_phy.c                |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c            |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c             |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c            |  2 +-
>  drivers/net/ethernet/intel/ixgbevf/vf.c                   |  2 +-
>  drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c |  2 +-
>  drivers/net/ethernet/qlogic/qed/qed_mcp.c                 |  2 +-
>  drivers/net/ethernet/sfc/falcon/farch.c                   |  2 +-
>  drivers/net/ethernet/sfc/farch.c                          |  2 +-
>  drivers/net/phy/adin.c                                    |  3 +--
>  drivers/net/usb/pegasus.c                                 |  4 ++--
>  drivers/net/usb/usbnet.c                                  |  2 +-
>  drivers/net/wireless/ath/ath5k/eeprom.c                   |  2 +-
>  drivers/net/wireless/mediatek/mt7601u/dma.c               |  8 ++++----
>  drivers/nvme/host/core.c                                  | 12 ++++++------
>  drivers/pcmcia/db1xxx_ss.c                                |  4 ++--
>  drivers/power/supply/abx500_chargalg.c                    |  2 +-
>  drivers/power/supply/charger-manager.c                    |  2 +-
>  drivers/rtc/rtc-pcf85063.c                                |  2 +-
>  drivers/s390/scsi/zfcp_fsf.c                              |  2 +-
>  drivers/scsi/aic7xxx/aic79xx_core.c                       |  4 ++--
>  drivers/scsi/aic94xx/aic94xx_tmf.c                        |  2 +-
>  drivers/scsi/lpfc/lpfc_sli.c                              |  2 +-
>  drivers/scsi/smartpqi/smartpqi_init.c                     |  2 +-
>  drivers/scsi/sr.c                                         |  2 +-
>  drivers/tty/serial/sunsu.c                                |  2 +-
>  drivers/tty/serial/sunzilog.c                             |  2 +-
>  drivers/tty/vt/vt_ioctl.c                                 |  2 +-
>  drivers/usb/dwc3/core.c                                   |  2 +-
>  drivers/usb/gadget/legacy/inode.c                         |  2 +-
>  drivers/usb/gadget/udc/pxa25x_udc.c                       |  4 ++--
>  drivers/usb/host/ohci-hcd.c                               |  2 +-
>  drivers/usb/isp1760/isp1760-hcd.c                         |  2 +-
>  drivers/usb/musb/cppi_dma.c                               |  2 +-
>  drivers/usb/phy/phy-fsl-usb.c                             |  2 +-
>  drivers/video/fbdev/stifb.c                               |  2 +-
>  fs/afs/yfsclient.c                                        |  8 ++++----
>  fs/ceph/dir.c                                             |  2 +-
>  fs/nfs/nfs4proc.c                                         |  2 +-
>  fs/nfs_common/nfsacl.c                                    |  2 +-
>  kernel/bpf/verifier.c                                     |  2 +-
>  kernel/sched/topology.c                                   |  2 +-
>  kernel/trace/trace_events_filter.c                        |  2 +-
>  net/dccp/output.c                                         |  2 +-
>  net/ipv4/ip_output.c                                      |  2 +-
>  net/netfilter/nf_tables_api.c                             |  2 +-
>  net/rxrpc/input.c                                         |  4 ++--
>  net/sctp/outqueue.c                                       |  2 +-
>  sound/soc/codecs/ak4613.c                                 |  2 +-
>  sound/soc/codecs/jz4770.c                                 |  2 +-
>  82 files changed, 109 insertions(+), 112 deletions(-)
> 
> diff --git a/arch/arm/mach-mmp/pm-pxa910.c b/arch/arm/mach-mmp/pm-pxa910.c
> index 1d71d73c1862..dcf2482a9e6c 100644
> --- a/arch/arm/mach-mmp/pm-pxa910.c
> +++ b/arch/arm/mach-mmp/pm-pxa910.c
> @@ -161,7 +161,7 @@ void pxa910_pm_enter_lowpower_mode(int state)
>  		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN;
>  		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
>  			| APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
> -		fallthrough;
> +		break;
>  	case POWER_MODE_CORE_INTIDLE:
>  		break;
>  	}
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 5d690d60ccad..bf3d54b0a233 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -128,7 +128,7 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
>  	switch (ESR_ELx_EC(esr)) {
>  	case ESR_ELx_EC_WATCHPT_LOW:
>  		run->debug.arch.far = vcpu->arch.fault.far_el2;
> -		fallthrough;
> +		break;
>  	case ESR_ELx_EC_SOFTSTP_LOW:
>  	case ESR_ELx_EC_BREAKPT_LOW:
>  	case ESR_ELx_EC_BKPT32:
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index e2955f1f6316..6ddc70211a0f 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -1823,7 +1823,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
>  		fallthrough;
>  	case CPU_I6400:
>  		c->options |= MIPS_CPU_SHARED_FTLB_RAM;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
> index 587cf1d115e8..9c8f8539ec5d 100644
> --- a/arch/mips/math-emu/cp1emu.c
> +++ b/arch/mips/math-emu/cp1emu.c
> @@ -1224,7 +1224,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
>  			case bctl_op:
>  				if (cpu_has_mips_2_3_4_5_r)
>  					likely = 1;
> -				fallthrough;
> +				break;
>  			case bct_op:
>  				break;
>  			}
> diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
> index 4b62d6b55024..5b1e412bbd32 100644
> --- a/arch/s390/pci/pci.c
> +++ b/arch/s390/pci/pci.c
> @@ -743,7 +743,7 @@ void zpci_release_device(struct kref *kref)
>  		zpci_cleanup_bus_resources(zdev);
>  		zpci_bus_device_unregister(zdev);
>  		zpci_destroy_iommu(zdev);
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
> index eea0f453cfb6..8aac5bc60f4c 100644
> --- a/crypto/tcrypt.c
> +++ b/crypto/tcrypt.c
> @@ -2464,7 +2464,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
>  		test_hash_speed("streebog512", sec,
>  				generic_hash_speed_template);
>  		if (mode > 300 && mode < 400) break;
> -		fallthrough;
> +		break;
>  	case 399:
>  		break;
>  
> @@ -2587,7 +2587,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
>  		test_mb_ahash_speed("streebog512", sec,
>  				    generic_hash_speed_template, num_mb);
>  		if (mode > 400 && mode < 500) break;
> -		fallthrough;
> +		break;
>  	case 499:
>  		break;
>  
> diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
> index 664ef658a955..4d6cce2352bd 100644
> --- a/drivers/ata/sata_mv.c
> +++ b/drivers/ata/sata_mv.c
> @@ -2044,7 +2044,7 @@ static enum ata_completion_errors mv_qc_prep(struct ata_queued_cmd *qc)
>  	case ATA_PROT_DMA:
>  		if (tf->command == ATA_CMD_DSM)
>  			return AC_ERR_OK;
> -		fallthrough;
> +		break;
>  	case ATA_PROT_NCQ:
>  		break;	/* continue below */
>  	case ATA_PROT_PIO:
> diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
> index ac811cfa6843..972a6837a20e 100644
> --- a/drivers/atm/lanai.c
> +++ b/drivers/atm/lanai.c
> @@ -2019,7 +2019,7 @@ static int lanai_normalize_ci(struct lanai_dev *lanai,
>  	switch (*vpip) {
>  		case ATM_VPI_ANY:
>  			*vpip = 0;
> -			fallthrough;
> +			break;
>  		case 0:
>  			break;
>  		default:
> diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
> index 5ac0dbf0e03d..35ac539cc2b1 100644
> --- a/drivers/gpu/drm/i915/display/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/display/intel_sprite.c
> @@ -2861,7 +2861,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
>  	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
>  		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
>  			return false;
> -		fallthrough;
> +		break;
>  	case DRM_FORMAT_MOD_LINEAR:
>  	case I915_FORMAT_MOD_X_TILED:
>  	case I915_FORMAT_MOD_Y_TILED:
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
> index 1ccfc8314812..bc83cf098e25 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
> @@ -71,7 +71,7 @@ void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
>  		fallthrough;
>  	case 1:
>  		header |= raw_frame[0];
> -		fallthrough;
> +		break;
>  	case 0:
>  		break;
>  	}
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index 83dfec327c42..822dc15b59b6 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -3833,7 +3833,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
>  	case MTTPC_B:
>  	case TABLETPC2FG:
>  		input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT);
> -		fallthrough;
> +		break;
>  
>  	case TABLETPC:
>  	case TABLETPCE:
> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
> index e32ef3f01fe8..b13b1cbcac29 100644
> --- a/drivers/i2c/busses/i2c-i801.c
> +++ b/drivers/i2c/busses/i2c-i801.c
> @@ -1785,7 +1785,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  		fallthrough;
>  	case PCI_DEVICE_ID_INTEL_82801CA_3:
>  		priv->features |= FEATURE_HOST_NOTIFY;
> -		fallthrough;
> +		break;
>  	case PCI_DEVICE_ID_INTEL_82801BA_2:
>  	case PCI_DEVICE_ID_INTEL_82801AB_3:
>  	case PCI_DEVICE_ID_INTEL_82801AA_3:
> diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
> index 776e89231c52..55339cad408a 100644
> --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
> +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
> @@ -209,7 +209,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		switch (old_state) {
>  		case RTRS_CLT_RECONNECTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -220,7 +220,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		case RTRS_CLT_CONNECTING_ERR:
>  		case RTRS_CLT_CLOSED:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -229,7 +229,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		switch (old_state) {
>  		case RTRS_CLT_CONNECTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -238,7 +238,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		switch (old_state) {
>  		case RTRS_CLT_CONNECTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -250,7 +250,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		case RTRS_CLT_RECONNECTING:
>  		case RTRS_CLT_CONNECTED:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -259,7 +259,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		switch (old_state) {
>  		case RTRS_CLT_CLOSING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -268,7 +268,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
>  		switch (old_state) {
>  		case RTRS_CLT_CLOSED:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
> index b61a18e57aeb..24e53b39a79c 100644
> --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
> +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
> @@ -78,7 +78,7 @@ static bool __rtrs_srv_change_state(struct rtrs_srv_sess *sess,
>  		switch (old_state) {
>  		case RTRS_SRV_CONNECTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -88,7 +88,7 @@ static bool __rtrs_srv_change_state(struct rtrs_srv_sess *sess,
>  		case RTRS_SRV_CONNECTING:
>  		case RTRS_SRV_CONNECTED:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -97,7 +97,7 @@ static bool __rtrs_srv_change_state(struct rtrs_srv_sess *sess,
>  		switch (old_state) {
>  		case RTRS_SRV_CLOSING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index c192544e874b..743db1abec40 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -3777,7 +3777,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
>  	switch (FIELD_GET(IDR0_TTF, reg)) {
>  	case IDR0_TTF_AARCH32_64:
>  		smmu->ias = 40;
> -		fallthrough;
> +		break;
>  	case IDR0_TTF_AARCH64:
>  		break;
>  	default:
> diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
> index e46036374227..10ff0a5c225a 100644
> --- a/drivers/irqchip/irq-vic.c
> +++ b/drivers/irqchip/irq-vic.c
> @@ -453,10 +453,10 @@ static void __init __vic_init(void __iomem *base, int parent_irq, int irq_start,
>  	case AMBA_VENDOR_ST:
>  		vic_init_st(base, irq_start, vic_sources, node);
>  		return;
> +	case AMBA_VENDOR_ARM:
> +		break;
>  	default:
>  		printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
> -		fallthrough;
> -	case AMBA_VENDOR_ARM:
>  		break;
>  	}
>  
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index 3dedd9cc4fb6..dc71573d5b09 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -1021,7 +1021,7 @@ static void clone_endio(struct bio *bio)
>  		switch (r) {
>  		case DM_ENDIO_REQUEUE:
>  			error = BLK_STS_DM_REQUEUE;
> -			fallthrough;
> +			break;
>  		case DM_ENDIO_DONE:
>  			break;
>  		case DM_ENDIO_INCOMPLETE:
> diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
> index 45f982863904..d6592e764a92 100644
> --- a/drivers/media/dvb-frontends/drxd_hard.c
> +++ b/drivers/media/dvb-frontends/drxd_hard.c
> @@ -1519,7 +1519,7 @@ static int SetDeviceTypeId(struct drxd_state *state)
>  				break;
>  			case 6:
>  				state->diversity = 1;
> -				fallthrough;
> +				break;
>  			case 5:
>  			case 8:
>  				break;
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 637687d761f2..855d3aba711a 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -3010,7 +3010,7 @@ static int ov5640_probe(struct i2c_client *client)
>  		switch (rotation) {
>  		case 180:
>  			sensor->upside_down = true;
> -			fallthrough;
> +			break;
>  		case 0:
>  			break;
>  		default:
> diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
> index d73f9f540932..fde56572dce8 100644
> --- a/drivers/media/i2c/ov6650.c
> +++ b/drivers/media/i2c/ov6650.c
> @@ -685,17 +685,16 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd,
>  	switch (mf->code) {
>  	case MEDIA_BUS_FMT_Y10_1X10:
>  		mf->code = MEDIA_BUS_FMT_Y8_1X8;
> -		fallthrough;
> +		break;
>  	case MEDIA_BUS_FMT_Y8_1X8:
>  	case MEDIA_BUS_FMT_YVYU8_2X8:
>  	case MEDIA_BUS_FMT_YUYV8_2X8:
>  	case MEDIA_BUS_FMT_VYUY8_2X8:
>  	case MEDIA_BUS_FMT_UYVY8_2X8:
> +	case MEDIA_BUS_FMT_SBGGR8_1X8:
>  		break;
>  	default:
>  		mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
> -		fallthrough;
> -	case MEDIA_BUS_FMT_SBGGR8_1X8:
>  		break;
>  	}
>  
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index 6fc0680a93d0..8bfba407b8f1 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -2795,7 +2795,7 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
>  		case 180:
>  			hwcfg->module_board_orient =
>  				SMIAPP_MODULE_BOARD_ORIENT_180;
> -			fallthrough;
> +			break;
>  		case 0:
>  			break;
>  		default:
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index 7d9401219a3a..df174089e74d 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -293,7 +293,7 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
>  	switch (decoder->input) {
>  	case TVP5150_COMPOSITE1:
>  		input |= 2;
> -		fallthrough;
> +		break;
>  	case TVP5150_COMPOSITE0:
>  		break;
>  	case TVP5150_SVIDEO:
> diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
> index 92fe051c672f..426c9e0152d8 100644
> --- a/drivers/media/pci/ddbridge/ddbridge-core.c
> +++ b/drivers/media/pci/ddbridge/ddbridge-core.c
> @@ -1336,7 +1336,7 @@ static void dvb_input_detach(struct ddb_input *input)
>  		fallthrough;
>  	case 0x10:
>  		dvb_dmx_release(&dvb->demux);
> -		fallthrough;
> +		break;
>  	case 0x01:
>  		break;
>  	}
> diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c
> index e747548ab286..cbef274d4f95 100644
> --- a/drivers/media/usb/cpia2/cpia2_core.c
> +++ b/drivers/media/usb/cpia2/cpia2_core.c
> @@ -1751,7 +1751,7 @@ int cpia2_set_fps(struct camera_data *cam, int framerate)
>  						    CPIA2_VP_SENSOR_FLAGS_500) {
>  				return -EINVAL;
>  			}
> -			fallthrough;
> +			break;
>  		case CPIA2_VP_FRAMERATE_15:
>  		case CPIA2_VP_FRAMERATE_12_5:
>  		case CPIA2_VP_FRAMERATE_7_5:
> diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c
> index 761b4ef3a381..5671482ec8fe 100644
> --- a/drivers/mfd/iqs62x.c
> +++ b/drivers/mfd/iqs62x.c
> @@ -490,8 +490,7 @@ static irqreturn_t iqs62x_irq(int irq, void *context)
>  
>  		case IQS62X_EVENT_HYST:
>  			event_map[i] <<= iqs62x->dev_desc->hyst_shift;
> -
> -			fallthrough;
> +			break;
>  
>  		case IQS62X_EVENT_WHEEL:
>  		case IQS62X_EVENT_HALL:
> diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
> index 444bd3a0a922..8324312e4f42 100644
> --- a/drivers/mmc/host/atmel-mci.c
> +++ b/drivers/mmc/host/atmel-mci.c
> @@ -2435,7 +2435,7 @@ static void atmci_get_cap(struct atmel_mci *host)
>  	case 0x100:
>  		host->caps.has_bad_data_ordering = 0;
>  		host->caps.need_reset_after_xfer = 0;
> -		fallthrough;
> +		break;
>  	case 0x0:
>  		break;
>  	default:
> diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
> index f5a53aac3c5f..b07934247297 100644
> --- a/drivers/mtd/nand/raw/nandsim.c
> +++ b/drivers/mtd/nand/raw/nandsim.c
> @@ -2286,7 +2286,7 @@ static int __init ns_init_module(void)
>  		fallthrough;
>  	case 1:
>  		chip->bbt_options |= NAND_BBT_USE_FLASH;
> -		fallthrough;
> +		break;
>  	case 0:
>  		break;
>  	default:
> diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
> index e11c877595fb..9fec7cc52710 100644
> --- a/drivers/net/ethernet/intel/e1000e/phy.c
> +++ b/drivers/net/ethernet/intel/e1000e/phy.c
> @@ -607,7 +607,7 @@ static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
>  		break;
>  	case e1000_ms_auto:
>  		phy_data &= ~CTL1000_ENABLE_MASTER;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
> index c0780c3624c8..1c601d7464dd 100644
> --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
> +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
> @@ -1329,7 +1329,7 @@ static u8 fm10k_iov_supported_xcast_mode_pf(struct fm10k_vf_info *vf_info,
>  	case FM10K_XCAST_MODE_NONE:
>  		if (vf_flags & FM10K_VF_FLAG_NONE_CAPABLE)
>  			return FM10K_XCAST_MODE_NONE;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
> index c897a2863e4f..857b699f02c9 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
> @@ -541,7 +541,7 @@ static void i40e_set_hw_flags(struct i40e_hw *hw)
>  		    (aq->api_maj_ver == 1 &&
>  		     aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_X722))
>  			hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> index 91ab824926b9..ef4f3dbc7b7e 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> @@ -1690,7 +1690,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
>  	case I40E_RX_PTYPE_INNER_PROT_UDP:
>  	case I40E_RX_PTYPE_INNER_PROT_SCTP:
>  		skb->ip_summed = CHECKSUM_UNNECESSARY;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
> index 256fa07d54d5..c2c1ef255008 100644
> --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c
> +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
> @@ -1007,7 +1007,7 @@ static inline void iavf_rx_checksum(struct iavf_vsi *vsi,
>  	case IAVF_RX_PTYPE_INNER_PROT_UDP:
>  	case IAVF_RX_PTYPE_INNER_PROT_SCTP:
>  		skb->ip_summed = CHECKSUM_UNNECESSARY;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
> index 8c8eb82e6272..f8f7ffbc45f0 100644
> --- a/drivers/net/ethernet/intel/igb/e1000_phy.c
> +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
> @@ -2621,7 +2621,7 @@ static s32 igb_set_master_slave_mode(struct e1000_hw *hw)
>  		break;
>  	case e1000_ms_auto:
>  		phy_data &= ~CR_1000T_MS_ENABLE;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
> index 8d3798a32f0e..1549f0342384 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
> @@ -1589,7 +1589,7 @@ s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
>  	case 0x0000:
>  		/* Mask Flex Bytes */
>  		fdirm |= IXGBE_FDIRM_FLEX;
> -		fallthrough;
> +		break;
>  	case 0xFFFF:
>  		break;
>  	default:
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index 0b675c34ce49..17e0fe4d380e 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -5901,7 +5901,7 @@ void ixgbe_disable_tx(struct ixgbe_adapter *adapter)
>  		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
>  				(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
>  				 ~IXGBE_DMATXCTL_TE));
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> index 988db46bff0e..45b18708f5ed 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
> @@ -1141,7 +1141,7 @@ static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter,
>  		/* promisc introduced in 1.3 version */
>  		if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC)
>  			return -EOPNOTSUPP;
> -		fallthrough;
> +		break;
>  	case ixgbe_mbox_api_13:
>  	case ixgbe_mbox_api_14:
>  		break;
> diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
> index bfe6dfcec4ab..7f14665b6bdf 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/vf.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
> @@ -540,7 +540,7 @@ static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode)
>  		/* promisc introduced in 1.3 version */
>  		if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC)
>  			return -EOPNOTSUPP;
> -		fallthrough;
> +		break;
>  	case ixgbe_mbox_api_14:
>  	case ixgbe_mbox_api_13:
>  		break;
> diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
> index 252fe06f58aa..1d5b87079104 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
> @@ -345,7 +345,7 @@ static int matching_bar(struct nfp_bar *bar, u32 tgt, u32 act, u32 tok,
>  		baract = NFP_CPP_ACTION_RW;
>  		if (act == 0)
>  			act = NFP_CPP_ACTION_RW;
> -		fallthrough;
> +		break;
>  	case NFP_PCIE_BAR_PCIE2CPP_MapType_FIXED:
>  		break;
>  	default:
> diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
> index cd882c453394..1bffe5cb88f4 100644
> --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
> +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
> @@ -3546,7 +3546,7 @@ qed_mcp_resc_allocation_msg(struct qed_hwfn *p_hwfn,
>  	switch (p_in_params->cmd) {
>  	case DRV_MSG_SET_RESOURCE_VALUE_MSG:
>  		mfw_resc_info.size = p_in_params->resc_max_val;
> -		fallthrough;
> +		break;
>  	case DRV_MSG_GET_RESOURCE_ALLOC_MSG:
>  		break;
>  	default:
> diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c
> index fa1ade856b10..14f42c94809d 100644
> --- a/drivers/net/ethernet/sfc/falcon/farch.c
> +++ b/drivers/net/ethernet/sfc/falcon/farch.c
> @@ -1052,7 +1052,7 @@ ef4_farch_handle_rx_event(struct ef4_channel *channel, const ef4_qword_t *event)
>  			fallthrough;
>  		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
>  			flags |= EF4_RX_PKT_CSUMMED;
> -			fallthrough;
> +			break;
>  		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
>  		case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
>  			break;
> diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
> index e004524e14a8..cea0eb822473 100644
> --- a/drivers/net/ethernet/sfc/farch.c
> +++ b/drivers/net/ethernet/sfc/farch.c
> @@ -1038,7 +1038,7 @@ efx_farch_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
>  			fallthrough;
>  		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
>  			flags |= EFX_RX_PKT_CSUMMED;
> -			fallthrough;
> +			break;
>  		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
>  		case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
>  			break;
> diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
> index 307f0ac1287b..95aeffe7482b 100644
> --- a/drivers/net/phy/adin.c
> +++ b/drivers/net/phy/adin.c
> @@ -366,10 +366,9 @@ static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval)
>  
>  	switch (tx_interval) {
>  	case 1000: /* 1 second */
> -		fallthrough;
>  	case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
>  		val |= ADIN1300_NRG_PD_TX_EN;
> -		fallthrough;
> +		break;
>  	case ETHTOOL_PHY_EDPD_NO_TX:
>  		break;
>  	default:
> diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
> index e92cb51a2c77..9adb26ee4a86 100644
> --- a/drivers/net/usb/pegasus.c
> +++ b/drivers/net/usb/pegasus.c
> @@ -627,10 +627,10 @@ static void write_bulk_callback(struct urb *urb)
>  	case -ESHUTDOWN:
>  		netif_dbg(pegasus, ifdown, net, "tx unlink, %d\n", status);
>  		return;
> +	case 0:
> +		break;
>  	default:
>  		netif_info(pegasus, tx_err, net, "TX status %d\n", status);
> -		fallthrough;
> -	case 0:
>  		break;
>  	}
>  
> diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
> index 2b2a841cd938..56edd8c9819e 100644
> --- a/drivers/net/usb/usbnet.c
> +++ b/drivers/net/usb/usbnet.c
> @@ -110,7 +110,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
>  				if (!usb_endpoint_dir_in(&e->desc))
>  					continue;
>  				intr = 1;
> -				fallthrough;
> +				break;
>  			case USB_ENDPOINT_XFER_BULK:
>  				break;
>  			default:
> diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
> index 1fbc2c19848f..f5ea317f2a67 100644
> --- a/drivers/net/wireless/ath/ath5k/eeprom.c
> +++ b/drivers/net/wireless/ath/ath5k/eeprom.c
> @@ -1178,7 +1178,7 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
>  			offset += ath5k_pdgains_size_2413(ee,
>  					AR5K_EEPROM_MODE_11A) +
>  					AR5K_EEPROM_N_5GHZ_CHAN / 2;
> -		fallthrough;
> +		break;
>  	case AR5K_EEPROM_MODE_11A:
>  		break;
>  	default:
> diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
> index 09f931d4598c..778be26d329f 100644
> --- a/drivers/net/wireless/mediatek/mt7601u/dma.c
> +++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
> @@ -193,11 +193,11 @@ static void mt7601u_complete_rx(struct urb *urb)
>  	case -ESHUTDOWN:
>  	case -ENOENT:
>  		return;
> +	case 0:
> +		break;
>  	default:
>  		dev_err_ratelimited(dev->dev, "rx urb failed: %d\n",
>  				    urb->status);
> -		fallthrough;
> -	case 0:
>  		break;
>  	}
>  
> @@ -238,11 +238,11 @@ static void mt7601u_complete_tx(struct urb *urb)
>  	case -ESHUTDOWN:
>  	case -ENOENT:
>  		return;
> +	case 0:
> +		break;
>  	default:
>  		dev_err_ratelimited(dev->dev, "tx urb failed: %d\n",
>  				    urb->status);
> -		fallthrough;
> -	case 0:
>  		break;
>  	}
>  
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index ea1fa41fbba8..aea9f978861e 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -365,7 +365,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
>  		case NVME_CTRL_RESETTING:
>  		case NVME_CTRL_CONNECTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -375,7 +375,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
>  		case NVME_CTRL_NEW:
>  		case NVME_CTRL_LIVE:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -385,7 +385,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
>  		case NVME_CTRL_NEW:
>  		case NVME_CTRL_RESETTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -396,7 +396,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
>  		case NVME_CTRL_RESETTING:
>  		case NVME_CTRL_CONNECTING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -406,7 +406,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
>  		case NVME_CTRL_DELETING:
>  		case NVME_CTRL_DEAD:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> @@ -415,7 +415,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
>  		switch (old_state) {
>  		case NVME_CTRL_DELETING:
>  			changed = true;
> -			fallthrough;
> +			break;
>  		default:
>  			break;
>  		}
> diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
> index a7c7c7cd2326..d5eec00aaf97 100644
> --- a/drivers/pcmcia/db1xxx_ss.c
> +++ b/drivers/pcmcia/db1xxx_ss.c
> @@ -258,7 +258,7 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
>  		fallthrough;
>  	case 33:
>  		++v;
> -		fallthrough;
> +		break;
>  	case 0:
>  		break;
>  	default:
> @@ -273,7 +273,7 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
>  	case 33:
>  	case 50:
>  		++p;
> -		fallthrough;
> +		break;
>  	case 0:
>  		break;
>  	default:
> diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c
> index 175c4f3d7955..b847a1570ab0 100644
> --- a/drivers/power/supply/abx500_chargalg.c
> +++ b/drivers/power/supply/abx500_chargalg.c
> @@ -1419,7 +1419,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
>  		abx500_chargalg_stop_charging(di);
>  		di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
>  		abx500_chargalg_state_to(di, STATE_HANDHELD);
> -		fallthrough;
> +		break;
>  
>  	case STATE_HANDHELD:
>  		break;
> diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
> index 07992821e252..ac7871a7684b 100644
> --- a/drivers/power/supply/charger-manager.c
> +++ b/drivers/power/supply/charger-manager.c
> @@ -585,7 +585,7 @@ static int cm_get_target_status(struct charger_manager *cm)
>  	case POWER_SUPPLY_STATUS_FULL:
>  		if (is_full_charged(cm))
>  			return POWER_SUPPLY_STATUS_FULL;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
> index f8b99cb72959..65bb87cc8380 100644
> --- a/drivers/rtc/rtc-pcf85063.c
> +++ b/drivers/rtc/rtc-pcf85063.c
> @@ -353,7 +353,7 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
>  	default:
>  		dev_warn(&pcf85063->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",
>  			 load);
> -		fallthrough;
> +		break;
>  	case 7000:
>  		break;
>  	case 12500:
> diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
> index 140186fe1d1e..2741a07df692 100644
> --- a/drivers/s390/scsi/zfcp_fsf.c
> +++ b/drivers/s390/scsi/zfcp_fsf.c
> @@ -2105,7 +2105,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
>  
>  	case FSF_PORT_HANDLE_NOT_VALID:
>  		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
> -		fallthrough;
> +		break;
>  	case FSF_LUN_ALREADY_OPEN:
>  		break;
>  	case FSF_PORT_BOXED:
> diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
> index 1c617c0d5899..e8fa68d96cde 100644
> --- a/drivers/scsi/aic7xxx/aic79xx_core.c
> +++ b/drivers/scsi/aic7xxx/aic79xx_core.c
> @@ -8175,7 +8175,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
>  				if ((scb->flags & SCB_ACTIVE) == 0)
>  					printk("Inactive SCB in qinfifo\n");
>  				ahd_done_with_status(ahd, scb, status);
> -				fallthrough;
> +				break;
>  			case SEARCH_REMOVE:
>  				break;
>  			case SEARCH_PRINT:
> @@ -8295,7 +8295,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
>  			}
>  			case SEARCH_PRINT:
>  				printk(" 0x%x", SCB_GET_TAG(scb));
> -				fallthrough;
> +				break;
>  			case SEARCH_COUNT:
>  				break;
>  			}
> diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
> index 0eb6e206a2b4..fdd0f34fcb17 100644
> --- a/drivers/scsi/aic94xx/aic94xx_tmf.c
> +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
> @@ -490,7 +490,7 @@ int asd_abort_task(struct sas_task *task)
>  		switch (tcs.dl_opcode) {
>  		default:
>  			res = asd_clear_nexus(task);
> -			fallthrough;
> +			break;
>  		case TC_NO_ERROR:
>  			break;
>  			/* The task hasn't been sent to the device xor
> diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
> index e158cd77d387..253a4a41ebc9 100644
> --- a/drivers/scsi/lpfc/lpfc_sli.c
> +++ b/drivers/scsi/lpfc/lpfc_sli.c
> @@ -9339,7 +9339,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number,
>  			 */
>  			if (piocb->iocb_cmpl)
>  				piocb->iocb_cmpl = NULL;
> -			fallthrough;
> +			break;
>  		case CMD_CREATE_XRI_CR:
>  		case CMD_CLOSE_XRI_CN:
>  		case CMD_CLOSE_XRI_CX:
> diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
> index 9d0229656681..f2be6feea226 100644
> --- a/drivers/scsi/smartpqi/smartpqi_init.c
> +++ b/drivers/scsi/smartpqi/smartpqi_init.c
> @@ -2937,7 +2937,7 @@ static int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info, struct pqi_queue
>  		case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS:
>  			if (io_request->scmd)
>  				io_request->scmd->result = 0;
> -			fallthrough;
> +			break;
>  		case PQI_RESPONSE_IU_GENERAL_MANAGEMENT:
>  			break;
>  		case PQI_RESPONSE_IU_VENDOR_GENERAL:
> diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
> index 3b3a53c6a0de..1216396284f9 100644
> --- a/drivers/scsi/sr.c
> +++ b/drivers/scsi/sr.c
> @@ -880,7 +880,7 @@ static void get_sectorsize(struct scsi_cd *cd)
>  			fallthrough;
>  		case 2048:
>  			cd->capacity *= 4;
> -			fallthrough;
> +			break;
>  		case 512:
>  			break;
>  		default:
> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
> index 319e5ceb6130..de3fbdcfa7f8 100644
> --- a/drivers/tty/serial/sunsu.c
> +++ b/drivers/tty/serial/sunsu.c
> @@ -514,7 +514,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break)
>  			switch (ret) {
>  			case 2:
>  				sunsu_change_mouse_baud(up);
> -				fallthrough;
> +				break;
>  			case 1:
>  				break;
>  
> diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
> index 001e19d7c17d..a1f5c73be291 100644
> --- a/drivers/tty/serial/sunzilog.c
> +++ b/drivers/tty/serial/sunzilog.c
> @@ -306,7 +306,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
>  		switch (ret) {
>  		case 2:
>  			sunzilog_change_mouse_baud(up);
> -			fallthrough;
> +			break;
>  		case 1:
>  			break;
>  
> diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
> index 2ea76a09e07f..c7ca691f1d2b 100644
> --- a/drivers/tty/vt/vt_ioctl.c
> +++ b/drivers/tty/vt/vt_ioctl.c
> @@ -255,7 +255,7 @@ static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
>  	case KD_TEXT0:
>  	case KD_TEXT1:
>  		mode = KD_TEXT;
> -		fallthrough;
> +		break;
>  	case KD_TEXT:
>  		break;
>  	default:
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 2eb34c8b4065..85f04dca7ae9 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -646,7 +646,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
>  			if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
>  				break;
>  		}
> -		fallthrough;
> +		break;
>  	case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
>  	default:
>  		break;
> diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
> index 1b430b36d0a6..261ec2dd52c6 100644
> --- a/drivers/usb/gadget/legacy/inode.c
> +++ b/drivers/usb/gadget/legacy/inode.c
> @@ -1717,7 +1717,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
>  	case STATE_DEV_UNCONNECTED:
>  		next_event (dev, GADGETFS_SUSPEND);
>  		ep0_readable (dev);
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
> index 10324a7334fe..a5a754ba6bc9 100644
> --- a/drivers/usb/gadget/udc/pxa25x_udc.c
> +++ b/drivers/usb/gadget/udc/pxa25x_udc.c
> @@ -2340,12 +2340,12 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
>  	case PXA250_A0:
>  	case PXA250_A1:
>  		/* A0/A1 "not released"; ep 13, 15 unusable */
> -		fallthrough;
> +		break;
>  	case PXA250_B2: case PXA210_B2:
>  	case PXA250_B1: case PXA210_B1:
>  	case PXA250_B0: case PXA210_B0:
>  		/* OUT-DMA is broken ... */
> -		fallthrough;
> +		break;
>  	case PXA250_C0: case PXA210_C0:
>  		break;
>  #elif	defined(CONFIG_ARCH_IXP4XX)
> diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
> index dd37e77dae00..9ea59b99535e 100644
> --- a/drivers/usb/host/ohci-hcd.c
> +++ b/drivers/usb/host/ohci-hcd.c
> @@ -1051,7 +1051,7 @@ int ohci_restart(struct ohci_hcd *ohci)
>  			ed->ed_next = ohci->ed_rm_list;
>  			ed->ed_prev = NULL;
>  			ohci->ed_rm_list = ed;
> -			fallthrough;
> +			break;
>  		case ED_UNLINK:
>  			break;
>  		default:
> diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c
> index dd74ab7a2f9c..30c168bccf70 100644
> --- a/drivers/usb/isp1760/isp1760-hcd.c
> +++ b/drivers/usb/isp1760/isp1760-hcd.c
> @@ -792,7 +792,7 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh,
>  				case OUT_PID:
>  					qtd->urb->actual_length +=
>  							qtd->actual_length;
> -					fallthrough;
> +					break;
>  				case SETUP_PID:
>  					break;
>  				}
> diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
> index edb5b63d7063..a066aec2b4c1 100644
> --- a/drivers/usb/musb/cppi_dma.c
> +++ b/drivers/usb/musb/cppi_dma.c
> @@ -975,7 +975,7 @@ static int cppi_channel_program(struct dma_channel *ch,
>  		musb_dbg(musb, "%cX DMA%d not allocated!",
>  				cppi_ch->transmit ? 'T' : 'R',
>  				cppi_ch->index);
> -		fallthrough;
> +		break;
>  	case MUSB_DMA_STATUS_FREE:
>  		break;
>  	}
> diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
> index f34c9437a182..d5c3b548aa51 100644
> --- a/drivers/usb/phy/phy-fsl-usb.c
> +++ b/drivers/usb/phy/phy-fsl-usb.c
> @@ -914,7 +914,7 @@ int usb_otg_start(struct platform_device *pdev)
>  		fallthrough;
>  	case FSL_USB2_PHY_UTMI:
>  		temp |= PORTSC_PTS_UTMI;
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c
> index 265865610edc..aae5ca0b89c9 100644
> --- a/drivers/video/fbdev/stifb.c
> +++ b/drivers/video/fbdev/stifb.c
> @@ -1157,7 +1157,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
>  			dev_name);
>  		   goto out_err0;
>  		}
> -		fallthrough;
> +		break;
>  	case S9000_ID_ARTIST:
>  	case S9000_ID_HCRX:
>  	case S9000_ID_TIMBER:
> diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
> index 3b1239b7e90d..6be481a98097 100644
> --- a/fs/afs/yfsclient.c
> +++ b/fs/afs/yfsclient.c
> @@ -461,7 +461,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
>  		req->file_size = vp->scb.status.size;
>  
>  		call->unmarshall++;
> -		fallthrough;
> +		break;
>  
>  	case 5:
>  		break;
> @@ -1363,7 +1363,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
>  		_debug("motd '%s'", p);
>  
>  		call->unmarshall++;
> -		fallthrough;
> +		break;
>  
>  	case 8:
>  		break;
> @@ -1727,7 +1727,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
>  		xdr_decode_YFSVolSync(&bp, &op->volsync);
>  
>  		call->unmarshall++;
> -		fallthrough;
> +		break;
>  
>  	case 6:
>  		break;
> @@ -1886,7 +1886,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
>  		xdr_decode_YFSVolSync(&bp, &op->volsync);
>  
>  		call->unmarshall++;
> -		fallthrough;
> +		break;
>  
>  	case 6:
>  		break;
> diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
> index d72e4a12bb69..67c3005fb88d 100644
> --- a/fs/ceph/dir.c
> +++ b/fs/ceph/dir.c
> @@ -1740,7 +1740,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
>  			case -ENOENT:
>  				if (d_really_is_negative(dentry))
>  					valid = 1;
> -				fallthrough;
> +				break;
>  			default:
>  				break;
>  			}
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 6e95c85fe395..4bf60dcf13e1 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -9444,7 +9444,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
>  		fallthrough;
>  	default:
>  		task->tk_status = 0;
> -		fallthrough;
> +		break;
>  	case 0:
>  		break;
>  	case -NFS4ERR_DELAY:
> diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
> index d056ad2fdefd..009c1e434aa5 100644
> --- a/fs/nfs_common/nfsacl.c
> +++ b/fs/nfs_common/nfsacl.c
> @@ -237,7 +237,7 @@ posix_acl_from_nfsacl(struct posix_acl *acl)
>  				break;
>  			case ACL_MASK:
>  				mask = pa;
> -				fallthrough;
> +				break;
>  			case ACL_OTHER:
>  				break;
>  		}
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 86fdebb5ffd8..c88c7a7d77fb 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -5334,7 +5334,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
>  				off_reg == dst_reg ? dst : src);
>  			return -EACCES;
>  		}
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
> index da3cd60e4b78..c6c8699f466c 100644
> --- a/kernel/sched/topology.c
> +++ b/kernel/sched/topology.c
> @@ -1233,7 +1233,7 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
>  		fallthrough;
>  	case sa_sd_storage:
>  		__sdt_free(cpu_map);
> -		fallthrough;
> +		break;
>  	case sa_none:
>  		break;
>  	}
> diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
> index 78a678eeb140..52df27e45843 100644
> --- a/kernel/trace/trace_events_filter.c
> +++ b/kernel/trace/trace_events_filter.c
> @@ -1273,7 +1273,7 @@ static int parse_pred(const char *str, void *data,
>  		switch (op) {
>  		case OP_NE:
>  			pred->not = 1;
> -			fallthrough;
> +			break;
>  		case OP_GLOB:
>  		case OP_EQ:
>  			break;
> diff --git a/net/dccp/output.c b/net/dccp/output.c
> index 50e6d5699bb2..5a4dbd7cee32 100644
> --- a/net/dccp/output.c
> +++ b/net/dccp/output.c
> @@ -62,7 +62,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
>  		switch (dcb->dccpd_type) {
>  		case DCCP_PKT_DATA:
>  			set_ack = 0;
> -			fallthrough;
> +			break;
>  		case DCCP_PKT_DATAACK:
>  		case DCCP_PKT_RESET:
>  			break;
> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> index 825e381e9909..3cf38c0bedf3 100644
> --- a/net/ipv4/ip_output.c
> +++ b/net/ipv4/ip_output.c
> @@ -333,7 +333,7 @@ static int ip_mc_finish_output(struct net *net, struct sock *sk,
>  	switch (ret) {
>  	case NET_XMIT_CN:
>  		do_cn = true;
> -		fallthrough;
> +		break;
>  	case NET_XMIT_SUCCESS:
>  		break;
>  	default:
> diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
> index 97fb6f776114..4844781699d5 100644
> --- a/net/netfilter/nf_tables_api.c
> +++ b/net/netfilter/nf_tables_api.c
> @@ -8525,7 +8525,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
>  		default:
>  			return -EINVAL;
>  		}
> -		fallthrough;
> +		break;
>  	case NFT_CONTINUE:
>  	case NFT_BREAK:
>  	case NFT_RETURN:
> diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
> index 667c44aa5a63..b654b8c65d10 100644
> --- a/net/rxrpc/input.c
> +++ b/net/rxrpc/input.c
> @@ -1101,7 +1101,7 @@ static void rxrpc_input_implicit_end_call(struct rxrpc_sock *rx,
>  	switch (READ_ONCE(call->state)) {
>  	case RXRPC_CALL_SERVER_AWAIT_ACK:
>  		rxrpc_call_completed(call);
> -		fallthrough;
> +		break;
>  	case RXRPC_CALL_COMPLETE:
>  		break;
>  	default:
> @@ -1265,7 +1265,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
>  	case RXRPC_PACKET_TYPE_ACKALL:
>  		if (sp->hdr.callNumber == 0)
>  			goto bad_message;
> -		fallthrough;
> +		break;
>  	case RXRPC_PACKET_TYPE_ABORT:
>  		break;
>  
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index 3fd06a27105d..f8ce1b3925a9 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -1030,7 +1030,7 @@ static void sctp_outq_flush_data(struct sctp_flush_ctx *ctx,
>  		if (!ctx->packet || !ctx->packet->has_cookie_echo)
>  			return;
>  
> -		fallthrough;
> +		break;
>  	case SCTP_STATE_ESTABLISHED:
>  	case SCTP_STATE_SHUTDOWN_PENDING:
>  	case SCTP_STATE_SHUTDOWN_RECEIVED:
> diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
> index 8d663e8d64c4..b35193eb9057 100644
> --- a/sound/soc/codecs/ak4613.c
> +++ b/sound/soc/codecs/ak4613.c
> @@ -457,7 +457,7 @@ static int ak4613_set_bias_level(struct snd_soc_component *component,
>  		fallthrough;
>  	case SND_SOC_BIAS_STANDBY:
>  		mgmt1 |= PMVR;
> -		fallthrough;
> +		break;
>  	case SND_SOC_BIAS_OFF:
>  	default:
>  		break;
> diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c
> index 298689a07168..734cf7809b7e 100644
> --- a/sound/soc/codecs/jz4770.c
> +++ b/sound/soc/codecs/jz4770.c
> @@ -202,7 +202,7 @@ static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
>  				   REG_CR_VIC_SB_SLEEP, REG_CR_VIC_SB_SLEEP);
>  		regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
>  				   REG_CR_VIC_SB, REG_CR_VIC_SB);
> -		fallthrough;
> +		break;
>  	default:
>  		break;
>  	}
> 
> 


From mchehab+huawei at kernel.org  Thu Sep 10 02:28:12 2020
From: mchehab+huawei at kernel.org (Mauro Carvalho Chehab)
Date: Thu, 10 Sep 2020 08:28:12 +0200
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <20200910082812.057a04e6@coco.lan>

Em Wed, 09 Sep 2020 13:06:39 -0700
Joe Perches <joe at perches.com> escreveu:

> fallthrough to a separate case/default label break; isn't very readable.
> 
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
> 
> Found using:
> 
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> 
> Miscellanea:
> 
> o Move or coalesce a couple label blocks above a default: block.
> 
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
> 
> Compiled allyesconfig x86-64 only.
> A few files for other arches were not compiled.
> 


>  drivers/media/dvb-frontends/drxd_hard.c                   |  2 +-
>  drivers/media/i2c/ov5640.c                                |  2 +-
>  drivers/media/i2c/ov6650.c                                |  5 ++---
>  drivers/media/i2c/smiapp/smiapp-core.c                    |  2 +-
>  drivers/media/i2c/tvp5150.c                               |  2 +-
>  drivers/media/pci/ddbridge/ddbridge-core.c                |  2 +-
>  drivers/media/usb/cpia2/cpia2_core.c                      |  2 +-

For media drivers:

Reviewed-by: Mauro Carvalho Chehab <mchehab+huawei at kernel.org>


Thanks,
Mauro


From balbi at kernel.org  Thu Sep 10 04:47:27 2020
From: balbi at kernel.org (Felipe Balbi)
Date: Thu, 10 Sep 2020 11:47:27 +0300
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <878sdikogw.fsf@kernel.org>

Hi,

Joe Perches <joe at perches.com> writes:
>  drivers/usb/dwc3/core.c                                   |  2 +-
>  drivers/usb/gadget/legacy/inode.c                         |  2 +-
>  drivers/usb/gadget/udc/pxa25x_udc.c                       |  4 ++--
>  drivers/usb/phy/phy-fsl-usb.c                             |  2 +-

for the drivers above:

Acked-by: Felipe Balbi <balbi at kernel.org>

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 857 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-afs/attachments/20200910/60c0c7ad/attachment-0001.sig>

From joe at perches.com  Wed Sep  9 16:06:39 2020
From: joe at perches.com (Joe Perches)
Date: Wed, 09 Sep 2020 13:06:39 -0700
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to break;
Message-ID: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>

fallthrough to a separate case/default label break; isn't very readable.

Convert pseudo-keyword fallthrough; statements to a simple break; when
the next label is case or default and the only statement in the next
label block is break;

Found using:

$ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *

Miscellanea:

o Move or coalesce a couple label blocks above a default: block.

Signed-off-by: Joe Perches <joe at perches.com>
---

Compiled allyesconfig x86-64 only.
A few files for other arches were not compiled.

 arch/arm/mach-mmp/pm-pxa910.c                             |  2 +-
 arch/arm64/kvm/handle_exit.c                              |  2 +-
 arch/mips/kernel/cpu-probe.c                              |  2 +-
 arch/mips/math-emu/cp1emu.c                               |  2 +-
 arch/s390/pci/pci.c                                       |  2 +-
 crypto/tcrypt.c                                           |  4 ++--
 drivers/ata/sata_mv.c                                     |  2 +-
 drivers/atm/lanai.c                                       |  2 +-
 drivers/gpu/drm/i915/display/intel_sprite.c               |  2 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c           |  2 +-
 drivers/hid/wacom_wac.c                                   |  2 +-
 drivers/i2c/busses/i2c-i801.c                             |  2 +-
 drivers/infiniband/ulp/rtrs/rtrs-clt.c                    | 14 +++++++-------
 drivers/infiniband/ulp/rtrs/rtrs-srv.c                    |  6 +++---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c               |  2 +-
 drivers/irqchip/irq-vic.c                                 |  4 ++--
 drivers/md/dm.c                                           |  2 +-
 drivers/media/dvb-frontends/drxd_hard.c                   |  2 +-
 drivers/media/i2c/ov5640.c                                |  2 +-
 drivers/media/i2c/ov6650.c                                |  5 ++---
 drivers/media/i2c/smiapp/smiapp-core.c                    |  2 +-
 drivers/media/i2c/tvp5150.c                               |  2 +-
 drivers/media/pci/ddbridge/ddbridge-core.c                |  2 +-
 drivers/media/usb/cpia2/cpia2_core.c                      |  2 +-
 drivers/mfd/iqs62x.c                                      |  3 +--
 drivers/mmc/host/atmel-mci.c                              |  2 +-
 drivers/mtd/nand/raw/nandsim.c                            |  2 +-
 drivers/net/ethernet/intel/e1000e/phy.c                   |  2 +-
 drivers/net/ethernet/intel/fm10k/fm10k_pf.c               |  2 +-
 drivers/net/ethernet/intel/i40e/i40e_adminq.c             |  2 +-
 drivers/net/ethernet/intel/i40e/i40e_txrx.c               |  2 +-
 drivers/net/ethernet/intel/iavf/iavf_txrx.c               |  2 +-
 drivers/net/ethernet/intel/igb/e1000_phy.c                |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c            |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c             |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c            |  2 +-
 drivers/net/ethernet/intel/ixgbevf/vf.c                   |  2 +-
 drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c |  2 +-
 drivers/net/ethernet/qlogic/qed/qed_mcp.c                 |  2 +-
 drivers/net/ethernet/sfc/falcon/farch.c                   |  2 +-
 drivers/net/ethernet/sfc/farch.c                          |  2 +-
 drivers/net/phy/adin.c                                    |  3 +--
 drivers/net/usb/pegasus.c                                 |  4 ++--
 drivers/net/usb/usbnet.c                                  |  2 +-
 drivers/net/wireless/ath/ath5k/eeprom.c                   |  2 +-
 drivers/net/wireless/mediatek/mt7601u/dma.c               |  8 ++++----
 drivers/nvme/host/core.c                                  | 12 ++++++------
 drivers/pcmcia/db1xxx_ss.c                                |  4 ++--
 drivers/power/supply/abx500_chargalg.c                    |  2 +-
 drivers/power/supply/charger-manager.c                    |  2 +-
 drivers/rtc/rtc-pcf85063.c                                |  2 +-
 drivers/s390/scsi/zfcp_fsf.c                              |  2 +-
 drivers/scsi/aic7xxx/aic79xx_core.c                       |  4 ++--
 drivers/scsi/aic94xx/aic94xx_tmf.c                        |  2 +-
 drivers/scsi/lpfc/lpfc_sli.c                              |  2 +-
 drivers/scsi/smartpqi/smartpqi_init.c                     |  2 +-
 drivers/scsi/sr.c                                         |  2 +-
 drivers/tty/serial/sunsu.c                                |  2 +-
 drivers/tty/serial/sunzilog.c                             |  2 +-
 drivers/tty/vt/vt_ioctl.c                                 |  2 +-
 drivers/usb/dwc3/core.c                                   |  2 +-
 drivers/usb/gadget/legacy/inode.c                         |  2 +-
 drivers/usb/gadget/udc/pxa25x_udc.c                       |  4 ++--
 drivers/usb/host/ohci-hcd.c                               |  2 +-
 drivers/usb/isp1760/isp1760-hcd.c                         |  2 +-
 drivers/usb/musb/cppi_dma.c                               |  2 +-
 drivers/usb/phy/phy-fsl-usb.c                             |  2 +-
 drivers/video/fbdev/stifb.c                               |  2 +-
 fs/afs/yfsclient.c                                        |  8 ++++----
 fs/ceph/dir.c                                             |  2 +-
 fs/nfs/nfs4proc.c                                         |  2 +-
 fs/nfs_common/nfsacl.c                                    |  2 +-
 kernel/bpf/verifier.c                                     |  2 +-
 kernel/sched/topology.c                                   |  2 +-
 kernel/trace/trace_events_filter.c                        |  2 +-
 net/dccp/output.c                                         |  2 +-
 net/ipv4/ip_output.c                                      |  2 +-
 net/netfilter/nf_tables_api.c                             |  2 +-
 net/rxrpc/input.c                                         |  4 ++--
 net/sctp/outqueue.c                                       |  2 +-
 sound/soc/codecs/ak4613.c                                 |  2 +-
 sound/soc/codecs/jz4770.c                                 |  2 +-
 82 files changed, 109 insertions(+), 112 deletions(-)

diff --git a/arch/arm/mach-mmp/pm-pxa910.c b/arch/arm/mach-mmp/pm-pxa910.c
index 1d71d73c1862..dcf2482a9e6c 100644
--- a/arch/arm/mach-mmp/pm-pxa910.c
+++ b/arch/arm/mach-mmp/pm-pxa910.c
@@ -161,7 +161,7 @@ void pxa910_pm_enter_lowpower_mode(int state)
 		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN;
 		idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
 			| APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
-		fallthrough;
+		break;
 	case POWER_MODE_CORE_INTIDLE:
 		break;
 	}
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 5d690d60ccad..bf3d54b0a233 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -128,7 +128,7 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
 	switch (ESR_ELx_EC(esr)) {
 	case ESR_ELx_EC_WATCHPT_LOW:
 		run->debug.arch.far = vcpu->arch.fault.far_el2;
-		fallthrough;
+		break;
 	case ESR_ELx_EC_SOFTSTP_LOW:
 	case ESR_ELx_EC_BREAKPT_LOW:
 	case ESR_ELx_EC_BKPT32:
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e2955f1f6316..6ddc70211a0f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1823,7 +1823,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 		fallthrough;
 	case CPU_I6400:
 		c->options |= MIPS_CPU_SHARED_FTLB_RAM;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 587cf1d115e8..9c8f8539ec5d 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1224,7 +1224,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			case bctl_op:
 				if (cpu_has_mips_2_3_4_5_r)
 					likely = 1;
-				fallthrough;
+				break;
 			case bct_op:
 				break;
 			}
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 4b62d6b55024..5b1e412bbd32 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -743,7 +743,7 @@ void zpci_release_device(struct kref *kref)
 		zpci_cleanup_bus_resources(zdev);
 		zpci_bus_device_unregister(zdev);
 		zpci_destroy_iommu(zdev);
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index eea0f453cfb6..8aac5bc60f4c 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -2464,7 +2464,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
 		test_hash_speed("streebog512", sec,
 				generic_hash_speed_template);
 		if (mode > 300 && mode < 400) break;
-		fallthrough;
+		break;
 	case 399:
 		break;
 
@@ -2587,7 +2587,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
 		test_mb_ahash_speed("streebog512", sec,
 				    generic_hash_speed_template, num_mb);
 		if (mode > 400 && mode < 500) break;
-		fallthrough;
+		break;
 	case 499:
 		break;
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 664ef658a955..4d6cce2352bd 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -2044,7 +2044,7 @@ static enum ata_completion_errors mv_qc_prep(struct ata_queued_cmd *qc)
 	case ATA_PROT_DMA:
 		if (tf->command == ATA_CMD_DSM)
 			return AC_ERR_OK;
-		fallthrough;
+		break;
 	case ATA_PROT_NCQ:
 		break;	/* continue below */
 	case ATA_PROT_PIO:
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index ac811cfa6843..972a6837a20e 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -2019,7 +2019,7 @@ static int lanai_normalize_ci(struct lanai_dev *lanai,
 	switch (*vpip) {
 		case ATM_VPI_ANY:
 			*vpip = 0;
-			fallthrough;
+			break;
 		case 0:
 			break;
 		default:
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 5ac0dbf0e03d..35ac539cc2b1 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -2861,7 +2861,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
 		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
 			return false;
-		fallthrough;
+		break;
 	case DRM_FORMAT_MOD_LINEAR:
 	case I915_FORMAT_MOD_X_TILED:
 	case I915_FORMAT_MOD_Y_TILED:
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
index 1ccfc8314812..bc83cf098e25 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c
@@ -71,7 +71,7 @@ void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
 		fallthrough;
 	case 1:
 		header |= raw_frame[0];
-		fallthrough;
+		break;
 	case 0:
 		break;
 	}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 83dfec327c42..822dc15b59b6 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3833,7 +3833,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
 	case MTTPC_B:
 	case TABLETPC2FG:
 		input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT);
-		fallthrough;
+		break;
 
 	case TABLETPC:
 	case TABLETPCE:
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index e32ef3f01fe8..b13b1cbcac29 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -1785,7 +1785,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		fallthrough;
 	case PCI_DEVICE_ID_INTEL_82801CA_3:
 		priv->features |= FEATURE_HOST_NOTIFY;
-		fallthrough;
+		break;
 	case PCI_DEVICE_ID_INTEL_82801BA_2:
 	case PCI_DEVICE_ID_INTEL_82801AB_3:
 	case PCI_DEVICE_ID_INTEL_82801AA_3:
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index 776e89231c52..55339cad408a 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -209,7 +209,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		switch (old_state) {
 		case RTRS_CLT_RECONNECTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -220,7 +220,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		case RTRS_CLT_CONNECTING_ERR:
 		case RTRS_CLT_CLOSED:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -229,7 +229,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		switch (old_state) {
 		case RTRS_CLT_CONNECTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -238,7 +238,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		switch (old_state) {
 		case RTRS_CLT_CONNECTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -250,7 +250,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		case RTRS_CLT_RECONNECTING:
 		case RTRS_CLT_CONNECTED:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -259,7 +259,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		switch (old_state) {
 		case RTRS_CLT_CLOSING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -268,7 +268,7 @@ static bool __rtrs_clt_change_state(struct rtrs_clt_sess *sess,
 		switch (old_state) {
 		case RTRS_CLT_CLOSED:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index b61a18e57aeb..24e53b39a79c 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -78,7 +78,7 @@ static bool __rtrs_srv_change_state(struct rtrs_srv_sess *sess,
 		switch (old_state) {
 		case RTRS_SRV_CONNECTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -88,7 +88,7 @@ static bool __rtrs_srv_change_state(struct rtrs_srv_sess *sess,
 		case RTRS_SRV_CONNECTING:
 		case RTRS_SRV_CONNECTED:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -97,7 +97,7 @@ static bool __rtrs_srv_change_state(struct rtrs_srv_sess *sess,
 		switch (old_state) {
 		case RTRS_SRV_CLOSING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index c192544e874b..743db1abec40 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3777,7 +3777,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 	switch (FIELD_GET(IDR0_TTF, reg)) {
 	case IDR0_TTF_AARCH32_64:
 		smmu->ias = 40;
-		fallthrough;
+		break;
 	case IDR0_TTF_AARCH64:
 		break;
 	default:
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index e46036374227..10ff0a5c225a 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -453,10 +453,10 @@ static void __init __vic_init(void __iomem *base, int parent_irq, int irq_start,
 	case AMBA_VENDOR_ST:
 		vic_init_st(base, irq_start, vic_sources, node);
 		return;
+	case AMBA_VENDOR_ARM:
+		break;
 	default:
 		printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
-		fallthrough;
-	case AMBA_VENDOR_ARM:
 		break;
 	}
 
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 3dedd9cc4fb6..dc71573d5b09 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1021,7 +1021,7 @@ static void clone_endio(struct bio *bio)
 		switch (r) {
 		case DM_ENDIO_REQUEUE:
 			error = BLK_STS_DM_REQUEUE;
-			fallthrough;
+			break;
 		case DM_ENDIO_DONE:
 			break;
 		case DM_ENDIO_INCOMPLETE:
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
index 45f982863904..d6592e764a92 100644
--- a/drivers/media/dvb-frontends/drxd_hard.c
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -1519,7 +1519,7 @@ static int SetDeviceTypeId(struct drxd_state *state)
 				break;
 			case 6:
 				state->diversity = 1;
-				fallthrough;
+				break;
 			case 5:
 			case 8:
 				break;
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 637687d761f2..855d3aba711a 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -3010,7 +3010,7 @@ static int ov5640_probe(struct i2c_client *client)
 		switch (rotation) {
 		case 180:
 			sensor->upside_down = true;
-			fallthrough;
+			break;
 		case 0:
 			break;
 		default:
diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
index d73f9f540932..fde56572dce8 100644
--- a/drivers/media/i2c/ov6650.c
+++ b/drivers/media/i2c/ov6650.c
@@ -685,17 +685,16 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd,
 	switch (mf->code) {
 	case MEDIA_BUS_FMT_Y10_1X10:
 		mf->code = MEDIA_BUS_FMT_Y8_1X8;
-		fallthrough;
+		break;
 	case MEDIA_BUS_FMT_Y8_1X8:
 	case MEDIA_BUS_FMT_YVYU8_2X8:
 	case MEDIA_BUS_FMT_YUYV8_2X8:
 	case MEDIA_BUS_FMT_VYUY8_2X8:
 	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
 		break;
 	default:
 		mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
-		fallthrough;
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
 		break;
 	}
 
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 6fc0680a93d0..8bfba407b8f1 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2795,7 +2795,7 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
 		case 180:
 			hwcfg->module_board_orient =
 				SMIAPP_MODULE_BOARD_ORIENT_180;
-			fallthrough;
+			break;
 		case 0:
 			break;
 		default:
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 7d9401219a3a..df174089e74d 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -293,7 +293,7 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
 	switch (decoder->input) {
 	case TVP5150_COMPOSITE1:
 		input |= 2;
-		fallthrough;
+		break;
 	case TVP5150_COMPOSITE0:
 		break;
 	case TVP5150_SVIDEO:
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 92fe051c672f..426c9e0152d8 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1336,7 +1336,7 @@ static void dvb_input_detach(struct ddb_input *input)
 		fallthrough;
 	case 0x10:
 		dvb_dmx_release(&dvb->demux);
-		fallthrough;
+		break;
 	case 0x01:
 		break;
 	}
diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c
index e747548ab286..cbef274d4f95 100644
--- a/drivers/media/usb/cpia2/cpia2_core.c
+++ b/drivers/media/usb/cpia2/cpia2_core.c
@@ -1751,7 +1751,7 @@ int cpia2_set_fps(struct camera_data *cam, int framerate)
 						    CPIA2_VP_SENSOR_FLAGS_500) {
 				return -EINVAL;
 			}
-			fallthrough;
+			break;
 		case CPIA2_VP_FRAMERATE_15:
 		case CPIA2_VP_FRAMERATE_12_5:
 		case CPIA2_VP_FRAMERATE_7_5:
diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c
index 761b4ef3a381..5671482ec8fe 100644
--- a/drivers/mfd/iqs62x.c
+++ b/drivers/mfd/iqs62x.c
@@ -490,8 +490,7 @@ static irqreturn_t iqs62x_irq(int irq, void *context)
 
 		case IQS62X_EVENT_HYST:
 			event_map[i] <<= iqs62x->dev_desc->hyst_shift;
-
-			fallthrough;
+			break;
 
 		case IQS62X_EVENT_WHEEL:
 		case IQS62X_EVENT_HALL:
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 444bd3a0a922..8324312e4f42 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -2435,7 +2435,7 @@ static void atmci_get_cap(struct atmel_mci *host)
 	case 0x100:
 		host->caps.has_bad_data_ordering = 0;
 		host->caps.need_reset_after_xfer = 0;
-		fallthrough;
+		break;
 	case 0x0:
 		break;
 	default:
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index f5a53aac3c5f..b07934247297 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -2286,7 +2286,7 @@ static int __init ns_init_module(void)
 		fallthrough;
 	case 1:
 		chip->bbt_options |= NAND_BBT_USE_FLASH;
-		fallthrough;
+		break;
 	case 0:
 		break;
 	default:
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index e11c877595fb..9fec7cc52710 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
@@ -607,7 +607,7 @@ static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
 		break;
 	case e1000_ms_auto:
 		phy_data &= ~CTL1000_ENABLE_MASTER;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
index c0780c3624c8..1c601d7464dd 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
@@ -1329,7 +1329,7 @@ static u8 fm10k_iov_supported_xcast_mode_pf(struct fm10k_vf_info *vf_info,
 	case FM10K_XCAST_MODE_NONE:
 		if (vf_flags & FM10K_VF_FLAG_NONE_CAPABLE)
 			return FM10K_XCAST_MODE_NONE;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index c897a2863e4f..857b699f02c9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -541,7 +541,7 @@ static void i40e_set_hw_flags(struct i40e_hw *hw)
 		    (aq->api_maj_ver == 1 &&
 		     aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_X722))
 			hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 91ab824926b9..ef4f3dbc7b7e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1690,7 +1690,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
 	case I40E_RX_PTYPE_INNER_PROT_UDP:
 	case I40E_RX_PTYPE_INNER_PROT_SCTP:
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
index 256fa07d54d5..c2c1ef255008 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
@@ -1007,7 +1007,7 @@ static inline void iavf_rx_checksum(struct iavf_vsi *vsi,
 	case IAVF_RX_PTYPE_INNER_PROT_UDP:
 	case IAVF_RX_PTYPE_INNER_PROT_SCTP:
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index 8c8eb82e6272..f8f7ffbc45f0 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -2621,7 +2621,7 @@ static s32 igb_set_master_slave_mode(struct e1000_hw *hw)
 		break;
 	case e1000_ms_auto:
 		phy_data &= ~CR_1000T_MS_ENABLE;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 8d3798a32f0e..1549f0342384 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -1589,7 +1589,7 @@ s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
 	case 0x0000:
 		/* Mask Flex Bytes */
 		fdirm |= IXGBE_FDIRM_FLEX;
-		fallthrough;
+		break;
 	case 0xFFFF:
 		break;
 	default:
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 0b675c34ce49..17e0fe4d380e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -5901,7 +5901,7 @@ void ixgbe_disable_tx(struct ixgbe_adapter *adapter)
 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
 				(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
 				 ~IXGBE_DMATXCTL_TE));
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 988db46bff0e..45b18708f5ed 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -1141,7 +1141,7 @@ static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter,
 		/* promisc introduced in 1.3 version */
 		if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC)
 			return -EOPNOTSUPP;
-		fallthrough;
+		break;
 	case ixgbe_mbox_api_13:
 	case ixgbe_mbox_api_14:
 		break;
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index bfe6dfcec4ab..7f14665b6bdf 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -540,7 +540,7 @@ static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode)
 		/* promisc introduced in 1.3 version */
 		if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC)
 			return -EOPNOTSUPP;
-		fallthrough;
+		break;
 	case ixgbe_mbox_api_14:
 	case ixgbe_mbox_api_13:
 		break;
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
index 252fe06f58aa..1d5b87079104 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
@@ -345,7 +345,7 @@ static int matching_bar(struct nfp_bar *bar, u32 tgt, u32 act, u32 tok,
 		baract = NFP_CPP_ACTION_RW;
 		if (act == 0)
 			act = NFP_CPP_ACTION_RW;
-		fallthrough;
+		break;
 	case NFP_PCIE_BAR_PCIE2CPP_MapType_FIXED:
 		break;
 	default:
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index cd882c453394..1bffe5cb88f4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -3546,7 +3546,7 @@ qed_mcp_resc_allocation_msg(struct qed_hwfn *p_hwfn,
 	switch (p_in_params->cmd) {
 	case DRV_MSG_SET_RESOURCE_VALUE_MSG:
 		mfw_resc_info.size = p_in_params->resc_max_val;
-		fallthrough;
+		break;
 	case DRV_MSG_GET_RESOURCE_ALLOC_MSG:
 		break;
 	default:
diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c
index fa1ade856b10..14f42c94809d 100644
--- a/drivers/net/ethernet/sfc/falcon/farch.c
+++ b/drivers/net/ethernet/sfc/falcon/farch.c
@@ -1052,7 +1052,7 @@ ef4_farch_handle_rx_event(struct ef4_channel *channel, const ef4_qword_t *event)
 			fallthrough;
 		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
 			flags |= EF4_RX_PKT_CSUMMED;
-			fallthrough;
+			break;
 		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
 		case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
 			break;
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index e004524e14a8..cea0eb822473 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -1038,7 +1038,7 @@ efx_farch_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
 			fallthrough;
 		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
 			flags |= EFX_RX_PKT_CSUMMED;
-			fallthrough;
+			break;
 		case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
 		case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
 			break;
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index 307f0ac1287b..95aeffe7482b 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -366,10 +366,9 @@ static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval)
 
 	switch (tx_interval) {
 	case 1000: /* 1 second */
-		fallthrough;
 	case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
 		val |= ADIN1300_NRG_PD_TX_EN;
-		fallthrough;
+		break;
 	case ETHTOOL_PHY_EDPD_NO_TX:
 		break;
 	default:
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index e92cb51a2c77..9adb26ee4a86 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -627,10 +627,10 @@ static void write_bulk_callback(struct urb *urb)
 	case -ESHUTDOWN:
 		netif_dbg(pegasus, ifdown, net, "tx unlink, %d\n", status);
 		return;
+	case 0:
+		break;
 	default:
 		netif_info(pegasus, tx_err, net, "TX status %d\n", status);
-		fallthrough;
-	case 0:
 		break;
 	}
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 2b2a841cd938..56edd8c9819e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -110,7 +110,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
 				if (!usb_endpoint_dir_in(&e->desc))
 					continue;
 				intr = 1;
-				fallthrough;
+				break;
 			case USB_ENDPOINT_XFER_BULK:
 				break;
 			default:
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 1fbc2c19848f..f5ea317f2a67 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -1178,7 +1178,7 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
 			offset += ath5k_pdgains_size_2413(ee,
 					AR5K_EEPROM_MODE_11A) +
 					AR5K_EEPROM_N_5GHZ_CHAN / 2;
-		fallthrough;
+		break;
 	case AR5K_EEPROM_MODE_11A:
 		break;
 	default:
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
index 09f931d4598c..778be26d329f 100644
--- a/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -193,11 +193,11 @@ static void mt7601u_complete_rx(struct urb *urb)
 	case -ESHUTDOWN:
 	case -ENOENT:
 		return;
+	case 0:
+		break;
 	default:
 		dev_err_ratelimited(dev->dev, "rx urb failed: %d\n",
 				    urb->status);
-		fallthrough;
-	case 0:
 		break;
 	}
 
@@ -238,11 +238,11 @@ static void mt7601u_complete_tx(struct urb *urb)
 	case -ESHUTDOWN:
 	case -ENOENT:
 		return;
+	case 0:
+		break;
 	default:
 		dev_err_ratelimited(dev->dev, "tx urb failed: %d\n",
 				    urb->status);
-		fallthrough;
-	case 0:
 		break;
 	}
 
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index ea1fa41fbba8..aea9f978861e 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -365,7 +365,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		case NVME_CTRL_RESETTING:
 		case NVME_CTRL_CONNECTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -375,7 +375,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		case NVME_CTRL_NEW:
 		case NVME_CTRL_LIVE:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -385,7 +385,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		case NVME_CTRL_NEW:
 		case NVME_CTRL_RESETTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -396,7 +396,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		case NVME_CTRL_RESETTING:
 		case NVME_CTRL_CONNECTING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -406,7 +406,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		case NVME_CTRL_DELETING:
 		case NVME_CTRL_DEAD:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
@@ -415,7 +415,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		switch (old_state) {
 		case NVME_CTRL_DELETING:
 			changed = true;
-			fallthrough;
+			break;
 		default:
 			break;
 		}
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index a7c7c7cd2326..d5eec00aaf97 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -258,7 +258,7 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
 		fallthrough;
 	case 33:
 		++v;
-		fallthrough;
+		break;
 	case 0:
 		break;
 	default:
@@ -273,7 +273,7 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
 	case 33:
 	case 50:
 		++p;
-		fallthrough;
+		break;
 	case 0:
 		break;
 	default:
diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c
index 175c4f3d7955..b847a1570ab0 100644
--- a/drivers/power/supply/abx500_chargalg.c
+++ b/drivers/power/supply/abx500_chargalg.c
@@ -1419,7 +1419,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
 		abx500_chargalg_stop_charging(di);
 		di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
 		abx500_chargalg_state_to(di, STATE_HANDHELD);
-		fallthrough;
+		break;
 
 	case STATE_HANDHELD:
 		break;
diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
index 07992821e252..ac7871a7684b 100644
--- a/drivers/power/supply/charger-manager.c
+++ b/drivers/power/supply/charger-manager.c
@@ -585,7 +585,7 @@ static int cm_get_target_status(struct charger_manager *cm)
 	case POWER_SUPPLY_STATUS_FULL:
 		if (is_full_charged(cm))
 			return POWER_SUPPLY_STATUS_FULL;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index f8b99cb72959..65bb87cc8380 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -353,7 +353,7 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
 	default:
 		dev_warn(&pcf85063->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",
 			 load);
-		fallthrough;
+		break;
 	case 7000:
 		break;
 	case 12500:
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 140186fe1d1e..2741a07df692 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -2105,7 +2105,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
 
 	case FSF_PORT_HANDLE_NOT_VALID:
 		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
-		fallthrough;
+		break;
 	case FSF_LUN_ALREADY_OPEN:
 		break;
 	case FSF_PORT_BOXED:
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 1c617c0d5899..e8fa68d96cde 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -8175,7 +8175,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
 				if ((scb->flags & SCB_ACTIVE) == 0)
 					printk("Inactive SCB in qinfifo\n");
 				ahd_done_with_status(ahd, scb, status);
-				fallthrough;
+				break;
 			case SEARCH_REMOVE:
 				break;
 			case SEARCH_PRINT:
@@ -8295,7 +8295,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
 			}
 			case SEARCH_PRINT:
 				printk(" 0x%x", SCB_GET_TAG(scb));
-				fallthrough;
+				break;
 			case SEARCH_COUNT:
 				break;
 			}
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 0eb6e206a2b4..fdd0f34fcb17 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -490,7 +490,7 @@ int asd_abort_task(struct sas_task *task)
 		switch (tcs.dl_opcode) {
 		default:
 			res = asd_clear_nexus(task);
-			fallthrough;
+			break;
 		case TC_NO_ERROR:
 			break;
 			/* The task hasn't been sent to the device xor
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e158cd77d387..253a4a41ebc9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -9339,7 +9339,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number,
 			 */
 			if (piocb->iocb_cmpl)
 				piocb->iocb_cmpl = NULL;
-			fallthrough;
+			break;
 		case CMD_CREATE_XRI_CR:
 		case CMD_CLOSE_XRI_CN:
 		case CMD_CLOSE_XRI_CX:
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 9d0229656681..f2be6feea226 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2937,7 +2937,7 @@ static int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info, struct pqi_queue
 		case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS:
 			if (io_request->scmd)
 				io_request->scmd->result = 0;
-			fallthrough;
+			break;
 		case PQI_RESPONSE_IU_GENERAL_MANAGEMENT:
 			break;
 		case PQI_RESPONSE_IU_VENDOR_GENERAL:
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 3b3a53c6a0de..1216396284f9 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -880,7 +880,7 @@ static void get_sectorsize(struct scsi_cd *cd)
 			fallthrough;
 		case 2048:
 			cd->capacity *= 4;
-			fallthrough;
+			break;
 		case 512:
 			break;
 		default:
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 319e5ceb6130..de3fbdcfa7f8 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -514,7 +514,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break)
 			switch (ret) {
 			case 2:
 				sunsu_change_mouse_baud(up);
-				fallthrough;
+				break;
 			case 1:
 				break;
 
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 001e19d7c17d..a1f5c73be291 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -306,7 +306,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
 		switch (ret) {
 		case 2:
 			sunzilog_change_mouse_baud(up);
-			fallthrough;
+			break;
 		case 1:
 			break;
 
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 2ea76a09e07f..c7ca691f1d2b 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -255,7 +255,7 @@ static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
 	case KD_TEXT0:
 	case KD_TEXT1:
 		mode = KD_TEXT;
-		fallthrough;
+		break;
 	case KD_TEXT:
 		break;
 	default:
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 2eb34c8b4065..85f04dca7ae9 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -646,7 +646,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
 			if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
 				break;
 		}
-		fallthrough;
+		break;
 	case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
 	default:
 		break;
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index 1b430b36d0a6..261ec2dd52c6 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1717,7 +1717,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
 	case STATE_DEV_UNCONNECTED:
 		next_event (dev, GADGETFS_SUSPEND);
 		ep0_readable (dev);
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index 10324a7334fe..a5a754ba6bc9 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -2340,12 +2340,12 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
 	case PXA250_A0:
 	case PXA250_A1:
 		/* A0/A1 "not released"; ep 13, 15 unusable */
-		fallthrough;
+		break;
 	case PXA250_B2: case PXA210_B2:
 	case PXA250_B1: case PXA210_B1:
 	case PXA250_B0: case PXA210_B0:
 		/* OUT-DMA is broken ... */
-		fallthrough;
+		break;
 	case PXA250_C0: case PXA210_C0:
 		break;
 #elif	defined(CONFIG_ARCH_IXP4XX)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index dd37e77dae00..9ea59b99535e 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1051,7 +1051,7 @@ int ohci_restart(struct ohci_hcd *ohci)
 			ed->ed_next = ohci->ed_rm_list;
 			ed->ed_prev = NULL;
 			ohci->ed_rm_list = ed;
-			fallthrough;
+			break;
 		case ED_UNLINK:
 			break;
 		default:
diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c
index dd74ab7a2f9c..30c168bccf70 100644
--- a/drivers/usb/isp1760/isp1760-hcd.c
+++ b/drivers/usb/isp1760/isp1760-hcd.c
@@ -792,7 +792,7 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh,
 				case OUT_PID:
 					qtd->urb->actual_length +=
 							qtd->actual_length;
-					fallthrough;
+					break;
 				case SETUP_PID:
 					break;
 				}
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index edb5b63d7063..a066aec2b4c1 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -975,7 +975,7 @@ static int cppi_channel_program(struct dma_channel *ch,
 		musb_dbg(musb, "%cX DMA%d not allocated!",
 				cppi_ch->transmit ? 'T' : 'R',
 				cppi_ch->index);
-		fallthrough;
+		break;
 	case MUSB_DMA_STATUS_FREE:
 		break;
 	}
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index f34c9437a182..d5c3b548aa51 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -914,7 +914,7 @@ int usb_otg_start(struct platform_device *pdev)
 		fallthrough;
 	case FSL_USB2_PHY_UTMI:
 		temp |= PORTSC_PTS_UTMI;
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c
index 265865610edc..aae5ca0b89c9 100644
--- a/drivers/video/fbdev/stifb.c
+++ b/drivers/video/fbdev/stifb.c
@@ -1157,7 +1157,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 			dev_name);
 		   goto out_err0;
 		}
-		fallthrough;
+		break;
 	case S9000_ID_ARTIST:
 	case S9000_ID_HCRX:
 	case S9000_ID_TIMBER:
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
index 3b1239b7e90d..6be481a98097 100644
--- a/fs/afs/yfsclient.c
+++ b/fs/afs/yfsclient.c
@@ -461,7 +461,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
 		req->file_size = vp->scb.status.size;
 
 		call->unmarshall++;
-		fallthrough;
+		break;
 
 	case 5:
 		break;
@@ -1363,7 +1363,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
 		_debug("motd '%s'", p);
 
 		call->unmarshall++;
-		fallthrough;
+		break;
 
 	case 8:
 		break;
@@ -1727,7 +1727,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
 		xdr_decode_YFSVolSync(&bp, &op->volsync);
 
 		call->unmarshall++;
-		fallthrough;
+		break;
 
 	case 6:
 		break;
@@ -1886,7 +1886,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
 		xdr_decode_YFSVolSync(&bp, &op->volsync);
 
 		call->unmarshall++;
-		fallthrough;
+		break;
 
 	case 6:
 		break;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index d72e4a12bb69..67c3005fb88d 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1740,7 +1740,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
 			case -ENOENT:
 				if (d_really_is_negative(dentry))
 					valid = 1;
-				fallthrough;
+				break;
 			default:
 				break;
 			}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6e95c85fe395..4bf60dcf13e1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -9444,7 +9444,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 		fallthrough;
 	default:
 		task->tk_status = 0;
-		fallthrough;
+		break;
 	case 0:
 		break;
 	case -NFS4ERR_DELAY:
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
index d056ad2fdefd..009c1e434aa5 100644
--- a/fs/nfs_common/nfsacl.c
+++ b/fs/nfs_common/nfsacl.c
@@ -237,7 +237,7 @@ posix_acl_from_nfsacl(struct posix_acl *acl)
 				break;
 			case ACL_MASK:
 				mask = pa;
-				fallthrough;
+				break;
 			case ACL_OTHER:
 				break;
 		}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 86fdebb5ffd8..c88c7a7d77fb 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5334,7 +5334,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 				off_reg == dst_reg ? dst : src);
 			return -EACCES;
 		}
-		fallthrough;
+		break;
 	default:
 		break;
 	}
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index da3cd60e4b78..c6c8699f466c 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -1233,7 +1233,7 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
 		fallthrough;
 	case sa_sd_storage:
 		__sdt_free(cpu_map);
-		fallthrough;
+		break;
 	case sa_none:
 		break;
 	}
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 78a678eeb140..52df27e45843 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1273,7 +1273,7 @@ static int parse_pred(const char *str, void *data,
 		switch (op) {
 		case OP_NE:
 			pred->not = 1;
-			fallthrough;
+			break;
 		case OP_GLOB:
 		case OP_EQ:
 			break;
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 50e6d5699bb2..5a4dbd7cee32 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -62,7 +62,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 		switch (dcb->dccpd_type) {
 		case DCCP_PKT_DATA:
 			set_ack = 0;
-			fallthrough;
+			break;
 		case DCCP_PKT_DATAACK:
 		case DCCP_PKT_RESET:
 			break;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 825e381e9909..3cf38c0bedf3 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -333,7 +333,7 @@ static int ip_mc_finish_output(struct net *net, struct sock *sk,
 	switch (ret) {
 	case NET_XMIT_CN:
 		do_cn = true;
-		fallthrough;
+		break;
 	case NET_XMIT_SUCCESS:
 		break;
 	default:
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 97fb6f776114..4844781699d5 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8525,7 +8525,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
 		default:
 			return -EINVAL;
 		}
-		fallthrough;
+		break;
 	case NFT_CONTINUE:
 	case NFT_BREAK:
 	case NFT_RETURN:
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 667c44aa5a63..b654b8c65d10 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1101,7 +1101,7 @@ static void rxrpc_input_implicit_end_call(struct rxrpc_sock *rx,
 	switch (READ_ONCE(call->state)) {
 	case RXRPC_CALL_SERVER_AWAIT_ACK:
 		rxrpc_call_completed(call);
-		fallthrough;
+		break;
 	case RXRPC_CALL_COMPLETE:
 		break;
 	default:
@@ -1265,7 +1265,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 	case RXRPC_PACKET_TYPE_ACKALL:
 		if (sp->hdr.callNumber == 0)
 			goto bad_message;
-		fallthrough;
+		break;
 	case RXRPC_PACKET_TYPE_ABORT:
 		break;
 
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 3fd06a27105d..f8ce1b3925a9 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1030,7 +1030,7 @@ static void sctp_outq_flush_data(struct sctp_flush_ctx *ctx,
 		if (!ctx->packet || !ctx->packet->has_cookie_echo)
 			return;
 
-		fallthrough;
+		break;
 	case SCTP_STATE_ESTABLISHED:
 	case SCTP_STATE_SHUTDOWN_PENDING:
 	case SCTP_STATE_SHUTDOWN_RECEIVED:
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 8d663e8d64c4..b35193eb9057 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -457,7 +457,7 @@ static int ak4613_set_bias_level(struct snd_soc_component *component,
 		fallthrough;
 	case SND_SOC_BIAS_STANDBY:
 		mgmt1 |= PMVR;
-		fallthrough;
+		break;
 	case SND_SOC_BIAS_OFF:
 	default:
 		break;
diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c
index 298689a07168..734cf7809b7e 100644
--- a/sound/soc/codecs/jz4770.c
+++ b/sound/soc/codecs/jz4770.c
@@ -202,7 +202,7 @@ static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
 				   REG_CR_VIC_SB_SLEEP, REG_CR_VIC_SB_SLEEP);
 		regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
 				   REG_CR_VIC_SB, REG_CR_VIC_SB);
-		fallthrough;
+		break;
 	default:
 		break;
 	}




From kbusch at kernel.org  Wed Sep  9 16:55:58 2020
From: kbusch at kernel.org (Keith Busch)
Date: Wed, 9 Sep 2020 13:55:58 -0700
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <20200909205558.GA3384631@dhcp-10-100-145-180.wdl.wdc.com>

On Wed, Sep 09, 2020 at 01:06:39PM -0700, Joe Perches wrote:
> diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
> index eea0f453cfb6..8aac5bc60f4c 100644
> --- a/crypto/tcrypt.c
> +++ b/crypto/tcrypt.c
> @@ -2464,7 +2464,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
>  		test_hash_speed("streebog512", sec,
>  				generic_hash_speed_template);
>  		if (mode > 300 && mode < 400) break;
> -		fallthrough;
> +		break;
>  	case 399:
>  		break;

Just imho, this change makes the preceding 'if' look even more
pointless. Maybe the fallthrough was a deliberate choice? Not that my
opinion matters here as I don't know this module, but it looked a bit
odd to me.


From jgg at ziepe.ca  Wed Sep  9 18:36:02 2020
From: jgg at ziepe.ca (Jason Gunthorpe)
Date: Wed, 9 Sep 2020 19:36:02 -0300
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <20200909223602.GJ87483@ziepe.ca>

On Wed, Sep 09, 2020 at 01:06:39PM -0700, Joe Perches wrote:
> fallthrough to a separate case/default label break; isn't very readable.
> 
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
> 
> Found using:
> 
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> 
> Miscellanea:
> 
> o Move or coalesce a couple label blocks above a default: block.
> 
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
> 
> Compiled allyesconfig x86-64 only.
> A few files for other arches were not compiled.

IB part looks OK, I prefer it like this

You could do the same for continue as well, I saw a few of those..

Thanks,
Jason


From joe at perches.com  Wed Sep  9 18:47:24 2020
From: joe at perches.com (Joe Perches)
Date: Wed, 09 Sep 2020 15:47:24 -0700
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <20200909223602.GJ87483@ziepe.ca>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
 <20200909223602.GJ87483@ziepe.ca>
Message-ID: <b3d6f71aea87f4bb88554f1a3fdaee0b2feb158c.camel@perches.com>

On Wed, 2020-09-09 at 19:36 -0300, Jason Gunthorpe wrote:
> On Wed, Sep 09, 2020 at 01:06:39PM -0700, Joe Perches wrote:
> > fallthrough to a separate case/default label break; isn't very readable.
> > 
> > Convert pseudo-keyword fallthrough; statements to a simple break; when
> > the next label is case or default and the only statement in the next
> > label block is break;
> > 
> > Found using:
> > 
> > $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> > 
> > Miscellanea:
> > 
> > o Move or coalesce a couple label blocks above a default: block.
> > 
> > Signed-off-by: Joe Perches <joe at perches.com>
> > ---
> > 
> > Compiled allyesconfig x86-64 only.
> > A few files for other arches were not compiled.
> 
> IB part looks OK, I prefer it like this
> 
> You could do the same for continue as well, I saw a few of those..

I saw some continue uses as well but wasn't sure
and didn't look to see if the switch/case with
continue was in a for/while loop.




From wsa at kernel.org  Thu Sep 10 02:53:12 2020
From: wsa at kernel.org (Wolfram Sang)
Date: Thu, 10 Sep 2020 08:53:12 +0200
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <20200910065312.GH1031@ninjato>


> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
> index e32ef3f01fe8..b13b1cbcac29 100644
> --- a/drivers/i2c/busses/i2c-i801.c
> +++ b/drivers/i2c/busses/i2c-i801.c
> @@ -1785,7 +1785,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
>  		fallthrough;
>  	case PCI_DEVICE_ID_INTEL_82801CA_3:
>  		priv->features |= FEATURE_HOST_NOTIFY;
> -		fallthrough;
> +		break;
>  	case PCI_DEVICE_ID_INTEL_82801BA_2:
>  	case PCI_DEVICE_ID_INTEL_82801AB_3:
>  	case PCI_DEVICE_ID_INTEL_82801AA_3:

I am not the maintainer (Jean is) but I suggest to drop this hunk. The
code is more complex with multiple 'fallthrough', so this change alone
actually makes the code inconsistent. A rework would need a seperate
patch.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-afs/attachments/20200910/4bdcedb4/attachment-0001.sig>

From Nicolas.Ferre at microchip.com  Thu Sep 10 04:24:21 2020
From: Nicolas.Ferre at microchip.com (Nicolas.Ferre at microchip.com)
Date: Thu, 10 Sep 2020 08:24:21 +0000
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <c2929349-ca60-486d-3cad-a83321587c5f@microchip.com>

Joe,

Please drop this chunk: it's a successive controller version number 
which are all backward compatible with "fallthrough" on each case so 
removing from this last one makes it inconsistent.

In sort: NACK for atmel-mci.

Best regards,
   Nicolas


On 09/09/2020 at 22:06, Joe Perches wrote:
> diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
> index 444bd3a0a922..8324312e4f42 100644
> --- a/drivers/mmc/host/atmel-mci.c
> +++ b/drivers/mmc/host/atmel-mci.c
> @@ -2435,7 +2435,7 @@ static void atmci_get_cap(struct atmel_mci *host)
>          case 0x100:
>                  host->caps.has_bad_data_ordering = 0;
>                  host->caps.need_reset_after_xfer = 0;
> -               fallthrough;
> +               break;
>          case 0x0:
>                  break;
>          default:


-- 
Nicolas Ferre


From maier at linux.ibm.com  Thu Sep 10 05:18:29 2020
From: maier at linux.ibm.com (Steffen Maier)
Date: Thu, 10 Sep 2020 11:18:29 +0200
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <0c66fbe5-c48b-7dc1-f7fe-1498da9cc1a3@linux.ibm.com>

On 9/9/20 10:06 PM, Joe Perches wrote:
> fallthrough to a separate case/default label break; isn't very readable.
> 
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
> 
> Found using:
> 
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> 
> Miscellanea:
> 
> o Move or coalesce a couple label blocks above a default: block.
> 
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
> 
> Compiled allyesconfig x86-64 only.
> A few files for other arches were not compiled.

>   drivers/s390/scsi/zfcp_fsf.c                              |  2 +-

>   82 files changed, 109 insertions(+), 112 deletions(-)

> diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
> index 140186fe1d1e..2741a07df692 100644
> --- a/drivers/s390/scsi/zfcp_fsf.c
> +++ b/drivers/s390/scsi/zfcp_fsf.c
> @@ -2105,7 +2105,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
>   
>   	case FSF_PORT_HANDLE_NOT_VALID:
>   		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
> -		fallthrough;
> +		break;
>   	case FSF_LUN_ALREADY_OPEN:
>   		break;
>   	case FSF_PORT_BOXED:

Acked-by: Steffen Maier <maier at linux.ibm.com> # for zfcp


-- 
Mit freundlichen Gruessen / Kind regards
Steffen Maier

Linux on IBM Z Development

https://www.ibm.com/privacy/us/en/
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Matthias Hartmann
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294


From idryomov at gmail.com  Thu Sep 10 05:24:26 2020
From: idryomov at gmail.com (Ilya Dryomov)
Date: Thu, 10 Sep 2020 11:24:26 +0200
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough;
 to break; 
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <CAOi1vP-v77pj3G5Ez94CDYVs2jSO828c4uV_wzNi6sRKp=Yvyg@mail.gmail.com>

On Wed, Sep 9, 2020 at 10:10 PM Joe Perches <joe at perches.com> wrote:
>
> fallthrough to a separate case/default label break; isn't very readable.
>
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
>
> Found using:
>
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
>
> Miscellanea:
>
> o Move or coalesce a couple label blocks above a default: block.
>
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
>
> Compiled allyesconfig x86-64 only.
> A few files for other arches were not compiled.
>
>  arch/arm/mach-mmp/pm-pxa910.c                             |  2 +-
>  arch/arm64/kvm/handle_exit.c                              |  2 +-
>  arch/mips/kernel/cpu-probe.c                              |  2 +-
>  arch/mips/math-emu/cp1emu.c                               |  2 +-
>  arch/s390/pci/pci.c                                       |  2 +-
>  crypto/tcrypt.c                                           |  4 ++--
>  drivers/ata/sata_mv.c                                     |  2 +-
>  drivers/atm/lanai.c                                       |  2 +-
>  drivers/gpu/drm/i915/display/intel_sprite.c               |  2 +-
>  drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi.c           |  2 +-
>  drivers/hid/wacom_wac.c                                   |  2 +-
>  drivers/i2c/busses/i2c-i801.c                             |  2 +-
>  drivers/infiniband/ulp/rtrs/rtrs-clt.c                    | 14 +++++++-------
>  drivers/infiniband/ulp/rtrs/rtrs-srv.c                    |  6 +++---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c               |  2 +-
>  drivers/irqchip/irq-vic.c                                 |  4 ++--
>  drivers/md/dm.c                                           |  2 +-
>  drivers/media/dvb-frontends/drxd_hard.c                   |  2 +-
>  drivers/media/i2c/ov5640.c                                |  2 +-
>  drivers/media/i2c/ov6650.c                                |  5 ++---
>  drivers/media/i2c/smiapp/smiapp-core.c                    |  2 +-
>  drivers/media/i2c/tvp5150.c                               |  2 +-
>  drivers/media/pci/ddbridge/ddbridge-core.c                |  2 +-
>  drivers/media/usb/cpia2/cpia2_core.c                      |  2 +-
>  drivers/mfd/iqs62x.c                                      |  3 +--
>  drivers/mmc/host/atmel-mci.c                              |  2 +-
>  drivers/mtd/nand/raw/nandsim.c                            |  2 +-
>  drivers/net/ethernet/intel/e1000e/phy.c                   |  2 +-
>  drivers/net/ethernet/intel/fm10k/fm10k_pf.c               |  2 +-
>  drivers/net/ethernet/intel/i40e/i40e_adminq.c             |  2 +-
>  drivers/net/ethernet/intel/i40e/i40e_txrx.c               |  2 +-
>  drivers/net/ethernet/intel/iavf/iavf_txrx.c               |  2 +-
>  drivers/net/ethernet/intel/igb/e1000_phy.c                |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c            |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c             |  2 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c            |  2 +-
>  drivers/net/ethernet/intel/ixgbevf/vf.c                   |  2 +-
>  drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c |  2 +-
>  drivers/net/ethernet/qlogic/qed/qed_mcp.c                 |  2 +-
>  drivers/net/ethernet/sfc/falcon/farch.c                   |  2 +-
>  drivers/net/ethernet/sfc/farch.c                          |  2 +-
>  drivers/net/phy/adin.c                                    |  3 +--
>  drivers/net/usb/pegasus.c                                 |  4 ++--
>  drivers/net/usb/usbnet.c                                  |  2 +-
>  drivers/net/wireless/ath/ath5k/eeprom.c                   |  2 +-
>  drivers/net/wireless/mediatek/mt7601u/dma.c               |  8 ++++----
>  drivers/nvme/host/core.c                                  | 12 ++++++------
>  drivers/pcmcia/db1xxx_ss.c                                |  4 ++--
>  drivers/power/supply/abx500_chargalg.c                    |  2 +-
>  drivers/power/supply/charger-manager.c                    |  2 +-
>  drivers/rtc/rtc-pcf85063.c                                |  2 +-
>  drivers/s390/scsi/zfcp_fsf.c                              |  2 +-
>  drivers/scsi/aic7xxx/aic79xx_core.c                       |  4 ++--
>  drivers/scsi/aic94xx/aic94xx_tmf.c                        |  2 +-
>  drivers/scsi/lpfc/lpfc_sli.c                              |  2 +-
>  drivers/scsi/smartpqi/smartpqi_init.c                     |  2 +-
>  drivers/scsi/sr.c                                         |  2 +-
>  drivers/tty/serial/sunsu.c                                |  2 +-
>  drivers/tty/serial/sunzilog.c                             |  2 +-
>  drivers/tty/vt/vt_ioctl.c                                 |  2 +-
>  drivers/usb/dwc3/core.c                                   |  2 +-
>  drivers/usb/gadget/legacy/inode.c                         |  2 +-
>  drivers/usb/gadget/udc/pxa25x_udc.c                       |  4 ++--
>  drivers/usb/host/ohci-hcd.c                               |  2 +-
>  drivers/usb/isp1760/isp1760-hcd.c                         |  2 +-
>  drivers/usb/musb/cppi_dma.c                               |  2 +-
>  drivers/usb/phy/phy-fsl-usb.c                             |  2 +-
>  drivers/video/fbdev/stifb.c                               |  2 +-
>  fs/afs/yfsclient.c                                        |  8 ++++----
>  fs/ceph/dir.c                                             |  2 +-

For ceph:

Acked-by: Ilya Dryomov <idryomov at gmail.com>

Thanks,

                Ilya


From matthias.bgg at gmail.com  Thu Sep 10 06:16:33 2020
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 10 Sep 2020 12:16:33 +0200
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <81d852d4-115f-c6c6-ef80-17c47ec4849a@gmail.com>



On 09/09/2020 22:06, Joe Perches wrote:
> diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
> index 09f931d4598c..778be26d329f 100644
> --- a/drivers/net/wireless/mediatek/mt7601u/dma.c
> +++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
> @@ -193,11 +193,11 @@ static void mt7601u_complete_rx(struct urb *urb)
>   	case -ESHUTDOWN:
>   	case -ENOENT:
>   		return;
> +	case 0:
> +		break;
>   	default:
>   		dev_err_ratelimited(dev->dev, "rx urb failed: %d\n",
>   				    urb->status);
> -		fallthrough;
> -	case 0:
>   		break;
>   	}
>   
> @@ -238,11 +238,11 @@ static void mt7601u_complete_tx(struct urb *urb)
>   	case -ESHUTDOWN:
>   	case -ENOENT:
>   		return;
> +	case 0:
> +		break;
>   	default:
>   		dev_err_ratelimited(dev->dev, "tx urb failed: %d\n",
>   				    urb->status);
> -		fallthrough;
> -	case 0:
>   		break;
>   	}

Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>


From robin.murphy at arm.com  Thu Sep 10 10:21:05 2020
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 10 Sep 2020 15:21:05 +0100
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <9372456a-8dcf-2735-57a4-e126aa5df3a6@arm.com>

On 2020-09-09 21:06, Joe Perches wrote:
> fallthrough to a separate case/default label break; isn't very readable.
> 
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
> 
> Found using:
> 
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> 
> Miscellanea:
> 
> o Move or coalesce a couple label blocks above a default: block.
> 
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
> 
> Compiled allyesconfig x86-64 only.
> A few files for other arches were not compiled.
> 

[...]
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index c192544e874b..743db1abec40 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -3777,7 +3777,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
>   	switch (FIELD_GET(IDR0_TTF, reg)) {
>   	case IDR0_TTF_AARCH32_64:
>   		smmu->ias = 40;
> -		fallthrough;
> +		break;
>   	case IDR0_TTF_AARCH64:
>   		break;
>   	default:

I have to say I don't really agree with the readability argument for 
this one - a fallthrough is semantically correct here, since the first 
case is a superset of the second. It just happens that anything we would 
do for the common subset is implicitly assumed (there are other 
potential cases we simply haven't added support for at the moment), thus 
the second case is currently empty.

This change actively obfuscates that distinction.

Robin.


From joe at perches.com  Fri Sep 11 00:19:35 2020
From: joe at perches.com (Joe Perches)
Date: Thu, 10 Sep 2020 21:19:35 -0700
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <9372456a-8dcf-2735-57a4-e126aa5df3a6@arm.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
 <9372456a-8dcf-2735-57a4-e126aa5df3a6@arm.com>
Message-ID: <f4ad706519917d493a0af32ea2da8565227cc74a.camel@perches.com>

On Thu, 2020-09-10 at 15:21 +0100, Robin Murphy wrote:
> On 2020-09-09 21:06, Joe Perches wrote:
> > fallthrough to a separate case/default label break; isn't very readable.
> > 
> > Convert pseudo-keyword fallthrough; statements to a simple break; when
> > the next label is case or default and the only statement in the next
> > label block is break;
> > 
> > Found using:
> > 
> > $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> > 
> > Miscellanea:
> > 
> > o Move or coalesce a couple label blocks above a default: block.
> > 
> > Signed-off-by: Joe Perches <joe at perches.com>
> > ---
> > 
> > Compiled allyesconfig x86-64 only.
> > A few files for other arches were not compiled.
> > 
> 
> [...]
> > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > index c192544e874b..743db1abec40 100644
> > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > @@ -3777,7 +3777,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
> >   	switch (FIELD_GET(IDR0_TTF, reg)) {
> >   	case IDR0_TTF_AARCH32_64:
> >   		smmu->ias = 40;
> > -		fallthrough;
> > +		break;
> >   	case IDR0_TTF_AARCH64:
> >   		break;
> >   	default:
> 
> I have to say I don't really agree with the readability argument for 
> this one - a fallthrough is semantically correct here, since the first 
> case is a superset of the second. It just happens that anything we would 
> do for the common subset is implicitly assumed (there are other 
> potential cases we simply haven't added support for at the moment), thus 
> the second case is currently empty.
> This change actively obfuscates that distinction.

Then perhaps comments should be added to usefully
describe the mechanisms.

	case IDR0_TTF_AARCH32_64:
		smmu->ias = 40;
		fallthrough;	/* and still do the 64 bit processing */
	case IDR0_TTF_AARCH64:
		/* Nothing specific yet */
		break;

> Robin.



From dan.carpenter at oracle.com  Fri Sep 11 07:32:56 2020
From: dan.carpenter at oracle.com (Dan Carpenter)
Date: Fri, 11 Sep 2020 14:32:56 +0300
Subject: [bug report] rxrpc: Rewrite the client connection manager
Message-ID: <20200911113256.GA367487@mwanda>

Hello David Howells,

The patch 245500d853e9: "rxrpc: Rewrite the client connection
manager" from Jul 1, 2020, leads to the following static checker
warning:

	net/rxrpc/conn_client.c:662 rxrpc_wait_for_channel()
	warn: 'bundle->alloc_error' is unsigned

net/rxrpc/conn_client.c
   414          candidate = rxrpc_alloc_client_connection(bundle, gfp);
   415  
   416          spin_lock(&bundle->channel_lock);
   417          bundle->alloc_conn = false;
   418  
   419          if (IS_ERR(candidate)) {
   420                  bundle->alloc_error = PTR_ERR(candidate);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The bundle->alloc_error variable is unsigned short so it can't hold
negative values.

   421                  spin_unlock(&bundle->channel_lock);
   422                  _leave(" [err %ld]", PTR_ERR(candidate));
   423                  return;
   424          }
   425  
   426          bundle->alloc_error = 0;
   427  
   428          for (i = 0; i < ARRAY_SIZE(bundle->conns); i++) {
   429                  unsigned int shift = i * RXRPC_MAXCALLS;

[ snip ]

   642  static int rxrpc_wait_for_channel(struct rxrpc_bundle *bundle,
   643                                    struct rxrpc_call *call, gfp_t gfp)
   644  {
   645          DECLARE_WAITQUEUE(myself, current);
   646          int ret = 0;
   647  
   648          _enter("%d", call->debug_id);
   649  
   650          if (!gfpflags_allow_blocking(gfp)) {
   651                  rxrpc_maybe_add_conn(bundle, gfp);
   652                  rxrpc_activate_channels(bundle);
   653                  ret = bundle->alloc_error ?: -EAGAIN;
   654                  goto out;
   655          }
   656  
   657          add_wait_queue_exclusive(&call->waitq, &myself);
   658          for (;;) {
   659                  rxrpc_maybe_add_conn(bundle, gfp);
   660                  rxrpc_activate_channels(bundle);
   661                  ret = bundle->alloc_error;
                        ^^^^^^^^^^^^^^^^^^^^^^^^^

   662                  if (ret < 0)
                            ^^^^^^^
Impossible condition.

   663                          break;
   664  
   665                  switch (call->interruptibility) {
   666                  case RXRPC_INTERRUPTIBLE:
   667                  case RXRPC_PREINTERRUPTIBLE:
   668                          set_current_state(TASK_INTERRUPTIBLE);
   669                          break;
   670                  case RXRPC_UNINTERRUPTIBLE:

regards,
dan carpenter


From dhowells at redhat.com  Mon Sep 14 11:30:46 2020
From: dhowells at redhat.com (David Howells)
Date: Mon, 14 Sep 2020 16:30:46 +0100
Subject: [PATCH net-next 0/5] rxrpc: Fixes for the connection manager rewrite
Message-ID: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>


Here are some fixes for the connection manager rewrite:

 (1) Fix a goto to the wrong place in error handling.

 (2) Fix a missing NULL pointer check.

 (3) The stored allocation error needs to be stored signed.

 (4) Fix a leak of connection bundle when clearing connections due to
     net namespace exit.

 (5) Fix an overget of the bundle when setting up a new client conn.

The patches are tagged here:

	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
	rxrpc-next-20200914

and can also be found on this branch:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-next

David
---
David Howells (5):
      rxrpc: Fix an error goto in rxrpc_connect_call()
      rxrpc: Fix a missing NULL-pointer check in a trace
      rxrpc: Fix rxrpc_bundle::alloc_error to be signed
      rxrpc: Fix conn bundle leak in net-namespace exit
      rxrpc: Fix an overget of the conn bundle when setting up a client conn


 include/trace/events/rxrpc.h | 2 +-
 net/rxrpc/ar-internal.h      | 2 +-
 net/rxrpc/conn_client.c      | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)




From dhowells at redhat.com  Mon Sep 14 11:30:53 2020
From: dhowells at redhat.com (David Howells)
Date: Mon, 14 Sep 2020 16:30:53 +0100
Subject: [PATCH net-next 1/5] rxrpc: Fix an error goto in rxrpc_connect_call()
In-Reply-To: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
References: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
Message-ID: <160009745364.1014072.15669282566191320805.stgit@warthog.procyon.org.uk>

Fix an error-handling goto in rxrpc_connect_call() whereby it will jump to
free the bundle it failed to allocate.

Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
Reported-by: kernel test robot <lkp at intel.com>
Reported-by: Dan Carpenter <dan.carpenter at oracle.com>
Signed-off-by: David Howells <dhowells at redhat.com>
---

 net/rxrpc/conn_client.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 0e4e1879c24d..180be4da8d26 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -724,8 +724,9 @@ int rxrpc_connect_call(struct rxrpc_sock *rx,
 	/* Paired with the write barrier in rxrpc_activate_one_channel(). */
 	smp_rmb();
 
-out:
+out_put_bundle:
 	rxrpc_put_bundle(bundle);
+out:
 	_leave(" = %d", ret);
 	return ret;
 
@@ -742,7 +743,7 @@ int rxrpc_connect_call(struct rxrpc_sock *rx,
 	trace_rxrpc_client(call->conn, ret, rxrpc_client_chan_wait_failed);
 	rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 0, ret);
 	rxrpc_disconnect_client_call(bundle, call);
-	goto out;
+	goto out_put_bundle;
 }
 
 /*




From dhowells at redhat.com  Mon Sep 14 11:31:00 2020
From: dhowells at redhat.com (David Howells)
Date: Mon, 14 Sep 2020 16:31:00 +0100
Subject: [PATCH net-next 2/5] rxrpc: Fix a missing NULL-pointer check in a
 trace
In-Reply-To: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
References: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
Message-ID: <160009746059.1014072.11451831292156673294.stgit@warthog.procyon.org.uk>

Fix the rxrpc_client tracepoint to not dereference conn to get the cid if
conn is NULL, as it does for other fields.

	RIP: 0010:trace_event_raw_event_rxrpc_client+0x7e/0xe0 [rxrpc]
	Call Trace:
	 rxrpc_activate_channels+0x62/0xb0 [rxrpc]
	 rxrpc_connect_call+0x481/0x650 [rxrpc]
	 ? wake_up_q+0xa0/0xa0
	 ? rxrpc_kernel_begin_call+0x12a/0x1b0 [rxrpc]
	 rxrpc_new_client_call+0x2a5/0x5e0 [rxrpc]

Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
Reported-by: Marc Dionne <marc.dionne at auristor.com>
Signed-off-by: David Howells <dhowells at redhat.com>
Tested-by: Marc Dionne <marc.dionne at auristor.com>
---

 include/trace/events/rxrpc.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 3b67d5981224..e70c90116eda 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -579,7 +579,7 @@ TRACE_EVENT(rxrpc_client,
 		    __entry->channel = channel;
 		    __entry->usage = conn ? atomic_read(&conn->usage) : -2;
 		    __entry->op = op;
-		    __entry->cid = conn->proto.cid;
+		    __entry->cid = conn ? conn->proto.cid : 0;
 			   ),
 
 	    TP_printk("C=%08x h=%2d %s i=%08x u=%d",




From dhowells at redhat.com  Mon Sep 14 11:31:21 2020
From: dhowells at redhat.com (David Howells)
Date: Mon, 14 Sep 2020 16:31:21 +0100
Subject: [PATCH net-next 5/5] rxrpc: Fix an overget of the conn bundle when
 setting up a client conn
In-Reply-To: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
References: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
Message-ID: <160009748120.1014072.10308681243643184204.stgit@warthog.procyon.org.uk>

When setting up a client connection, a second ref is accidentally obtained
on the connection bundle (we get one when allocating the conn and a second
one when adding the conn to the bundle).

Fix it to only use the ref obtained by rxrpc_alloc_client_connection() and
not to add a second when adding the candidate conn to the bundle.

Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
Signed-off-by: David Howells <dhowells at redhat.com>
---

 net/rxrpc/conn_client.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 0eb36ba52485..78c845a4f1ad 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -433,7 +433,6 @@ static void rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle, gfp_t gfp)
 		if (!rxrpc_may_reuse_conn(old)) {
 			if (old)
 				trace_rxrpc_client(old, -1, rxrpc_client_replace);
-			candidate->bundle = rxrpc_get_bundle(bundle);
 			candidate->bundle_shift = shift;
 			bundle->conns[i] = candidate;
 			for (j = 0; j < RXRPC_MAXCALLS; j++)




From dhowells at redhat.com  Mon Sep 14 11:31:14 2020
From: dhowells at redhat.com (David Howells)
Date: Mon, 14 Sep 2020 16:31:14 +0100
Subject: [PATCH net-next 4/5] rxrpc: Fix conn bundle leak in net-namespace exit
In-Reply-To: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
References: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
Message-ID: <160009747424.1014072.2463414249066927982.stgit@warthog.procyon.org.uk>

When the network namespace exits, rxrpc_clean_up_local_conns() needs to
unbundle each client connection it evicts.  Fix it to do this.

kernel BUG at net/rxrpc/conn_object.c:481!
RIP: 0010:rxrpc_destroy_all_connections.cold+0x11/0x13 net/rxrpc/conn_object.c:481
Call Trace:
 rxrpc_exit_net+0x1a4/0x2e0 net/rxrpc/net_ns.c:119
 ops_exit_list+0xb0/0x160 net/core/net_namespace.c:186
 cleanup_net+0x4ea/0xa00 net/core/net_namespace.c:603
 process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294

Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
Reported-by: syzbot+52071f826a617b9c76ed at syzkaller.appspotmail.com
Signed-off-by: David Howells <dhowells at redhat.com>
---

 net/rxrpc/conn_client.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 180be4da8d26..0eb36ba52485 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -1112,6 +1112,7 @@ void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
 		conn = list_entry(graveyard.next,
 				  struct rxrpc_connection, cache_link);
 		list_del_init(&conn->cache_link);
+		rxrpc_unbundle_conn(conn);
 		rxrpc_put_connection(conn);
 	}
 




From dhowells at redhat.com  Mon Sep 14 11:31:07 2020
From: dhowells at redhat.com (David Howells)
Date: Mon, 14 Sep 2020 16:31:07 +0100
Subject: [PATCH net-next 3/5] rxrpc: Fix rxrpc_bundle::alloc_error to be signed
In-Reply-To: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
References: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
Message-ID: <160009746742.1014072.15836712415506346429.stgit@warthog.procyon.org.uk>

The alloc_error field in the rxrpc_bundle struct should be signed as it has
negative error codes assigned to it.  Checks directly on it may then fail,
and may produce a warning like this:

	net/rxrpc/conn_client.c:662 rxrpc_wait_for_channel()
	warn: 'bundle->alloc_error' is unsigned

Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
Reported-by Dan Carpenter <dan.carpenter at oracle.com>
Signed-off-by: David Howells <dhowells at redhat.com>
---

 net/rxrpc/ar-internal.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index cd5a80b34738..19f714386654 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -395,7 +395,7 @@ struct rxrpc_bundle {
 	unsigned int		debug_id;
 	bool			try_upgrade;	/* True if the bundle is attempting upgrade */
 	bool			alloc_conn;	/* True if someone's getting a conn */
-	unsigned short		alloc_error;	/* Error from last conn allocation */
+	short			alloc_error;	/* Error from last conn allocation */
 	spinlock_t		channel_lock;
 	struct rb_node		local_node;	/* Node in local->client_conns */
 	struct list_head	waiting_calls;	/* Calls waiting for channels */




From davem at davemloft.net  Mon Sep 14 17:04:22 2020
From: davem at davemloft.net (David Miller)
Date: Mon, 14 Sep 2020 14:04:22 -0700 (PDT)
Subject: [PATCH net-next 0/5] rxrpc: Fixes for the connection manager
 rewrite
In-Reply-To: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
References: <160009744625.1014072.11957943055200732444.stgit@warthog.procyon.org.uk>
Message-ID: <20200914.140422.1249552994072814160.davem@davemloft.net>

From: David Howells <dhowells at redhat.com>
Date: Mon, 14 Sep 2020 16:30:46 +0100

> 
> Here are some fixes for the connection manager rewrite:
> 
>  (1) Fix a goto to the wrong place in error handling.
> 
>  (2) Fix a missing NULL pointer check.
> 
>  (3) The stored allocation error needs to be stored signed.
> 
>  (4) Fix a leak of connection bundle when clearing connections due to
>      net namespace exit.
> 
>  (5) Fix an overget of the bundle when setting up a new client conn.
> 
> The patches are tagged here:
> 
> 	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
> 	rxrpc-next-20200914

Pulled, thanks David.


From syzbot+d57aaf84dd8a550e6d91 at syzkaller.appspotmail.com  Wed Sep 16 04:52:15 2020
From: syzbot+d57aaf84dd8a550e6d91 at syzkaller.appspotmail.com (syzbot)
Date: Wed, 16 Sep 2020 01:52:15 -0700
Subject: KASAN: use-after-free Write in rxrpc_put_bundle
Message-ID: <0000000000005b8e4505af6a62a9@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    ed6d9b02 ionic: fix up debugfs after queue swap
git tree:       net-next
console output: https://syzkaller.appspot.com/x/log.txt?x=13d4c1b5900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=d29a102d22f784ea
dashboard link: https://syzkaller.appspot.com/bug?extid=d57aaf84dd8a550e6d91
compiler:       gcc (GCC) 10.1.0-syz 20200507
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15fe9101900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1749d92d900000

The issue was bisected to:

commit 245500d853e9f20036cec7df4f6984ece4c6bf26
Author: David Howells <dhowells at redhat.com>
Date:   Wed Jul 1 10:15:32 2020 +0000

    rxrpc: Rewrite the client connection manager

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=12348911900000
final oops:     https://syzkaller.appspot.com/x/report.txt?x=11348911900000
console output: https://syzkaller.appspot.com/x/log.txt?x=16348911900000

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+d57aaf84dd8a550e6d91 at syzkaller.appspotmail.com
Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")

==================================================================
BUG: KASAN: use-after-free in instrument_atomic_write include/linux/instrumented.h:71 [inline]
BUG: KASAN: use-after-free in atomic_dec_return include/asm-generic/atomic-instrumented.h:340 [inline]
BUG: KASAN: use-after-free in rxrpc_put_bundle+0x1d/0x80 net/rxrpc/conn_client.c:141
Write of size 4 at addr ffff8880a8669220 by task ksoftirqd/0/9

CPU: 0 PID: 9 Comm: ksoftirqd/0 Not tainted 5.9.0-rc3-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fd lib/dump_stack.c:118
 print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:383
 __kasan_report mm/kasan/report.c:513 [inline]
 kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
 check_memory_region_inline mm/kasan/generic.c:186 [inline]
 check_memory_region+0x13d/0x180 mm/kasan/generic.c:192
 instrument_atomic_write include/linux/instrumented.h:71 [inline]
 atomic_dec_return include/asm-generic/atomic-instrumented.h:340 [inline]
 rxrpc_put_bundle+0x1d/0x80 net/rxrpc/conn_client.c:141
 rxrpc_destroy_connection+0x150/0x2f0 net/rxrpc/conn_object.c:367
 rcu_do_batch kernel/rcu/tree.c:2428 [inline]
 rcu_core+0x5ca/0x1130 kernel/rcu/tree.c:2656
 __do_softirq+0x1f7/0xa91 kernel/softirq.c:298
 run_ksoftirqd kernel/softirq.c:652 [inline]
 run_ksoftirqd+0xcf/0x170 kernel/softirq.c:644
 smpboot_thread_fn+0x655/0x9e0 kernel/smpboot.c:165
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294

Allocated by task 6875:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
 kmem_cache_alloc_trace+0x174/0x2c0 mm/slab.c:3550
 kmalloc include/linux/slab.h:554 [inline]
 kzalloc include/linux/slab.h:666 [inline]
 rxrpc_alloc_bundle+0x7e/0x290 net/rxrpc/conn_client.c:121
 rxrpc_look_up_bundle net/rxrpc/conn_client.c:275 [inline]
 rxrpc_prep_call net/rxrpc/conn_client.c:374 [inline]
 rxrpc_connect_call+0x85c/0x1580 net/rxrpc/conn_client.c:710
 rxrpc_new_client_call+0x961/0x1020 net/rxrpc/call_object.c:331
 rxrpc_new_client_call_for_sendmsg net/rxrpc/sendmsg.c:622 [inline]
 rxrpc_do_sendmsg+0xf14/0x136d net/rxrpc/sendmsg.c:679
 rxrpc_sendmsg+0x420/0x630 net/rxrpc/af_rxrpc.c:560
 sock_sendmsg_nosec net/socket.c:651 [inline]
 sock_sendmsg+0xcf/0x120 net/socket.c:671
 ____sys_sendmsg+0x331/0x810 net/socket.c:2353
 ___sys_sendmsg+0xf3/0x170 net/socket.c:2407
 __sys_sendmmsg+0x195/0x480 net/socket.c:2497
 __do_sys_sendmmsg net/socket.c:2526 [inline]
 __se_sys_sendmmsg net/socket.c:2523 [inline]
 __x64_sys_sendmmsg+0x99/0x100 net/socket.c:2523
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 2642:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
 kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
 __cache_free mm/slab.c:3418 [inline]
 kfree+0x10e/0x2b0 mm/slab.c:3756
 rxrpc_put_bundle net/rxrpc/conn_client.c:146 [inline]
 rxrpc_put_bundle+0x6b/0x80 net/rxrpc/conn_client.c:138
 rxrpc_unbundle_conn+0x1f8/0x3d0 net/rxrpc/conn_client.c:935
 rxrpc_clean_up_local_conns+0x38d/0x587 net/rxrpc/conn_client.c:1114
 rxrpc_local_destroyer net/rxrpc/local_object.c:399 [inline]
 rxrpc_local_processor+0x38d/0x5e0 net/rxrpc/local_object.c:433
 process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294

The buggy address belongs to the object at ffff8880a8669200
 which belongs to the cache kmalloc-192 of size 192
The buggy address is located 32 bytes inside of
 192-byte region [ffff8880a8669200, ffff8880a86692c0)
The buggy address belongs to the page:
page:000000007bfb6cde refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff8880a8669d00 pfn:0xa8669
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea0002a42f88 ffffea00027d8f08 ffff8880aa040000
raw: ffff8880a8669d00 ffff8880a8669000 000000010000000d 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff8880a8669100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8880a8669180: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff8880a8669200: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                               ^
 ffff8880a8669280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
 ffff8880a8669300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
syzbot can test patches for this issue, for details see:
https://goo.gl/tpsmEJ#testing-patches


From hdanton at sina.com  Fri Sep 18 05:26:25 2020
From: hdanton at sina.com (Hillf Danton)
Date: Fri, 18 Sep 2020 17:26:25 +0800
Subject: KASAN: use-after-free Write in rxrpc_put_bundle
In-Reply-To: <0000000000005b8e4505af6a62a9@google.com>
References: <0000000000005b8e4505af6a62a9@google.com>
Message-ID: <20200918092625.9432-1-hdanton@sina.com>


Wed, 16 Sep 2020 01:52:15 -0700
> syzbot found the following issue on:
> 
> HEAD commit:    ed6d9b02 ionic: fix up debugfs after queue swap
> git tree:       net-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=13d4c1b5900000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=d29a102d22f784ea
> dashboard link: https://syzkaller.appspot.com/bug?extid=d57aaf84dd8a550e6d91
> compiler:       gcc (GCC) 10.1.0-syz 20200507
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15fe9101900000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1749d92d900000
> 
> The issue was bisected to:
> 
> commit 245500d853e9f20036cec7df4f6984ece4c6bf26
> Author: David Howells <dhowells at redhat.com>
> Date:   Wed Jul 1 10:15:32 2020 +0000
> 
>     rxrpc: Rewrite the client connection manager
> 
> bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=12348911900000
> final oops:     https://syzkaller.appspot.com/x/report.txt?x=11348911900000
> console output: https://syzkaller.appspot.com/x/log.txt?x=16348911900000
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+d57aaf84dd8a550e6d91 at syzkaller.appspotmail.com
> Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
> 
> ==================================================================
> BUG: KASAN: use-after-free in instrument_atomic_write include/linux/instrumented.h:71 [inline]
> BUG: KASAN: use-after-free in atomic_dec_return include/asm-generic/atomic-instrumented.h:340 [inline]
> BUG: KASAN: use-after-free in rxrpc_put_bundle+0x1d/0x80 net/rxrpc/conn_client.c:141
> Write of size 4 at addr ffff8880a8669220 by task ksoftirqd/0/9
> 
> CPU: 0 PID: 9 Comm: ksoftirqd/0 Not tainted 5.9.0-rc3-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> Call Trace:
>  __dump_stack lib/dump_stack.c:77 [inline]
>  dump_stack+0x198/0x1fd lib/dump_stack.c:118
>  print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:383
>  __kasan_report mm/kasan/report.c:513 [inline]
>  kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
>  check_memory_region_inline mm/kasan/generic.c:186 [inline]
>  check_memory_region+0x13d/0x180 mm/kasan/generic.c:192
>  instrument_atomic_write include/linux/instrumented.h:71 [inline]
>  atomic_dec_return include/asm-generic/atomic-instrumented.h:340 [inline]
>  rxrpc_put_bundle+0x1d/0x80 net/rxrpc/conn_client.c:141
>  rxrpc_destroy_connection+0x150/0x2f0 net/rxrpc/conn_object.c:367
>  rcu_do_batch kernel/rcu/tree.c:2428 [inline]
>  rcu_core+0x5ca/0x1130 kernel/rcu/tree.c:2656
>  __do_softirq+0x1f7/0xa91 kernel/softirq.c:298
>  run_ksoftirqd kernel/softirq.c:652 [inline]
>  run_ksoftirqd+0xcf/0x170 kernel/softirq.c:644
>  smpboot_thread_fn+0x655/0x9e0 kernel/smpboot.c:165
>  kthread+0x3b5/0x4a0 kernel/kthread.c:292
>  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
> 
> Allocated by task 6875:
>  kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
>  kasan_set_track mm/kasan/common.c:56 [inline]
>  __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
>  kmem_cache_alloc_trace+0x174/0x2c0 mm/slab.c:3550
>  kmalloc include/linux/slab.h:554 [inline]
>  kzalloc include/linux/slab.h:666 [inline]
>  rxrpc_alloc_bundle+0x7e/0x290 net/rxrpc/conn_client.c:121
>  rxrpc_look_up_bundle net/rxrpc/conn_client.c:275 [inline]
>  rxrpc_prep_call net/rxrpc/conn_client.c:374 [inline]
>  rxrpc_connect_call+0x85c/0x1580 net/rxrpc/conn_client.c:710
>  rxrpc_new_client_call+0x961/0x1020 net/rxrpc/call_object.c:331
>  rxrpc_new_client_call_for_sendmsg net/rxrpc/sendmsg.c:622 [inline]
>  rxrpc_do_sendmsg+0xf14/0x136d net/rxrpc/sendmsg.c:679
>  rxrpc_sendmsg+0x420/0x630 net/rxrpc/af_rxrpc.c:560
>  sock_sendmsg_nosec net/socket.c:651 [inline]
>  sock_sendmsg+0xcf/0x120 net/socket.c:671
>  ____sys_sendmsg+0x331/0x810 net/socket.c:2353
>  ___sys_sendmsg+0xf3/0x170 net/socket.c:2407
>  __sys_sendmmsg+0x195/0x480 net/socket.c:2497
>  __do_sys_sendmmsg net/socket.c:2526 [inline]
>  __se_sys_sendmmsg net/socket.c:2523 [inline]
>  __x64_sys_sendmmsg+0x99/0x100 net/socket.c:2523
>  do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> Freed by task 2642:
>  kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
>  kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
>  kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
>  __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
>  __cache_free mm/slab.c:3418 [inline]
>  kfree+0x10e/0x2b0 mm/slab.c:3756
>  rxrpc_put_bundle net/rxrpc/conn_client.c:146 [inline]
>  rxrpc_put_bundle+0x6b/0x80 net/rxrpc/conn_client.c:138
>  rxrpc_unbundle_conn+0x1f8/0x3d0 net/rxrpc/conn_client.c:935
>  rxrpc_clean_up_local_conns+0x38d/0x587 net/rxrpc/conn_client.c:1114
>  rxrpc_local_destroyer net/rxrpc/local_object.c:399 [inline]
>  rxrpc_local_processor+0x38d/0x5e0 net/rxrpc/local_object.c:433
>  process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
>  worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
>  kthread+0x3b5/0x4a0 kernel/kthread.c:292
>  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
> 
> The buggy address belongs to the object at ffff8880a8669200
>  which belongs to the cache kmalloc-192 of size 192
> The buggy address is located 32 bytes inside of
>  192-byte region [ffff8880a8669200, ffff8880a86692c0)
> The buggy address belongs to the page:
> page:000000007bfb6cde refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff8880a8669d00 pfn:0xa8669
> flags: 0xfffe0000000200(slab)
> raw: 00fffe0000000200 ffffea0002a42f88 ffffea00027d8f08 ffff8880aa040000
> raw: ffff8880a8669d00 ffff8880a8669000 000000010000000d 0000000000000000
> page dumped because: kasan: bad access detected
> 
> Memory state around the buggy address:
>  ffff8880a8669100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>  ffff8880a8669180: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
> >ffff8880a8669200: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>                                ^
>  ffff8880a8669280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>  ffff8880a8669300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ==================================================================


Put bundle on error to keep its usage count balanced.

--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -724,7 +724,8 @@ granted_channel:
 	smp_rmb();
 
 out_put_bundle:
-	rxrpc_put_bundle(bundle);
+	if (ret)
+		rxrpc_put_bundle(bundle);
 out:
 	_leave(" = %d", ret);
 	return ret;



From jani.nikula at linux.intel.com  Tue Sep 15 05:06:21 2020
From: jani.nikula at linux.intel.com (Jani Nikula)
Date: Tue, 15 Sep 2020 12:06:21 +0300
Subject: [Intel-gfx] [trivial PATCH] treewide: Convert switch/case
 fallthrough; to break; 
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <87d02nxvci.fsf@intel.com>

On Wed, 09 Sep 2020, Joe Perches <joe at perches.com> wrote:
> diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
> index 5ac0dbf0e03d..35ac539cc2b1 100644
> --- a/drivers/gpu/drm/i915/display/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/display/intel_sprite.c
> @@ -2861,7 +2861,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
>  	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
>  		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
>  			return false;
> -		fallthrough;
> +		break;
>  	case DRM_FORMAT_MOD_LINEAR:
>  	case I915_FORMAT_MOD_X_TILED:
>  	case I915_FORMAT_MOD_Y_TILED:

Acked-by: Jani Nikula <jani.nikula at intel.com>

for merging via whichever tree seems best.

BR,
Jani.


-- 
Jani Nikula, Intel Open Source Graphics Center


From miquel.raynal at bootlin.com  Tue Sep 15 05:19:25 2020
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Tue, 15 Sep 2020 11:19:25 +0200
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <20200915111925.475dd3f1@xps13>

Hi Joe,

For MTD:

>  drivers/mtd/nand/raw/nandsim.c                            |  2 +-

Reviewed-by: Miquel Raynal <miquel.raynal at bootlin.com>


Thanks,
Miqu?l


From simon.horman at netronome.com  Thu Sep 17 04:03:35 2020
From: simon.horman at netronome.com (Simon Horman)
Date: Thu, 17 Sep 2020 10:03:35 +0200
Subject: [oss-drivers] [trivial PATCH] treewide: Convert switch/case
 fallthrough; to break;
In-Reply-To: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
Message-ID: <20200917080334.GB5769@netronome.com>

On Wed, Sep 09, 2020 at 01:06:39PM -0700, Joe Perches wrote:
> fallthrough to a separate case/default label break; isn't very readable.
> 
> Convert pseudo-keyword fallthrough; statements to a simple break; when
> the next label is case or default and the only statement in the next
> label block is break;
> 
> Found using:
> 
> $ grep-2.5.4 -rP --include=*.[ch] -n "fallthrough;(\s*(case\s+\w+|default)\s*:\s*){1,7}break;" *
> 
> Miscellanea:
> 
> o Move or coalesce a couple label blocks above a default: block.
> 
> Signed-off-by: Joe Perches <joe at perches.com>

...

> diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
> index 252fe06f58aa..1d5b87079104 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
> @@ -345,7 +345,7 @@ static int matching_bar(struct nfp_bar *bar, u32 tgt, u32 act, u32 tok,
>  		baract = NFP_CPP_ACTION_RW;
>  		if (act == 0)
>  			act = NFP_CPP_ACTION_RW;
> -		fallthrough;
> +		break;
>  	case NFP_PCIE_BAR_PCIE2CPP_MapType_FIXED:
>  		break;
>  	default:

This is a cascading fall-through handling all map types.
I don't think this change improves readability.

...


From willy at infradead.org  Thu Sep 17 11:10:38 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:38 +0100
Subject: [PATCH 01/13] mm: Add AOP_UPDATED_PAGE return value
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-2-willy@infradead.org>

Allow synchronous ->readpage implementations to execute more
efficiently by skipping the re-locking of the page.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 Documentation/filesystems/locking.rst |  7 ++++---
 Documentation/filesystems/vfs.rst     | 21 ++++++++++++++-------
 include/linux/fs.h                    |  5 +++++
 mm/filemap.c                          | 12 ++++++++++--
 4 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index 64f94a18d97e..06a7a8bf2362 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -269,7 +269,7 @@ locking rules:
 ops			PageLocked(page)	 i_rwsem
 ======================	======================== =========
 writepage:		yes, unlocks (see below)
-readpage:		yes, unlocks
+readpage:		yes, may unlock
 writepages:
 set_page_dirty		no
 readahead:		yes, unlocks
@@ -294,8 +294,9 @@ swap_deactivate:	no
 ->write_begin(), ->write_end() and ->readpage() may be called from
 the request handler (/dev/loop).
 
-->readpage() unlocks the page, either synchronously or via I/O
-completion.
+->readpage() may return AOP_UPDATED_PAGE if the page is now Uptodate
+or 0 if the page will be unlocked asynchronously by I/O completion.
+If it returns -errno, it should unlock the page.
 
 ->readahead() unlocks the pages that I/O is attempted on like ->readpage().
 
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index ca52c82e5bb5..16248c299aaa 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -643,7 +643,7 @@ set_page_dirty to write data into the address_space, and writepage and
 writepages to writeback data to storage.
 
 Adding and removing pages to/from an address_space is protected by the
-inode's i_mutex.
+inode's i_rwsem held exclusively.
 
 When data is written to a page, the PG_Dirty flag should be set.  It
 typically remains set until writepage asks for it to be written.  This
@@ -757,12 +757,19 @@ cache in your filesystem.  The following members are defined:
 
 ``readpage``
 	called by the VM to read a page from backing store.  The page
-	will be Locked when readpage is called, and should be unlocked
-	and marked uptodate once the read completes.  If ->readpage
-	discovers that it needs to unlock the page for some reason, it
-	can do so, and then return AOP_TRUNCATED_PAGE.  In this case,
-	the page will be relocated, relocked and if that all succeeds,
-	->readpage will be called again.
+	will be Locked and !Uptodate when readpage is called.  Ideally,
+	the filesystem will bring the page Uptodate and return
+	AOP_UPDATED_PAGE.  If the filesystem encounters an error, it
+	should unlock the page and return a negative errno without marking
+	the page Uptodate.  It does not need to mark the page as Error.
+	If the filesystem returns 0, this means the page will be unlocked
+	asynchronously by I/O completion.  The VFS will wait for the
+	page to be unlocked, so there is no advantage to executing this
+	operation asynchronously.
+
+	The filesystem can also return AOP_TRUNCATED_PAGE to indicate
+	that it had to unlock the page to avoid a deadlock.  The caller
+	will re-check the page cache and call ->readpage again.
 
 ``writepages``
 	called by the VM to write out pages associated with the
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e019ea2f1347..6fc650050d20 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -273,6 +273,10 @@ struct iattr {
  *  			reference, it should drop it before retrying.  Returned
  *  			by readpage().
  *
+ * @AOP_UPDATED_PAGE: The readpage method has brought the page Uptodate
+ * without releasing the page lock.  This is suitable for synchronous
+ * implementations of readpage.
+ *
  * address_space_operation functions return these large constants to indicate
  * special semantics to the caller.  These are much larger than the bytes in a
  * page to allow for functions that return the number of bytes operated on in a
@@ -282,6 +286,7 @@ struct iattr {
 enum positive_aop_returns {
 	AOP_WRITEPAGE_ACTIVATE	= 0x80000,
 	AOP_TRUNCATED_PAGE	= 0x80001,
+	AOP_UPDATED_PAGE	= 0x80002,
 };
 
 #define AOP_FLAG_CONT_EXPAND		0x0001 /* called from cont_expand */
diff --git a/mm/filemap.c b/mm/filemap.c
index 1aaea26556cc..131a2aaa1537 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2254,8 +2254,10 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
 		 * PG_error will be set again if readpage fails.
 		 */
 		ClearPageError(page);
-		/* Start the actual read. The read will unlock the page. */
+		/* Start the actual read. The read may unlock the page. */
 		error = mapping->a_ops->readpage(filp, page);
+		if (error == AOP_UPDATED_PAGE)
+			goto page_ok;
 
 		if (unlikely(error)) {
 			if (error == AOP_TRUNCATED_PAGE) {
@@ -2619,7 +2621,7 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
 	 */
 	if (unlikely(!PageUptodate(page)))
 		goto page_not_uptodate;
-
+page_ok:
 	/*
 	 * We've made it this far and we had to drop our mmap_lock, now is the
 	 * time to return to the upper layer and have it re-find the vma and
@@ -2654,6 +2656,8 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
 	ClearPageError(page);
 	fpin = maybe_unlock_mmap_for_io(vmf, fpin);
 	error = mapping->a_ops->readpage(file, page);
+	if (error == AOP_UPDATED_PAGE)
+		goto page_ok;
 	if (!error) {
 		wait_on_page_locked(page);
 		if (!PageUptodate(page))
@@ -2867,6 +2871,10 @@ static struct page *do_read_cache_page(struct address_space *mapping,
 			err = filler(data, page);
 		else
 			err = mapping->a_ops->readpage(data, page);
+		if (err == AOP_UPDATED_PAGE) {
+			unlock_page(page);
+			goto out;
+		}
 
 		if (err < 0) {
 			put_page(page);
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:41 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:41 +0100
Subject: [PATCH 04/13] ceph: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-5-willy@infradead.org>

The ceph readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/ceph/addr.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 6ea761c84494..b2bf8bf7a312 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -291,10 +291,11 @@ static int ceph_do_readpage(struct file *filp, struct page *page)
 static int ceph_readpage(struct file *filp, struct page *page)
 {
 	int r = ceph_do_readpage(filp, page);
-	if (r != -EINPROGRESS)
-		unlock_page(page);
-	else
-		r = 0;
+	if (r == -EINPROGRESS)
+		return 0;
+	if (r == 0)
+		return AOP_UPDATED_PAGE;
+	unlock_page(page);
 	return r;
 }
 
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:42 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:42 +0100
Subject: [PATCH 05/13] cifs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-6-willy@infradead.org>

The cifs readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/cifs/file.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index be46fab4c96d..533b151a9143 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -4537,7 +4537,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 	/* send this page to the cache */
 	cifs_readpage_to_fscache(file_inode(file), page);
 
-	rc = 0;
+	kunmap(page);
+	return AOP_UPDATED_PAGE;
 
 io_error:
 	kunmap(page);
@@ -4677,7 +4678,10 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
 		 * an error, we don't need to return it. cifs_write_end will
 		 * do a sync write instead since PG_uptodate isn't set.
 		 */
-		cifs_readpage_worker(file, page, &page_start);
+		int err = cifs_readpage_worker(file, page, &page_start);
+
+		if (err == AOP_UPDATED_PAGE)
+			goto out;
 		put_page(page);
 		oncethru = 1;
 		goto start;
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:43 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:43 +0100
Subject: [PATCH 06/13] cramfs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-7-willy@infradead.org>

The cramfs readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/cramfs/inode.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 912308600d39..7a642146c074 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -916,15 +916,14 @@ static int cramfs_readpage(struct file *file, struct page *page)
 	flush_dcache_page(page);
 	kunmap(page);
 	SetPageUptodate(page);
-	unlock_page(page);
-	return 0;
+	return AOP_UPDATED_PAGE;
 
 err:
 	kunmap(page);
 	ClearPageUptodate(page);
 	SetPageError(page);
 	unlock_page(page);
-	return 0;
+	return -EIO;
 }
 
 static const struct address_space_operations cramfs_aops = {
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:44 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:44 +0100
Subject: [PATCH 07/13] ecryptfs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-8-willy@infradead.org>

The ecryptfs readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/ecryptfs/mmap.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 019572c6b39a..dee35181d789 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -219,12 +219,13 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
 		}
 	}
 out:
-	if (rc)
-		ClearPageUptodate(page);
-	else
-		SetPageUptodate(page);
-	ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n",
+	ecryptfs_printk(KERN_DEBUG, "Returning page with index = [0x%.16lx]\n",
 			page->index);
+	if (!rc) {
+		SetPageUptodate(page);
+		return AOP_UPDATED_PAGE;
+	}
+	ClearPageUptodate(page);
 	unlock_page(page);
 	return rc;
 }
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:45 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:45 +0100
Subject: [PATCH 08/13] fuse: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-9-willy@infradead.org>

The fuse readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/fuse/file.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6611ef3269a8..7aa5626bc582 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -850,6 +850,8 @@ static int fuse_readpage(struct file *file, struct page *page)
 
 	err = fuse_do_readpage(file, page);
 	fuse_invalidate_atime(inode);
+	if (!err)
+		return AOP_UPDATED_PAGE;
  out:
 	unlock_page(page);
 	return err;
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:46 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:46 +0100
Subject: [PATCH 09/13] hostfs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-10-willy@infradead.org>

The hostfs readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/hostfs/hostfs_kern.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index c070c0d8e3e9..c49221c09c4b 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -455,6 +455,8 @@ static int hostfs_readpage(struct file *file, struct page *page)
  out:
 	flush_dcache_page(page);
 	kunmap(page);
+	if (!ret)
+		return AOP_UPDATED_PAGE;
 	unlock_page(page);
 	return ret;
 }
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:47 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:47 +0100
Subject: [PATCH 10/13] jffs2: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-11-willy@infradead.org>

The jffs2 readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/jffs2/file.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index f8fb89b10227..959a74027041 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -116,15 +116,17 @@ int jffs2_do_readpage_unlock(void *data, struct page *pg)
 	return ret;
 }
 
-
 static int jffs2_readpage (struct file *filp, struct page *pg)
 {
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
 	int ret;
 
 	mutex_lock(&f->sem);
-	ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
+	ret = jffs2_do_readpage_nolock(pg->mapping->host, pg);
 	mutex_unlock(&f->sem);
+	if (!ret)
+		return AOP_UPDATED_PAGE;
+	unlock_page(pg);
 	return ret;
 }
 
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:48 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:48 +0100
Subject: [PATCH 11/13] ubifs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-12-willy@infradead.org>

The ubifs readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/ubifs/file.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index b77d1637bbbc..82633509c45e 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -772,7 +772,6 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,
 	if (err)
 		goto out_warn;
 
-	unlock_page(page1);
 	ret = 1;
 
 	isize = i_size_read(inode);
@@ -892,11 +891,16 @@ static int ubifs_bulk_read(struct page *page)
 
 static int ubifs_readpage(struct file *file, struct page *page)
 {
-	if (ubifs_bulk_read(page))
-		return 0;
-	do_readpage(page);
-	unlock_page(page);
-	return 0;
+	int err;
+
+	err = ubifs_bulk_read(page);
+	if (err == 0)
+		err = do_readpage(page);
+	if (err < 0) {
+		unlock_page(page);
+		return err;
+	}
+	return AOP_UPDATED_PAGE;
 }
 
 static int do_writepage(struct page *page, int len)
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:49 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:49 +0100
Subject: [PATCH 12/13] udf: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-13-willy@infradead.org>

The udf inline data readpage implementation was already synchronous,
so use AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/udf/file.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/udf/file.c b/fs/udf/file.c
index 628941a6b79a..52bbe92d7c43 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -61,9 +61,8 @@ static int udf_adinicb_readpage(struct file *file, struct page *page)
 {
 	BUG_ON(!PageLocked(page));
 	__udf_adinicb_readpage(page);
-	unlock_page(page);
 
-	return 0;
+	return AOP_UPDATED_PAGE;
 }
 
 static int udf_adinicb_writepage(struct page *page,
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:50 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:50 +0100
Subject: [PATCH 13/13] vboxsf: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-14-willy@infradead.org>

The vboxsf inline data readpage implementation was already synchronous,
so use AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/vboxsf/file.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
index c4ab5996d97a..c2a144e5cb5a 100644
--- a/fs/vboxsf/file.c
+++ b/fs/vboxsf/file.c
@@ -228,6 +228,8 @@ static int vboxsf_readpage(struct file *file, struct page *page)
 	}
 
 	kunmap(page);
+	if (!err)
+		return AOP_UPDATED_PAGE;
 	unlock_page(page);
 	return err;
 }
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:39 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:39 +0100
Subject: [PATCH 02/13] 9p: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-3-willy@infradead.org>

The 9p readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/9p/vfs_addr.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index cce9ace651a2..506ca0ba2ec7 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -65,7 +65,7 @@ static int v9fs_fid_readpage(void *data, struct page *page)
 	SetPageUptodate(page);
 
 	v9fs_readpage_to_fscache(inode, page);
-	retval = 0;
+	return AOP_UPDATED_PAGE;
 
 done:
 	unlock_page(page);
@@ -280,6 +280,10 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
 		goto out;
 
 	retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
+	if (retval == AOP_UPDATED_PAGE) {
+		retval = 0;
+		goto out;
+	}
 	put_page(page);
 	if (!retval)
 		goto start;
-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:37 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:37 +0100
Subject: [PATCH 00/13] Allow readpage to return a locked page
Message-ID: <20200917151050.5363-1-willy@infradead.org>

Linus recently made the page lock more fair.  That means that the old
pattern where we returned from ->readpage with the page unlocked and
then attempted to re-lock it will send us to the back of the queue for
this page's lock.

Ideally all filesystems would return from ->readpage with the
page Uptodate and Locked, but it's a bit painful to convert all the
asynchronous readpage implementations to synchronous.  These ones are
already synchronous, so convert them while I work on iomap.

A further benefit is that a synchronous readpage implementation allows
us to return an error to someone who might actually care about it.
There's no need to SetPageError, but I don't want to learn about how
a dozen filesystems handle I/O errors (hint: they're all different),
so I have not attempted to change that.

Please review your filesystem carefully.  I've tried to catch all the
places where a filesystem calls its own internal readpage implementation
without going through ->readpage, but I may have missed some.

Matthew Wilcox (Oracle) (13):
  mm: Add AOP_UPDATED_PAGE return value
  9p: Tell the VFS that readpage was synchronous
  afs: Tell the VFS that readpage was synchronous
  ceph: Tell the VFS that readpage was synchronous
  cifs: Tell the VFS that readpage was synchronous
  cramfs: Tell the VFS that readpage was synchronous
  ecryptfs: Tell the VFS that readpage was synchronous
  fuse: Tell the VFS that readpage was synchronous
  hostfs: Tell the VFS that readpage was synchronous
  jffs2: Tell the VFS that readpage was synchronous
  ubifs: Tell the VFS that readpage was synchronous
  udf: Tell the VFS that readpage was synchronous
  vboxsf: Tell the VFS that readpage was synchronous

 Documentation/filesystems/locking.rst |  7 ++++---
 Documentation/filesystems/vfs.rst     | 21 ++++++++++++++-------
 fs/9p/vfs_addr.c                      |  6 +++++-
 fs/afs/file.c                         |  3 ++-
 fs/ceph/addr.c                        |  9 +++++----
 fs/cifs/file.c                        |  8 ++++++--
 fs/cramfs/inode.c                     |  5 ++---
 fs/ecryptfs/mmap.c                    | 11 ++++++-----
 fs/fuse/file.c                        |  2 ++
 fs/hostfs/hostfs_kern.c               |  2 ++
 fs/jffs2/file.c                       |  6 ++++--
 fs/ubifs/file.c                       | 16 ++++++++++------
 fs/udf/file.c                         |  3 +--
 fs/vboxsf/file.c                      |  2 ++
 include/linux/fs.h                    |  5 +++++
 mm/filemap.c                          | 12 ++++++++++--
 16 files changed, 80 insertions(+), 38 deletions(-)

-- 
2.28.0



From willy at infradead.org  Thu Sep 17 11:10:40 2020
From: willy at infradead.org (Matthew Wilcox (Oracle))
Date: Thu, 17 Sep 2020 16:10:40 +0100
Subject: [PATCH 03/13] afs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-1-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
Message-ID: <20200917151050.5363-4-willy@infradead.org>

The afs readpage implementation was already synchronous, so use
AOP_UPDATED_PAGE to avoid cycling the page lock.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/afs/file.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/afs/file.c b/fs/afs/file.c
index 6f6ed1605cfe..8f15305b6574 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -367,7 +367,8 @@ int afs_page_filler(void *data, struct page *page)
 			BUG_ON(PageFsCache(page));
 		}
 #endif
-		unlock_page(page);
+		_leave(" = AOP_UPDATED_PAGE");
+		return AOP_UPDATED_PAGE;
 	}
 
 	_leave(" = 0");
-- 
2.28.0



From jlayton at kernel.org  Thu Sep 17 12:49:40 2020
From: jlayton at kernel.org (Jeff Layton)
Date: Thu, 17 Sep 2020 12:49:40 -0400
Subject: [PATCH 04/13] ceph: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-5-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
 <20200917151050.5363-5-willy@infradead.org>
Message-ID: <57d35fdb5ea646f96b70fd8b8a29434761c3f1d3.camel@kernel.org>

On Thu, 2020-09-17 at 16:10 +0100, Matthew Wilcox (Oracle) wrote:
> The ceph readpage implementation was already synchronous, so use
> AOP_UPDATED_PAGE to avoid cycling the page lock.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
> ---
>  fs/ceph/addr.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
> index 6ea761c84494..b2bf8bf7a312 100644
> --- a/fs/ceph/addr.c
> +++ b/fs/ceph/addr.c
> @@ -291,10 +291,11 @@ static int ceph_do_readpage(struct file *filp, struct page *page)
>  static int ceph_readpage(struct file *filp, struct page *page)
>  {
>  	int r = ceph_do_readpage(filp, page);
> -	if (r != -EINPROGRESS)
> -		unlock_page(page);
> -	else
> -		r = 0;
> +	if (r == -EINPROGRESS)
> +		return 0;
> +	if (r == 0)
> +		return AOP_UPDATED_PAGE;
> +	unlock_page(page);
>  	return r;
>  }
>  

Looks good to me. I assume you'll merge all of these as a set since the
early ones are a prerequisite?

Reviewed-by: Jeff Layton <jlayton at kernel.org>



From jacob.e.keller at intel.com  Thu Sep 17 15:40:13 2020
From: jacob.e.keller at intel.com (Jacob Keller)
Date: Thu, 17 Sep 2020 12:40:13 -0700
Subject: [trivial PATCH] treewide: Convert switch/case fallthrough; to
 break;
In-Reply-To: <20200909205558.GA3384631@dhcp-10-100-145-180.wdl.wdc.com>
References: <e6387578c75736d61b2fe70d9783d91329a97eb4.camel@perches.com>
 <20200909205558.GA3384631@dhcp-10-100-145-180.wdl.wdc.com>
Message-ID: <321069c8-a4c1-56ff-49fb-4c2bce1e6352@intel.com>



On 9/9/2020 1:55 PM, Keith Busch wrote:
> On Wed, Sep 09, 2020 at 01:06:39PM -0700, Joe Perches wrote:
>> diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
>> index eea0f453cfb6..8aac5bc60f4c 100644
>> --- a/crypto/tcrypt.c
>> +++ b/crypto/tcrypt.c
>> @@ -2464,7 +2464,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
>>  		test_hash_speed("streebog512", sec,
>>  				generic_hash_speed_template);
>>  		if (mode > 300 && mode < 400) break;
>> -		fallthrough;
>> +		break;
>>  	case 399:
>>  		break;
> 
> Just imho, this change makes the preceding 'if' look even more
> pointless. Maybe the fallthrough was a deliberate choice? Not that my
> opinion matters here as I don't know this module, but it looked a bit
> odd to me.
> 

Yea this does look very odd..


From richard at nod.at  Thu Sep 17 16:46:52 2020
From: richard at nod.at (Richard Weinberger)
Date: Thu, 17 Sep 2020 22:46:52 +0200 (CEST)
Subject: [PATCH 11/13] ubifs: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-12-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
 <20200917151050.5363-12-willy@infradead.org>
Message-ID: <482280458.101023.1600375612958.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "Matthew Wilcox" <willy at infradead.org>
> An: "linux-fsdevel" <linux-fsdevel at vger.kernel.org>
> CC: "Matthew Wilcox" <willy at infradead.org>, "linux-mm" <linux-mm at kvack.org>, v9fs-developer at lists.sourceforge.net,
> "linux-kernel" <linux-kernel at vger.kernel.org>, linux-afs at lists.infradead.org, "ceph-devel"
> <ceph-devel at vger.kernel.org>, linux-cifs at vger.kernel.org, ecryptfs at vger.kernel.org, "linux-um"
> <linux-um at lists.infradead.org>, "linux-mtd" <linux-mtd at lists.infradead.org>, "richard" <richard at nod.at>
> Gesendet: Donnerstag, 17. September 2020 17:10:48
> Betreff: [PATCH 11/13] ubifs: Tell the VFS that readpage was synchronous

> The ubifs readpage implementation was already synchronous, so use
> AOP_UPDATED_PAGE to avoid cycling the page lock.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
> ---
> fs/ubifs/file.c | 16 ++++++++++------
> 1 file changed, 10 insertions(+), 6 deletions(-)

For ubifs, jffs2 and hostfs:

Acked-by: Richard Weinberger <richard at nod.at>

Thanks,
//richard


From willy at infradead.org  Thu Sep 17 18:03:07 2020
From: willy at infradead.org (Matthew Wilcox)
Date: Thu, 17 Sep 2020 23:03:07 +0100
Subject: [PATCH 01/13] mm: Add AOP_UPDATED_PAGE return value
In-Reply-To: <20200917151050.5363-2-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
 <20200917151050.5363-2-willy@infradead.org>
Message-ID: <20200917220307.GX5449@casper.infradead.org>

On Thu, Sep 17, 2020 at 04:10:38PM +0100, Matthew Wilcox (Oracle) wrote:
> +++ b/mm/filemap.c
> @@ -2254,8 +2254,10 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
>  		 * PG_error will be set again if readpage fails.
>  		 */
>  		ClearPageError(page);
> -		/* Start the actual read. The read will unlock the page. */
> +		/* Start the actual read. The read may unlock the page. */
>  		error = mapping->a_ops->readpage(filp, page);
> +		if (error == AOP_UPDATED_PAGE)
> +			goto page_ok;
>  
>  		if (unlikely(error)) {
>  			if (error == AOP_TRUNCATED_PAGE) {

If anybody wants to actually test this, this hunk is wrong.

+++ b/mm/filemap.c
@@ -2256,8 +2256,11 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
                ClearPageError(page);
                /* Start the actual read. The read may unlock the page. */
                error = mapping->a_ops->readpage(filp, page);
-               if (error == AOP_UPDATED_PAGE)
+               if (error == AOP_UPDATED_PAGE) {
+                       unlock_page(page);
+                       error = 0;
                        goto page_ok;
+               }
 
                if (unlikely(error)) {
                        if (error == AOP_TRUNCATED_PAGE) {

> @@ -2619,7 +2621,7 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
>  	 */
>  	if (unlikely(!PageUptodate(page)))
>  		goto page_not_uptodate;
> -
> +page_ok:
>  	/*
>  	 * We've made it this far and we had to drop our mmap_lock, now is the
>  	 * time to return to the upper layer and have it re-find the vma and
> @@ -2654,6 +2656,8 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
>  	ClearPageError(page);
>  	fpin = maybe_unlock_mmap_for_io(vmf, fpin);
>  	error = mapping->a_ops->readpage(file, page);
> +	if (error == AOP_UPDATED_PAGE)
> +		goto page_ok;
>  	if (!error) {
>  		wait_on_page_locked(page);
>  		if (!PageUptodate(page))
> @@ -2867,6 +2871,10 @@ static struct page *do_read_cache_page(struct address_space *mapping,
>  			err = filler(data, page);
>  		else
>  			err = mapping->a_ops->readpage(data, page);
> +		if (err == AOP_UPDATED_PAGE) {
> +			unlock_page(page);
> +			goto out;
> +		}
>  
>  		if (err < 0) {
>  			put_page(page);
> -- 
> 2.28.0
> 


From asmadeus at codewreck.org  Fri Sep 18 01:59:19 2020
From: asmadeus at codewreck.org (Dominique Martinet)
Date: Fri, 18 Sep 2020 07:59:19 +0200
Subject: [V9fs-developer] [PATCH 02/13] 9p: Tell the VFS that readpage
 was synchronous
In-Reply-To: <20200917151050.5363-3-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
 <20200917151050.5363-3-willy@infradead.org>
Message-ID: <20200918055919.GA30929@nautica>

Matthew Wilcox (Oracle) wrote on Thu, Sep 17, 2020:
> diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
> index cce9ace651a2..506ca0ba2ec7 100644
> --- a/fs/9p/vfs_addr.c
> +++ b/fs/9p/vfs_addr.c
> @@ -280,6 +280,10 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
>  		goto out;
>  
>  	retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
> +	if (retval == AOP_UPDATED_PAGE) {
> +		retval = 0;
> +		goto out;
> +	}

FWIW this is a change of behaviour; for some reason the code used to
loop back to grab_cache_page_write_begin() and bail out on
PageUptodate() I suppose; some sort of race check?
The whole pattern is a bit weird to me and 9p has no guarantee on
concurrent writes to a file with cache enabled (except that it will
corrupt something), so this part is fine with me.

What I'm curious about is the page used to be both unlocked and put, but
now isn't either and the return value hasn't changed for the caller to
make a difference on write_begin / I don't see any code change in the
vfs  to handle that.
What did I miss?


(FWIW at least cifs in the series has the same pattern change; didn't
check all of them)


Thanks,
-- 
Dominique


From willy at infradead.org  Fri Sep 18 07:19:16 2020
From: willy at infradead.org (Matthew Wilcox)
Date: Fri, 18 Sep 2020 12:19:16 +0100
Subject: [V9fs-developer] [PATCH 02/13] 9p: Tell the VFS that readpage
 was synchronous
In-Reply-To: <20200918055919.GA30929@nautica>
References: <20200917151050.5363-1-willy@infradead.org>
 <20200917151050.5363-3-willy@infradead.org>
 <20200918055919.GA30929@nautica>
Message-ID: <20200918111916.GA32101@casper.infradead.org>

On Fri, Sep 18, 2020 at 07:59:19AM +0200, Dominique Martinet wrote:
> Matthew Wilcox (Oracle) wrote on Thu, Sep 17, 2020:
> > diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
> > index cce9ace651a2..506ca0ba2ec7 100644
> > --- a/fs/9p/vfs_addr.c
> > +++ b/fs/9p/vfs_addr.c
> > @@ -280,6 +280,10 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
> >  		goto out;
> >  
> >  	retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
> > +	if (retval == AOP_UPDATED_PAGE) {
> > +		retval = 0;
> > +		goto out;
> > +	}
> 
> FWIW this is a change of behaviour; for some reason the code used to
> loop back to grab_cache_page_write_begin() and bail out on
> PageUptodate() I suppose; some sort of race check?
> The whole pattern is a bit weird to me and 9p has no guarantee on
> concurrent writes to a file with cache enabled (except that it will
> corrupt something), so this part is fine with me.
> 
> What I'm curious about is the page used to be both unlocked and put, but
> now isn't either and the return value hasn't changed for the caller to
> make a difference on write_begin / I don't see any code change in the
> vfs  to handle that.
> What did I miss?

The page cache is kind of subtle.  The grab_cache_page_write_begin()
will return a Locked page with an increased refcount.  If it's Uptodate,
that's exactly what we want, and we return it.  If we have to read the
page, readpage used to unlock the page before returning, and rather than
re-lock it, we would drop the reference to the page and look it up again.
It's possible that after dropping the lock on that page that the page
was replaced in the page cache and so we'd get a different page.

Anyway, now (unless fscache is involved), v9fs_fid_readpage will return
the page without unlocking it.  So we don't need to do the dance of
dropping the lock, putting the refcount and looking the page back up
again.  We can just return the page.  The VFS doesn't need a special
return code because nothing has changed from the VFS's point of view --
it asked you to get a page and you got the page.


From hdanton at sina.com  Fri Sep 18 08:16:10 2020
From: hdanton at sina.com (Hillf Danton)
Date: Fri, 18 Sep 2020 20:16:10 +0800
Subject: [Linux-kernel-mentees] [PATCH syzbot net-next] rxrpc:
 Fixuse-after-free write in rxrpc_connect_call()
Message-ID: <20200918121610.9324-1-hdanton@sina.com>


On Fri, 18 Sep 2020 18:52:16 Dan Carpenter wrote:
> 
> The commit message is not clear and I can't immediately verify what
> the patch is trying to do.

Our fault and say sorry to you for it.

You can find the uaf syzbot report at the link below,

 https://lore.kernel.org/lkml/0000000000005b8e4505af6a62a9 at google.com/

and I sent a diff in reply to it. This is the thread Peilin raised and
asked syzbot to test the diff posted mainly for David to see if I'm 
in the right direction.

> Looking through the git log, I think this
> might already be fixed by commit f1b449748760 ("rxrpc: Fix an overget of
> the conn bundle when setting up a client conn")

Thanks for taking a look at it, Dan.

Quite likely if the syzbot report did not cover the commit above.

btw, I'm curious about why the mentees tag is necessary. Are you now taking
some intern job at some office like google.

Hillf



From asmadeus at codewreck.org  Fri Sep 18 08:30:25 2020
From: asmadeus at codewreck.org (Dominique Martinet)
Date: Fri, 18 Sep 2020 14:30:25 +0200
Subject: [V9fs-developer] [PATCH 02/13] 9p: Tell the VFS that readpage
 was synchronous
In-Reply-To: <20200918111916.GA32101@casper.infradead.org>
 <20200917151050.5363-3-willy@infradead.org>
Message-ID: <20200918123025.GA735@nautica>

Matthew Wilcox (Oracle) wrote on Thu, Sep 17, 2020:
> The 9p readpage implementation was already synchronous, so use
> AOP_UPDATED_PAGE to avoid cycling the page lock.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>

Acked-by: Dominique Martinet <asmadeus at codewreck.org>

(I assume it'll be merged together with the rest)

> > What I'm curious about is the page used to be both unlocked and put, but
> > now isn't either and the return value hasn't changed for the caller to
> > make a difference on write_begin / I don't see any code change in the
> > vfs  to handle that.
> > What did I miss?
> 
> The page cache is kind of subtle.  The grab_cache_page_write_begin()
> will return a Locked page with an increased refcount.  If it's Uptodate,
> that's exactly what we want, and we return it.  If we have to read the
> page, readpage used to unlock the page before returning, and rather than
> re-lock it, we would drop the reference to the page and look it up again.
> It's possible that after dropping the lock on that page that the page
> was replaced in the page cache and so we'd get a different page.

Thanks for the explanation, I didn't realize the page already is
gotten/locked at the PageUptodate goto out.

> Anyway, now (unless fscache is involved), v9fs_fid_readpage will return
> the page without unlocking it.  So we don't need to do the dance of
> dropping the lock, putting the refcount and looking the page back up
> again.  We can just return the page.  The VFS doesn't need a special
> return code because nothing has changed from the VFS's point of view --
> it asked you to get a page and you got the page.

Yes, looks good to me.

Cheers,
-- 
Dominique


From hdanton at sina.com  Fri Sep 18 22:33:03 2020
From: hdanton at sina.com (Hillf Danton)
Date: Sat, 19 Sep 2020 10:33:03 +0800
Subject: KASAN: use-after-free Write in rxrpc_put_bundle
In-Reply-To: <0000000000005b8e4505af6a62a9@google.com>
References: <0000000000005b8e4505af6a62a9@google.com>
Message-ID: <20200919023303.7648-1-hdanton@sina.com>


Wed, 16 Sep 2020 01:52:15 -0700
> syzbot found the following issue on:
> 
> HEAD commit:    ed6d9b02 ionic: fix up debugfs after queue swap
> git tree:       net-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=13d4c1b5900000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=d29a102d22f784ea
> dashboard link: https://syzkaller.appspot.com/bug?extid=d57aaf84dd8a550e6d91
> compiler:       gcc (GCC) 10.1.0-syz 20200507
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15fe9101900000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1749d92d900000
> 
> The issue was bisected to:
> 
> commit 245500d853e9f20036cec7df4f6984ece4c6bf26
> Author: David Howells <dhowells at redhat.com>
> Date:   Wed Jul 1 10:15:32 2020 +0000
> 
>     rxrpc: Rewrite the client connection manager
> 
> bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=12348911900000
> final oops:     https://syzkaller.appspot.com/x/report.txt?x=11348911900000
> console output: https://syzkaller.appspot.com/x/log.txt?x=16348911900000
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+d57aaf84dd8a550e6d91 at syzkaller.appspotmail.com
> Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
> 
> ==================================================================
> BUG: KASAN: use-after-free in instrument_atomic_write include/linux/instrumented.h:71 [inline]
> BUG: KASAN: use-after-free in atomic_dec_return include/asm-generic/atomic-instrumented.h:340 [inline]
> BUG: KASAN: use-after-free in rxrpc_put_bundle+0x1d/0x80 net/rxrpc/conn_client.c:141
> Write of size 4 at addr ffff8880a8669220 by task ksoftirqd/0/9
> 
> CPU: 0 PID: 9 Comm: ksoftirqd/0 Not tainted 5.9.0-rc3-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> Call Trace:
>  __dump_stack lib/dump_stack.c:77 [inline]
>  dump_stack+0x198/0x1fd lib/dump_stack.c:118
>  print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:383
>  __kasan_report mm/kasan/report.c:513 [inline]
>  kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
>  check_memory_region_inline mm/kasan/generic.c:186 [inline]
>  check_memory_region+0x13d/0x180 mm/kasan/generic.c:192
>  instrument_atomic_write include/linux/instrumented.h:71 [inline]
>  atomic_dec_return include/asm-generic/atomic-instrumented.h:340 [inline]
>  rxrpc_put_bundle+0x1d/0x80 net/rxrpc/conn_client.c:141
>  rxrpc_destroy_connection+0x150/0x2f0 net/rxrpc/conn_object.c:367
>  rcu_do_batch kernel/rcu/tree.c:2428 [inline]
>  rcu_core+0x5ca/0x1130 kernel/rcu/tree.c:2656
>  __do_softirq+0x1f7/0xa91 kernel/softirq.c:298
>  run_ksoftirqd kernel/softirq.c:652 [inline]
>  run_ksoftirqd+0xcf/0x170 kernel/softirq.c:644
>  smpboot_thread_fn+0x655/0x9e0 kernel/smpboot.c:165
>  kthread+0x3b5/0x4a0 kernel/kthread.c:292
>  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
> 
> Allocated by task 6875:
>  kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
>  kasan_set_track mm/kasan/common.c:56 [inline]
>  __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
>  kmem_cache_alloc_trace+0x174/0x2c0 mm/slab.c:3550
>  kmalloc include/linux/slab.h:554 [inline]
>  kzalloc include/linux/slab.h:666 [inline]
>  rxrpc_alloc_bundle+0x7e/0x290 net/rxrpc/conn_client.c:121
>  rxrpc_look_up_bundle net/rxrpc/conn_client.c:275 [inline]
>  rxrpc_prep_call net/rxrpc/conn_client.c:374 [inline]
>  rxrpc_connect_call+0x85c/0x1580 net/rxrpc/conn_client.c:710
>  rxrpc_new_client_call+0x961/0x1020 net/rxrpc/call_object.c:331
>  rxrpc_new_client_call_for_sendmsg net/rxrpc/sendmsg.c:622 [inline]
>  rxrpc_do_sendmsg+0xf14/0x136d net/rxrpc/sendmsg.c:679
>  rxrpc_sendmsg+0x420/0x630 net/rxrpc/af_rxrpc.c:560
>  sock_sendmsg_nosec net/socket.c:651 [inline]
>  sock_sendmsg+0xcf/0x120 net/socket.c:671
>  ____sys_sendmsg+0x331/0x810 net/socket.c:2353
>  ___sys_sendmsg+0xf3/0x170 net/socket.c:2407
>  __sys_sendmmsg+0x195/0x480 net/socket.c:2497
>  __do_sys_sendmmsg net/socket.c:2526 [inline]
>  __se_sys_sendmmsg net/socket.c:2523 [inline]
>  __x64_sys_sendmmsg+0x99/0x100 net/socket.c:2523
>  do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> Freed by task 2642:
>  kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
>  kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
>  kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
>  __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
>  __cache_free mm/slab.c:3418 [inline]
>  kfree+0x10e/0x2b0 mm/slab.c:3756
>  rxrpc_put_bundle net/rxrpc/conn_client.c:146 [inline]
>  rxrpc_put_bundle+0x6b/0x80 net/rxrpc/conn_client.c:138
>  rxrpc_unbundle_conn+0x1f8/0x3d0 net/rxrpc/conn_client.c:935
>  rxrpc_clean_up_local_conns+0x38d/0x587 net/rxrpc/conn_client.c:1114
>  rxrpc_local_destroyer net/rxrpc/local_object.c:399 [inline]
>  rxrpc_local_processor+0x38d/0x5e0 net/rxrpc/local_object.c:433
>  process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
>  worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
>  kthread+0x3b5/0x4a0 kernel/kthread.c:292
>  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
> 
> The buggy address belongs to the object at ffff8880a8669200
>  which belongs to the cache kmalloc-192 of size 192
> The buggy address is located 32 bytes inside of
>  192-byte region [ffff8880a8669200, ffff8880a86692c0)
> The buggy address belongs to the page:
> page:000000007bfb6cde refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff8880a8669d00 pfn:0xa8669
> flags: 0xfffe0000000200(slab)
> raw: 00fffe0000000200 ffffea0002a42f88 ffffea00027d8f08 ffff8880aa040000
> raw: ffff8880a8669d00 ffff8880a8669000 000000010000000d 0000000000000000
> page dumped because: kasan: bad access detected
> 
> Memory state around the buggy address:
>  ffff8880a8669100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>  ffff8880a8669180: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
> >ffff8880a8669200: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>                                ^
>  ffff8880a8669280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>  ffff8880a8669300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ==================================================================


Fix 245500d853e9 ("rxrpc: Rewrite the client connection manager")
by dropping bundle's usage count if it's erased from the RB tree.
Because it's bumped up on RB inserting.

--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -928,11 +928,11 @@ static void rxrpc_unbundle_conn(struct r
 		if (i == ARRAY_SIZE(bundle->conns) && !bundle->params.exclusive) {
 			_debug("erase bundle");
 			rb_erase(&bundle->local_node, &local->client_bundles);
+			/* pair with get on inserting bundle in rb tree */
+			rxrpc_put_bundle(bundle);
 		}
 
 		spin_unlock(&local->client_bundles_lock);
-		if (i == ARRAY_SIZE(bundle->conns))
-			rxrpc_put_bundle(bundle);
 	}
 
 	if (need_drop)



From syzbot+18d51774588492bf3f69 at syzkaller.appspotmail.com  Mon Sep 21 06:32:13 2020
From: syzbot+18d51774588492bf3f69 at syzkaller.appspotmail.com (syzbot)
Date: Mon, 21 Sep 2020 03:32:13 -0700
Subject: KASAN: use-after-free Read in afs_manage_cell
Message-ID: <00000000000012d56705afd05d8b@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    b652d2a5 Add linux-next specific files for 20200918
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=10fbecad900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=3cf0782933432b43
dashboard link: https://syzkaller.appspot.com/bug?extid=18d51774588492bf3f69
compiler:       gcc (GCC) 10.1.0-syz 20200507

Unfortunately, I don't have any reproducer for this issue yet.

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+18d51774588492bf3f69 at syzkaller.appspotmail.com

==================================================================
BUG: KASAN: use-after-free in afs_activate_cell fs/afs/cell.c:622 [inline]
BUG: KASAN: use-after-free in afs_manage_cell+0xf9d/0x11c0 fs/afs/cell.c:697
Read of size 8 at addr ffff888096141a20 by task kworker/1:6/20450

CPU: 1 PID: 20450 Comm: kworker/1:6 Not tainted 5.9.0-rc5-next-20200918-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: afs afs_manage_cell
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fb lib/dump_stack.c:118
 print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:385
 __kasan_report mm/kasan/report.c:545 [inline]
 kasan_report.cold+0x1f/0x37 mm/kasan/report.c:562
 afs_activate_cell fs/afs/cell.c:622 [inline]
 afs_manage_cell+0xf9d/0x11c0 fs/afs/cell.c:697
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 process_scheduled_works kernel/workqueue.c:2331 [inline]
 worker_thread+0x82b/0x1120 kernel/workqueue.c:2417
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

Allocated by task 5410:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
 kmem_cache_alloc_trace+0x1a0/0x480 mm/slab.c:3548
 kmalloc include/linux/slab.h:554 [inline]
 kzalloc include/linux/slab.h:666 [inline]
 afs_alloc_cell fs/afs/cell.c:151 [inline]
 afs_lookup_cell+0x5b8/0x1450 fs/afs/cell.c:262
 afs_parse_source fs/afs/super.c:290 [inline]
 afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
 vfs_parse_fs_param fs/fs_context.c:117 [inline]
 vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
 vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
 generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
 do_new_mount fs/namespace.c:2892 [inline]
 path_mount+0x1266/0x1e70 fs/namespace.c:3216
 do_mount fs/namespace.c:3229 [inline]
 __do_sys_mount fs/namespace.c:3437 [inline]
 __se_sys_mount fs/namespace.c:3414 [inline]
 __x64_sys_mount+0x27f/0x300 fs/namespace.c:3414
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 6900:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
 kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
 __cache_free mm/slab.c:3416 [inline]
 kfree+0x10e/0x2a0 mm/slab.c:3754
 rcu_do_batch kernel/rcu/tree.c:2482 [inline]
 rcu_core+0x621/0x11d0 kernel/rcu/tree.c:2717
 __do_softirq+0x203/0xab6 kernel/softirq.c:298

Last call_rcu():
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_record_aux_stack+0x82/0xb0 mm/kasan/generic.c:346
 __call_rcu kernel/rcu/tree.c:2959 [inline]
 call_rcu+0x15e/0x7d0 kernel/rcu/tree.c:3033
 afs_manage_cell+0x250/0x11c0 fs/afs/cell.c:751
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

The buggy address belongs to the object at ffff888096141800
 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 544 bytes inside of
 1024-byte region [ffff888096141800, ffff888096141c00)
The buggy address belongs to the page:
page:0000000010db85d7 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x96141
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea00024a9e48 ffffea000088a308 ffff8880aa040700
raw: 0000000000000000 ffff888096141000 0000000100000002 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888096141900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888096141980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888096141a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                               ^
 ffff888096141a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888096141b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.


From syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com  Mon Sep 21 06:33:17 2020
From: syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com (syzbot)
Date: Mon, 21 Sep 2020 03:33:17 -0700
Subject: KASAN: use-after-free Read in afs_deactivate_cell (2)
Message-ID: <000000000000e82e1a05afd0605d@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    325d0eab Merge branch 'akpm' (patches from Andrew)
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15ec729b900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=8d39f8ae68f9dcd5
dashboard link: https://syzkaller.appspot.com/bug?extid=a5e4946b04d6ca8fa5f3
compiler:       gcc (GCC) 10.1.0-syz 20200507

Unfortunately, I don't have any reproducer for this issue yet.

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com

==================================================================
BUG: KASAN: use-after-free in __hlist_del include/linux/list.h:826 [inline]
BUG: KASAN: use-after-free in hlist_del_rcu include/linux/rculist.h:487 [inline]
BUG: KASAN: use-after-free in afs_deactivate_cell+0x165/0x1a0 fs/afs/cell.c:647
Read of size 8 at addr ffff888090699880 by task kworker/0:3/7433

CPU: 0 PID: 7433 Comm: kworker/0:3 Not tainted 5.9.0-rc5-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: afs afs_manage_cell
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fd lib/dump_stack.c:118
 print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:383
 __kasan_report mm/kasan/report.c:513 [inline]
 kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
 __hlist_del include/linux/list.h:826 [inline]
 hlist_del_rcu include/linux/rculist.h:487 [inline]
 afs_deactivate_cell+0x165/0x1a0 fs/afs/cell.c:647
 afs_manage_cell+0x326/0x11c0 fs/afs/cell.c:721
 process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
 process_scheduled_works kernel/workqueue.c:2331 [inline]
 worker_thread+0x82b/0x1120 kernel/workqueue.c:2417
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294

Allocated by task 19085:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
 kmem_cache_alloc_trace+0x174/0x300 mm/slab.c:3550
 kmalloc include/linux/slab.h:554 [inline]
 kzalloc include/linux/slab.h:666 [inline]
 afs_alloc_cell fs/afs/cell.c:151 [inline]
 afs_lookup_cell+0x5c8/0x1440 fs/afs/cell.c:262
 afs_parse_source fs/afs/super.c:290 [inline]
 afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
 vfs_parse_fs_param fs/fs_context.c:117 [inline]
 vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
 vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
 generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
 do_new_mount fs/namespace.c:2871 [inline]
 path_mount+0x133f/0x20a0 fs/namespace.c:3192
 do_mount fs/namespace.c:3205 [inline]
 __do_sys_mount fs/namespace.c:3413 [inline]
 __se_sys_mount fs/namespace.c:3390 [inline]
 __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 9:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
 kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
 __cache_free mm/slab.c:3418 [inline]
 kfree+0x10e/0x2b0 mm/slab.c:3756
 rcu_do_batch kernel/rcu/tree.c:2428 [inline]
 rcu_core+0x5ca/0x1130 kernel/rcu/tree.c:2656
 __do_softirq+0x1f8/0xb23 kernel/softirq.c:298

Last call_rcu():
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_record_aux_stack+0x82/0xb0 mm/kasan/generic.c:346
 __call_rcu kernel/rcu/tree.c:2894 [inline]
 call_rcu+0x15e/0x7c0 kernel/rcu/tree.c:2968
 afs_manage_cell+0x250/0x11c0 fs/afs/cell.c:751
 process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294

The buggy address belongs to the object at ffff888090699800
 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 128 bytes inside of
 1024-byte region [ffff888090699800, ffff888090699c00)
The buggy address belongs to the page:
page:00000000d3e3a7d0 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x90699
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea0002558fc8 ffffea0001240988 ffff8880aa040700
raw: 0000000000000000 ffff888090699000 0000000100000002 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888090699780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888090699800: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888090699880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                   ^
 ffff888090699900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888090699980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.


From jaltman at auristor.com  Tue Sep 22 22:15:45 2020
From: jaltman at auristor.com (Jeffrey E Altman)
Date: Tue, 22 Sep 2020 22:15:45 -0400
Subject: SDC'20 Linux Kernel AFS BoF - Wednesday 3pm PDT
Message-ID: <30f14836-4d70-99f6-69e2-2faefc25a7a1@auristor.com>

Apologies for the late notice but I didn't find out until this evening
that SDC'20 BoFs would be open to the public.  Conference registration
is not required.

Wednesday 23 Sept 2020 3pm PDT

To join the Slack channel create a Slack account at

  https://www.snia.org/sdcbofspace

To join the Zoom use

  https://zoom.us/j/93098619297?pwd=TXhPSG1wWXFyYjExclFIOFJxM2xoUT09

Meeting ID: 930 9861 9297
Passcode: 204360

One tap mobile
+13017158592,,93098619297#,,,,,,0#,,204360# US (Germantown)
+13126266799,,93098619297#,,,,,,0#,,204360# US (Chicago)

Dial by your location
+1 301 715 8592 US (Germantown)
+1 312 626 6799 US (Chicago)
+1 646 558 8656 US (New York)
+1 253 215 8782 US (Tacoma)
+1 346 248 7799 US (Houston)
+1 669 900 9128 US (San Jose)
Find your local number: https://zoom.us/u/aMpmQ3yRk


-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4033 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/linux-afs/attachments/20200922/9db2a1df/attachment.p7s>

From syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com  Thu Sep 24 05:26:27 2020
From: syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com (syzbot)
Date: Thu, 24 Sep 2020 02:26:27 -0700
Subject: general protection fault in strncasecmp
Message-ID: <000000000000650d4005b00bcb0c@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    98477740 Merge branch 'rcu/urgent' of git://git.kernel.org..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15b4d887900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=5f4c828c9e3cef97
dashboard link: https://syzkaller.appspot.com/bug?extid=459a5dce0b4cb70fd076
compiler:       gcc (GCC) 10.1.0-syz 20200507
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=125d46c5900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16c58f8b900000

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com

general protection fault, probably for non-canonical address 0xf27d208691691fdb: 0000 [#1] PREEMPT SMP KASAN
KASAN: maybe wild-memory-access in range [0x93e924348b48fed8-0x93e924348b48fedf]
CPU: 1 PID: 10071 Comm: syz-executor152 Not tainted 5.9.0-rc6-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:strncasecmp lib/string.c:52 [inline]
RIP: 0010:strncasecmp+0x5f/0x240 lib/string.c:43
Code: 00 40 38 ce 0f 85 ec 01 00 00 4c 39 e2 0f 84 11 01 00 00 4c 89 fe 4c 89 e7 49 83 c4 01 48 89 f8 48 89 f9 48 c1 e8 03 83 e1 07 <42> 0f b6 04 28 38 c8 7f 08 84 c0 0f 85 0f 01 00 00 41 0f b6 6c 24
RSP: 0018:ffffc9000ba7f958 EFLAGS: 00010202
RAX: 127d248691691fdb RBX: dffffc0000000000 RCX: 0000000000000001
RDX: 93e924348b48fee3 RSI: ffff8880a1a65401 RDI: 93e924348b48fed9
RBP: 0000000000000009 R08: 000000000000002e R09: 0000000000000025
R10: 0000000000000000 R11: 0000000000000005 R12: 93e924348b48feda
R13: dffffc0000000000 R14: 00000000000000e7 R15: ffffffff82ddbcd0
FS:  00007fd01e732700(0000) GS:ffff8880ae500000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004cdb30 CR3: 00000000929cd000 CR4: 00000000001506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 afs_lookup_cell_rcu+0x313/0x720 fs/afs/cell.c:88
 afs_lookup_cell+0x2ee/0x1440 fs/afs/cell.c:249
 afs_parse_source fs/afs/super.c:290 [inline]
 afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
 vfs_parse_fs_param fs/fs_context.c:117 [inline]
 vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
 vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
 generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
 do_new_mount fs/namespace.c:2871 [inline]
 path_mount+0x133f/0x20a0 fs/namespace.c:3192
 do_mount fs/namespace.c:3205 [inline]
 __do_sys_mount fs/namespace.c:3413 [inline]
 __se_sys_mount fs/namespace.c:3390 [inline]
 __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x44d57a
Code: b8 a6 00 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 bd 9f fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 0f 83 9a 9f fb ff c3 66 0f 1f 84 00 00 00 00 00
RSP: 002b:00007fd01e731c48 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007fd01e731c90 RCX: 000000000044d57a
RDX: 0000000020000000 RSI: 0000000020000040 RDI: 0000000000000000
RBP: 0000000000000000 R08: 00007fd01e731c90 R09: 00007fd01e732700
R10: 0000000000000000 R11: 0000000000000246 R12: 00007fd01e7326d0
R13: 00007ffd130bca8f R14: 00007fd01e7329c0 R15: 0000000000000000
Modules linked in:
---[ end trace d103c481405d6a99 ]---
RIP: 0010:strncasecmp lib/string.c:52 [inline]
RIP: 0010:strncasecmp+0x5f/0x240 lib/string.c:43
Code: 00 40 38 ce 0f 85 ec 01 00 00 4c 39 e2 0f 84 11 01 00 00 4c 89 fe 4c 89 e7 49 83 c4 01 48 89 f8 48 89 f9 48 c1 e8 03 83 e1 07 <42> 0f b6 04 28 38 c8 7f 08 84 c0 0f 85 0f 01 00 00 41 0f b6 6c 24
RSP: 0018:ffffc9000ba7f958 EFLAGS: 00010202
RAX: 127d248691691fdb RBX: dffffc0000000000 RCX: 0000000000000001
RDX: 93e924348b48fee3 RSI: ffff8880a1a65401 RDI: 93e924348b48fed9
RBP: 0000000000000009 R08: 000000000000002e R09: 0000000000000025
R10: 0000000000000000 R11: 0000000000000005 R12: 93e924348b48feda
R13: dffffc0000000000 R14: 00000000000000e7 R15: ffffffff82ddbcd0
FS:  00007fd01e732700(0000) GS:ffff8880ae500000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fb63ee2c000 CR3: 00000000929cd000 CR4: 00000000001506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
syzbot can test patches for this issue, for details see:
https://goo.gl/tpsmEJ#testing-patches


From syzbot+1ecc2f9d3387f1d79d42 at syzkaller.appspotmail.com  Thu Sep 24 05:40:22 2020
From: syzbot+1ecc2f9d3387f1d79d42 at syzkaller.appspotmail.com (syzbot)
Date: Thu, 24 Sep 2020 02:40:22 -0700
Subject: KASAN: use-after-free Write in afs_deactivate_cell
Message-ID: <0000000000002b775d05b00bfdee@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    e6499702 Add linux-next specific files for 20200922
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=129f3cc3900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=fe45fda2f2c0a56a
dashboard link: https://syzkaller.appspot.com/bug?extid=1ecc2f9d3387f1d79d42
compiler:       gcc (GCC) 10.1.0-syz 20200507

Unfortunately, I don't have any reproducer for this issue yet.

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+1ecc2f9d3387f1d79d42 at syzkaller.appspotmail.com

==================================================================
BUG: KASAN: use-after-free in __hlist_del include/linux/list.h:831 [inline]
BUG: KASAN: use-after-free in hlist_del_rcu include/linux/rculist.h:514 [inline]
BUG: KASAN: use-after-free in afs_deactivate_cell+0x19a/0x1a0 fs/afs/cell.c:647
Write of size 8 at addr ffff8880979a2088 by task kworker/0:8/11772

CPU: 0 PID: 11772 Comm: kworker/0:8 Not tainted 5.9.0-rc6-next-20200922-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: afs afs_manage_cell
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fb lib/dump_stack.c:118
 print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:385
 __kasan_report mm/kasan/report.c:545 [inline]
 kasan_report.cold+0x1f/0x37 mm/kasan/report.c:562
 __hlist_del include/linux/list.h:831 [inline]
 hlist_del_rcu include/linux/rculist.h:514 [inline]
 afs_deactivate_cell+0x19a/0x1a0 fs/afs/cell.c:647
 afs_manage_cell+0x326/0x11c0 fs/afs/cell.c:721
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

Allocated by task 15153:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
 kmem_cache_alloc_trace+0x1a0/0x480 mm/slab.c:3548
 kmalloc include/linux/slab.h:554 [inline]
 kzalloc include/linux/slab.h:666 [inline]
 afs_alloc_cell fs/afs/cell.c:151 [inline]
 afs_lookup_cell+0x5b8/0x1450 fs/afs/cell.c:262
 afs_parse_source fs/afs/super.c:290 [inline]
 afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
 vfs_parse_fs_param fs/fs_context.c:117 [inline]
 vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
 vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
 generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
 do_new_mount fs/namespace.c:2892 [inline]
 path_mount+0x1266/0x1e70 fs/namespace.c:3227
 do_mount fs/namespace.c:3240 [inline]
 __do_sys_mount fs/namespace.c:3448 [inline]
 __se_sys_mount fs/namespace.c:3425 [inline]
 __x64_sys_mount+0x27f/0x300 fs/namespace.c:3425
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 3147:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
 kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
 __cache_free mm/slab.c:3416 [inline]
 kfree+0x10e/0x2a0 mm/slab.c:3754
 rcu_do_batch kernel/rcu/tree.c:2484 [inline]
 rcu_core+0x621/0x11d0 kernel/rcu/tree.c:2719
 __do_softirq+0x203/0xab6 kernel/softirq.c:298

Last call_rcu():
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_record_aux_stack+0x82/0xb0 mm/kasan/generic.c:346
 __call_rcu kernel/rcu/tree.c:2961 [inline]
 call_rcu+0x15e/0x7d0 kernel/rcu/tree.c:3035
 afs_manage_cell+0x250/0x11c0 fs/afs/cell.c:751
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

Second to last call_rcu():
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_record_aux_stack+0x82/0xb0 mm/kasan/generic.c:346
 __call_rcu kernel/rcu/tree.c:2961 [inline]
 call_rcu+0x15e/0x7d0 kernel/rcu/tree.c:3035
 in6_dev_finish_destroy+0x143/0x1b0 net/ipv6/addrconf_core.c:264
 in6_dev_put include/net/addrconf.h:379 [inline]
 addrconf_ifdown.isra.0+0x12af/0x1590 net/ipv6/addrconf.c:3848
 addrconf_notify+0x55c/0x2310 net/ipv6/addrconf.c:3627
 notifier_call_chain+0xb5/0x200 kernel/notifier.c:83
 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:2034
 call_netdevice_notifiers_extack net/core/dev.c:2046 [inline]
 call_netdevice_notifiers net/core/dev.c:2060 [inline]
 rollback_registered_many+0x97f/0x1550 net/core/dev.c:9331
 unregister_netdevice_many.part.0+0x1a/0x2f0 net/core/dev.c:10484
 unregister_netdevice_many net/core/dev.c:10483 [inline]
 default_device_exit_batch+0x30c/0x3d0 net/core/dev.c:10967
 ops_exit_list+0x10d/0x160 net/core/net_namespace.c:189
 cleanup_net+0x4ea/0xb10 net/core/net_namespace.c:603
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

The buggy address belongs to the object at ffff8880979a2000
 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 136 bytes inside of
 1024-byte region [ffff8880979a2000, ffff8880979a2400)
The buggy address belongs to the page:
page:0000000003e82d85 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x979a2
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea000279b408 ffffea000251f108 ffff8880aa040700
raw: 0000000000000000 ffff8880979a2000 0000000100000002 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff8880979a1f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff8880979a2000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff8880979a2080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                      ^
 ffff8880979a2100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8880979a2180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.


From hdanton at sina.com  Thu Sep 24 09:40:52 2020
From: hdanton at sina.com (Hillf Danton)
Date: Thu, 24 Sep 2020 21:40:52 +0800
Subject: general protection fault in strncasecmp
In-Reply-To: <000000000000650d4005b00bcb0c@google.com>
References: <000000000000650d4005b00bcb0c@google.com>
Message-ID: <20200924134052.1156-1-hdanton@sina.com>


On Thu, 24 Sep 2020 02:26:27 -0700
> syzbot found the following issue on:
> 
> HEAD commit:    98477740 Merge branch 'rcu/urgent' of git://git.kernel.org..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=15b4d887900000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=5f4c828c9e3cef97
> dashboard link: https://syzkaller.appspot.com/bug?extid=459a5dce0b4cb70fd076
> compiler:       gcc (GCC) 10.1.0-syz 20200507
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=125d46c5900000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16c58f8b900000
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com
> 
> general protection fault, probably for non-canonical address 0xf27d208691691fdb: 0000 [#1] PREEMPT SMP KASAN
> KASAN: maybe wild-memory-access in range [0x93e924348b48fed8-0x93e924348b48fedf]
> CPU: 1 PID: 10071 Comm: syz-executor152 Not tainted 5.9.0-rc6-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> RIP: 0010:strncasecmp lib/string.c:52 [inline]
> RIP: 0010:strncasecmp+0x5f/0x240 lib/string.c:43
> Code: 00 40 38 ce 0f 85 ec 01 00 00 4c 39 e2 0f 84 11 01 00 00 4c 89 fe 4c 89 e7 49 83 c4 01 48 89 f8 48 89 f9 48 c1 e8 03 83 e1 07 <42> 0f b6 04 28 38 c8 7f 08 84 c0 0f 85 0f 01 00 00 41 0f b6 6c 24
> RSP: 0018:ffffc9000ba7f958 EFLAGS: 00010202
> RAX: 127d248691691fdb RBX: dffffc0000000000 RCX: 0000000000000001
> RDX: 93e924348b48fee3 RSI: ffff8880a1a65401 RDI: 93e924348b48fed9
> RBP: 0000000000000009 R08: 000000000000002e R09: 0000000000000025
> R10: 0000000000000000 R11: 0000000000000005 R12: 93e924348b48feda
> R13: dffffc0000000000 R14: 00000000000000e7 R15: ffffffff82ddbcd0
> FS:  00007fd01e732700(0000) GS:ffff8880ae500000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00000000004cdb30 CR3: 00000000929cd000 CR4: 00000000001506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
>  afs_lookup_cell_rcu+0x313/0x720 fs/afs/cell.c:88
>  afs_lookup_cell+0x2ee/0x1440 fs/afs/cell.c:249
>  afs_parse_source fs/afs/super.c:290 [inline]
>  afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
>  vfs_parse_fs_param fs/fs_context.c:117 [inline]
>  vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
>  vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
>  generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
>  do_new_mount fs/namespace.c:2871 [inline]
>  path_mount+0x133f/0x20a0 fs/namespace.c:3192
>  do_mount fs/namespace.c:3205 [inline]
>  __do_sys_mount fs/namespace.c:3413 [inline]
>  __se_sys_mount fs/namespace.c:3390 [inline]
>  __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390
>  do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>  entry_SYSCALL_64_after_hwframe+0x44/0xa9


Bump up cell's usage count before anything important and skip it in
case of failure to do so.

--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -85,6 +85,20 @@ struct afs_cell *afs_lookup_cell_rcu(str
 		while (p) {
 			cell = rb_entry(p, struct afs_cell, net_node);
 
+			/*
+			 * care to detect writers because
+			 *
+			 * read_seqbegin_or_lock(&net->cells_lock, &seq);
+			 *
+			 * is unable to block 
+			 *
+			 * write_seqlock(&net->cells_lock);
+			 *
+			 */
+			if (!atomic_inc_not_zero(&cell->usage)) {
+				cell = NULL;
+				break;
+			}
 			n = strncasecmp(cell->name, name,
 					min_t(size_t, cell->name_len, namesz));
 			if (n == 0)
@@ -94,17 +108,11 @@ struct afs_cell *afs_lookup_cell_rcu(str
 			} else if (n > 0) {
 				p = rcu_dereference_raw(p->rb_right);
 			} else {
-				if (atomic_inc_not_zero(&cell->usage)) {
-					ret = 0;
-					break;
-				}
-				/* We want to repeat the search, this time with
-				 * the lock properly locked.
-				 */
+				ret = 0;
+				break;
 			}
 			cell = NULL;
 		}
-
 	} while (need_seqretry(&net->cells_lock, seq));
 
 	done_seqretry(&net->cells_lock, seq);



From syzbot+0e0db88e1eb44a91ae8d at syzkaller.appspotmail.com  Mon Sep 28 03:37:16 2020
From: syzbot+0e0db88e1eb44a91ae8d at syzkaller.appspotmail.com (syzbot)
Date: Mon, 28 Sep 2020 00:37:16 -0700
Subject: KASAN: use-after-free Read in __proc_create
Message-ID: <00000000000057f8db05b05abc47@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    7c7ec322 Merge tag 'for-linus' of git://git.kernel.org/pub..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1375b14b900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=6184b75aa6d48d66
dashboard link: https://syzkaller.appspot.com/bug?extid=0e0db88e1eb44a91ae8d
compiler:       clang version 10.0.0 (https://github.com/llvm/llvm-project/ c2443155a0fb245c8f17f2c1c72b6ea391e86e81)

Unfortunately, I don't have any reproducer for this issue yet.

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+0e0db88e1eb44a91ae8d at syzkaller.appspotmail.com

==================================================================
BUG: KASAN: use-after-free in strlen+0x4c/0x60 lib/string.c:544
Read of size 1 at addr ffff8880a29662c0 by task kworker/1:1/23

CPU: 1 PID: 23 Comm: kworker/1:1 Not tainted 5.9.0-rc6-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: afs afs_manage_cell
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x1d6/0x29e lib/dump_stack.c:118
 print_address_description+0x66/0x620 mm/kasan/report.c:383
 __kasan_report mm/kasan/report.c:513 [inline]
 kasan_report+0x132/0x1d0 mm/kasan/report.c:530
 strlen+0x4c/0x60 lib/string.c:544
 __proc_create+0x28d/0xb60 fs/proc/generic.c:399
 proc_mkdir_data+0x84/0x160 fs/proc/generic.c:482
 proc_net_mkdir include/linux/proc_fs.h:201 [inline]
 afs_proc_cell_setup+0xaf/0x180 fs/afs/proc.c:620
 afs_activate_cell fs/afs/cell.c:615 [inline]
 afs_manage_cell+0x7db/0x1540 fs/afs/cell.c:697
 process_one_work+0x789/0xfc0 kernel/workqueue.c:2269
 process_scheduled_works kernel/workqueue.c:2331 [inline]
 worker_thread+0xde4/0x1460 kernel/workqueue.c:2417
 kthread+0x37e/0x3a0 drivers/block/aoe/aoecmd.c:1234
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294

Allocated by task 8801:
 kasan_save_stack mm/kasan/common.c:48 [inline]
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc+0x100/0x130 mm/kasan/common.c:461
 __do_kmalloc mm/slab.c:3655 [inline]
 __kmalloc+0x205/0x300 mm/slab.c:3664
 kmalloc include/linux/slab.h:559 [inline]
 afs_alloc_cell fs/afs/cell.c:157 [inline]
 afs_lookup_cell+0x4d2/0x14d0 fs/afs/cell.c:262
 afs_parse_source fs/afs/super.c:290 [inline]
 afs_parse_param+0x526/0x790 fs/afs/super.c:326
 vfs_parse_fs_param+0x1e5/0x460 fs/fs_context.c:117
 vfs_parse_fs_string fs/fs_context.c:161 [inline]
 generic_parse_monolithic+0x230/0x350 fs/fs_context.c:201
 do_new_mount fs/namespace.c:2871 [inline]
 path_mount+0x176c/0x29e0 fs/namespace.c:3192
 do_mount fs/namespace.c:3205 [inline]
 __do_sys_mount fs/namespace.c:3413 [inline]
 __se_sys_mount+0x126/0x180 fs/namespace.c:3390
 do_syscall_64+0x31/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 8668:
 kasan_save_stack mm/kasan/common.c:48 [inline]
 kasan_set_track+0x3d/0x70 mm/kasan/common.c:56
 kasan_set_free_info+0x17/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xdd/0x110 mm/kasan/common.c:422
 __cache_free mm/slab.c:3418 [inline]
 kfree+0x113/0x200 mm/slab.c:3756
 afs_cell_destroy+0x16b/0x240 fs/afs/cell.c:500
 rcu_do_batch kernel/rcu/tree.c:2430 [inline]
 rcu_core+0x79b/0x1130 kernel/rcu/tree.c:2658
 __do_softirq+0x256/0x6d5 kernel/softirq.c:298

The buggy address belongs to the object at ffff8880a29662c0
 which belongs to the cache kmalloc-32 of size 32
The buggy address is located 0 bytes inside of
 32-byte region [ffff8880a29662c0, ffff8880a29662e0)
The buggy address belongs to the page:
page:00000000f15c0556 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff8880a2966fc1 pfn:0xa2966
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea00028f7d48 ffffea0002a22248 ffff8880aa440100
raw: ffff8880a2966fc1 ffff8880a2966000 000000010000003f 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff8880a2966180: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
 ffff8880a2966200: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
>ffff8880a2966280: 00 00 03 fc fc fc fc fc fa fb fb fb fc fc fc fc
                                           ^
 ffff8880a2966300: 00 07 fc fc fc fc fc fc fa fb fb fb fc fc fc fc
 ffff8880a2966380: fa fb fb fb fc fc fc fc 00 00 00 00 fc fc fc fc
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.


From syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com  Wed Sep 30 04:25:15 2020
From: syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com (syzbot)
Date: Wed, 30 Sep 2020 01:25:15 -0700
Subject: KASAN: use-after-free Read in afs_deactivate_cell (2)
In-Reply-To: <000000000000e82e1a05afd0605d@google.com>
Message-ID: <00000000000096cfce05b083a3a9@google.com>

syzbot has found a reproducer for the following issue on:

HEAD commit:    49e7e3e9 Add linux-next specific files for 20200929
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=12fbf387900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=b823d07e241e7aee
dashboard link: https://syzkaller.appspot.com/bug?extid=a5e4946b04d6ca8fa5f3
compiler:       gcc (GCC) 10.1.0-syz 20200507
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=173c446d900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=14ba5be3900000

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com

==================================================================
BUG: KASAN: use-after-free in __hlist_del include/linux/list.h:826 [inline]
BUG: KASAN: use-after-free in hlist_del_rcu include/linux/rculist.h:514 [inline]
BUG: KASAN: use-after-free in afs_deactivate_cell+0x165/0x1a0 fs/afs/cell.c:647
Read of size 8 at addr ffff888093021080 by task kworker/0:3/2653

CPU: 0 PID: 2653 Comm: kworker/0:3 Not tainted 5.9.0-rc7-next-20200929-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: afs afs_manage_cell
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fb lib/dump_stack.c:118
 print_address_description.constprop.0.cold+0xae/0x497 mm/kasan/report.c:385
 __kasan_report mm/kasan/report.c:545 [inline]
 kasan_report.cold+0x1f/0x37 mm/kasan/report.c:562
 __hlist_del include/linux/list.h:826 [inline]
 hlist_del_rcu include/linux/rculist.h:514 [inline]
 afs_deactivate_cell+0x165/0x1a0 fs/afs/cell.c:647
 afs_manage_cell+0x326/0x11c0 fs/afs/cell.c:721
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

Allocated by task 7905:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track mm/kasan/common.c:56 [inline]
 __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:461
 kmem_cache_alloc_trace+0x1a0/0x480 mm/slab.c:3552
 kmalloc include/linux/slab.h:554 [inline]
 kzalloc include/linux/slab.h:666 [inline]
 afs_alloc_cell fs/afs/cell.c:151 [inline]
 afs_lookup_cell+0x5b8/0x1450 fs/afs/cell.c:262
 afs_parse_source fs/afs/super.c:290 [inline]
 afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
 vfs_parse_fs_param fs/fs_context.c:117 [inline]
 vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
 vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
 generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
 do_new_mount fs/namespace.c:2892 [inline]
 path_mount+0x1266/0x1e70 fs/namespace.c:3227
 __do_sys_mount fs/namespace.c:3438 [inline]
 __se_sys_mount fs/namespace.c:3411 [inline]
 __x64_sys_mount+0x278/0x2f0 fs/namespace.c:3411
 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Freed by task 2653:
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_set_track+0x1c/0x30 mm/kasan/common.c:56
 kasan_set_free_info+0x1b/0x30 mm/kasan/generic.c:355
 __kasan_slab_free+0xd8/0x120 mm/kasan/common.c:422
 __cache_free mm/slab.c:3420 [inline]
 kfree+0x10e/0x2a0 mm/slab.c:3758
 rcu_do_batch kernel/rcu/tree.c:2481 [inline]
 rcu_core+0x645/0x1240 kernel/rcu/tree.c:2715
 __do_softirq+0x203/0xab6 kernel/softirq.c:298

Last call_rcu():
 kasan_save_stack+0x1b/0x40 mm/kasan/common.c:48
 kasan_record_aux_stack+0x82/0xb0 mm/kasan/generic.c:346
 __call_rcu kernel/rcu/tree.c:2957 [inline]
 call_rcu+0x15e/0x7d0 kernel/rcu/tree.c:3030
 afs_manage_cell+0x250/0x11c0 fs/afs/cell.c:751
 process_one_work+0x933/0x15a0 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3af/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296

The buggy address belongs to the object at ffff888093021000
 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 128 bytes inside of
 1024-byte region [ffff888093021000, ffff888093021400)
The buggy address belongs to the page:
page:00000000fb0f011a refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x93021
flags: 0xfffe0000000200(slab)
raw: 00fffe0000000200 ffffea0002992c48 ffffea000249fd08 ffff8880aa040700
raw: 0000000000000000 ffff888093021000 0000000100000002 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888093020f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888093021000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888093021080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                   ^
 ffff888093021100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888093021180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================



From syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com  Wed Sep 30 15:03:04 2020
From: syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com (syzbot)
Date: Wed, 30 Sep 2020 12:03:04 -0700
Subject: KASAN: use-after-free Read in afs_deactivate_cell (2)
In-Reply-To: <000000000000e82e1a05afd0605d@google.com>
Message-ID: <000000000000a1321d05b08c8c9b@google.com>

syzbot has bisected this issue to:

commit 13fcc6837049f1bd76d57e9abc217a91fdbad764
Author: David Howells <dhowells at redhat.com>
Date:   Thu Nov 1 23:07:27 2018 +0000

    afs: Add fs_context support

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=13ea9ea7900000
start commit:   49e7e3e9 Add linux-next specific files for 20200929
git tree:       linux-next
final oops:     https://syzkaller.appspot.com/x/report.txt?x=101a9ea7900000
console output: https://syzkaller.appspot.com/x/log.txt?x=17ea9ea7900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=b823d07e241e7aee
dashboard link: https://syzkaller.appspot.com/bug?extid=a5e4946b04d6ca8fa5f3
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=173c446d900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=14ba5be3900000

Reported-by: syzbot+a5e4946b04d6ca8fa5f3 at syzkaller.appspotmail.com
Fixes: 13fcc6837049 ("afs: Add fs_context support")

For information about bisection process see: https://goo.gl/tpsmEJ#bisection


From jack at suse.cz  Thu Sep 24 05:00:21 2020
From: jack at suse.cz (Jan Kara)
Date: Thu, 24 Sep 2020 11:00:21 +0200
Subject: [PATCH 12/13] udf: Tell the VFS that readpage was synchronous
In-Reply-To: <20200917151050.5363-13-willy@infradead.org>
References: <20200917151050.5363-1-willy@infradead.org>
 <20200917151050.5363-13-willy@infradead.org>
Message-ID: <20200924090021.GE27019@quack2.suse.cz>

On Thu 17-09-20 16:10:49, Matthew Wilcox (Oracle) wrote:
> The udf inline data readpage implementation was already synchronous,
> so use AOP_UPDATED_PAGE to avoid cycling the page lock.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>

Looks good. You can add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza
> ---
>  fs/udf/file.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/fs/udf/file.c b/fs/udf/file.c
> index 628941a6b79a..52bbe92d7c43 100644
> --- a/fs/udf/file.c
> +++ b/fs/udf/file.c
> @@ -61,9 +61,8 @@ static int udf_adinicb_readpage(struct file *file, struct page *page)
>  {
>  	BUG_ON(!PageLocked(page));
>  	__udf_adinicb_readpage(page);
> -	unlock_page(page);
>  
> -	return 0;
> +	return AOP_UPDATED_PAGE;
>  }
>  
>  static int udf_adinicb_writepage(struct page *page,
> -- 
> 2.28.0
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From syzbot+b994ecf2b023f14832c1 at syzkaller.appspotmail.com  Mon Sep 28 03:48:17 2020
From: syzbot+b994ecf2b023f14832c1 at syzkaller.appspotmail.com (syzbot)
Date: Mon, 28 Sep 2020 00:48:17 -0700
Subject: WARNING: proc registration bug in afs_manage_cell
Message-ID: <000000000000b9f2ac05b05ae349@google.com>

Hello,

syzbot found the following issue on:

HEAD commit:    c9c9e6a4 Merge tag 'trace-v5.9-rc5-2' of git://git.kernel...
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=13a34b1d900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=5f4c828c9e3cef97
dashboard link: https://syzkaller.appspot.com/bug?extid=b994ecf2b023f14832c1
compiler:       gcc (GCC) 10.1.0-syz 20200507
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=164ee99b900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=165dd5c5900000

The issue was bisected to:

commit 0e7bbcc104baaade4f64205e9706b7d43c46db7d
Author: Julian Anastasov <ja at ssi.bg>
Date:   Wed Jul 27 06:56:50 2016 +0000

    neigh: allow admin to set NUD_STALE

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=16850bab900000
final oops:     https://syzkaller.appspot.com/x/report.txt?x=15850bab900000
console output: https://syzkaller.appspot.com/x/log.txt?x=11850bab900000

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+b994ecf2b023f14832c1 at syzkaller.appspotmail.com
Fixes: 0e7bbcc104ba ("neigh: allow admin to set NUD_STALE")

------------[ cut here ]------------
proc_dir_entry 'afs/^]$[+.](%{' already registered
WARNING: CPU: 1 PID: 2468 at fs/proc/generic.c:371 proc_register+0x34c/0x700 fs/proc/generic.c:371
Kernel panic - not syncing: panic_on_warn set ...
CPU: 1 PID: 2468 Comm: kworker/1:2 Not tainted 5.9.0-rc6-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: afs afs_manage_cell
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x198/0x1fd lib/dump_stack.c:118
 panic+0x382/0x7fb kernel/panic.c:231
 __warn.cold+0x20/0x4b kernel/panic.c:600
 report_bug+0x1bd/0x210 lib/bug.c:198
 handle_bug+0x38/0x90 arch/x86/kernel/traps.c:234
 exc_invalid_op+0x14/0x40 arch/x86/kernel/traps.c:254
 asm_exc_invalid_op+0x12/0x20 arch/x86/include/asm/idtentry.h:536
RIP: 0010:proc_register+0x34c/0x700 fs/proc/generic.c:371
Code: df 48 89 f9 48 c1 e9 03 80 3c 01 00 0f 85 5d 03 00 00 48 8b 44 24 28 48 c7 c7 60 61 9a 88 48 8b b0 d8 00 00 00 e8 46 1b 5d ff <0f> 0b 48 c7 c7 60 f6 1e 8a e8 76 78 3d 06 48 8b 4c 24 38 48 b8 00
RSP: 0018:ffffc90008387ac8 EFLAGS: 00010282
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: ffff8880a06f0540 RSI: ffffffff815f5985 RDI: fffff52001070f4b
RBP: ffff8880a8237c50 R08: 0000000000000001 R09: ffff8880ae5318e7
R10: 0000000000000000 R11: 0000000000000000 R12: ffff888086ce9d98
R13: ffff888086ce9c40 R14: dffffc0000000000 R15: 000000000000000a
 proc_mkdir_data+0x140/0x1a0 fs/proc/generic.c:487
 proc_net_mkdir include/linux/proc_fs.h:201 [inline]
 afs_proc_cell_setup+0xb2/0x1f0 fs/afs/proc.c:620
 afs_activate_cell fs/afs/cell.c:615 [inline]
 afs_manage_cell+0x56a/0x11c0 fs/afs/cell.c:697
 process_one_work+0x94c/0x1670 kernel/workqueue.c:2269
 worker_thread+0x64c/0x1120 kernel/workqueue.c:2415
 kthread+0x3b5/0x4a0 kernel/kthread.c:292
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294
Kernel Offset: disabled
Rebooting in 86400 seconds..


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller at googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
syzbot can test patches for this issue, for details see:
https://goo.gl/tpsmEJ#testing-patches


From syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com  Mon Sep 28 13:40:05 2020
From: syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com (syzbot)
Date: Mon, 28 Sep 2020 10:40:05 -0700
Subject: general protection fault in strncasecmp
In-Reply-To: <000000000000650d4005b00bcb0c@google.com>
Message-ID: <0000000000002edd5605b0632812@google.com>

syzbot has bisected this issue to:

commit bfd45be0b83e8f711f3abc892850d6047972d127
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue Oct 11 20:52:22 2016 +0000

    kprobes: include <asm/sections.h> instead of <asm-generic/sections.h>

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=1613329d900000
start commit:   98477740 Merge branch 'rcu/urgent' of git://git.kernel.org..
git tree:       upstream
final oops:     https://syzkaller.appspot.com/x/report.txt?x=1513329d900000
console output: https://syzkaller.appspot.com/x/log.txt?x=1113329d900000
kernel config:  https://syzkaller.appspot.com/x/.config?x=5f4c828c9e3cef97
dashboard link: https://syzkaller.appspot.com/bug?extid=459a5dce0b4cb70fd076
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=125d46c5900000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16c58f8b900000

Reported-by: syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com
Fixes: bfd45be0b83e ("kprobes: include <asm/sections.h> instead of <asm-generic/sections.h>")

For information about bisection process see: https://goo.gl/tpsmEJ#bisection


