From: Sasha Levin Date: Tue, 23 Jun 2020 14:07:47 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v5.7.6~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4100bf0e2ee693eb9e041d7761a74aff3584f559;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/net-core-device_rename-use-rwsem-instead-of-a-seqcou.patch b/queue-5.4/net-core-device_rename-use-rwsem-instead-of-a-seqcou.patch new file mode 100644 index 00000000000..8f25725b0a0 --- /dev/null +++ b/queue-5.4/net-core-device_rename-use-rwsem-instead-of-a-seqcou.patch @@ -0,0 +1,160 @@ +From 69175668f0bad4069ccf3023f009967e7d2b71a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2020 16:49:44 +0200 +Subject: net: core: device_rename: Use rwsem instead of a seqcount + +From: Ahmed S. Darwish + +[ Upstream commit 11d6011c2cf29f7c8181ebde6c8bc0c4d83adcd7 ] + +Sequence counters write paths are critical sections that must never be +preempted, and blocking, even for CONFIG_PREEMPTION=n, is not allowed. + +Commit 5dbe7c178d3f ("net: fix kernel deadlock with interface rename and +netdev name retrieval.") handled a deadlock, observed with +CONFIG_PREEMPTION=n, where the devnet_rename seqcount read side was +infinitely spinning: it got scheduled after the seqcount write side +blocked inside its own critical section. + +To fix that deadlock, among other issues, the commit added a +cond_resched() inside the read side section. While this will get the +non-preemptible kernel eventually unstuck, the seqcount reader is fully +exhausting its slice just spinning -- until TIF_NEED_RESCHED is set. + +The fix is also still broken: if the seqcount reader belongs to a +real-time scheduling policy, it can spin forever and the kernel will +livelock. + +Disabling preemption over the seqcount write side critical section will +not work: inside it are a number of GFP_KERNEL allocations and mutex +locking through the drivers/base/ :: device_rename() call chain. + +>From all the above, replace the seqcount with a rwsem. + +Fixes: 5dbe7c178d3f (net: fix kernel deadlock with interface rename and netdev name retrieval.) +Fixes: 30e6c9fa93cf (net: devnet_rename_seq should be a seqcount) +Fixes: c91f6df2db49 (sockopt: Change getsockopt() of SO_BINDTODEVICE to return an interface name) +Cc: +Reported-by: kbuild test robot [ v1 missing up_read() on error exit ] +Reported-by: Dan Carpenter [ v1 missing up_read() on error exit ] +Signed-off-by: Ahmed S. Darwish +Reviewed-by: Sebastian Andrzej Siewior +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 40 ++++++++++++++++++---------------------- + 1 file changed, 18 insertions(+), 22 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index b127f022d8bd9..204d87e7c9b19 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -79,6 +79,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -194,7 +195,7 @@ static DEFINE_SPINLOCK(napi_hash_lock); + static unsigned int napi_gen_id = NR_CPUS; + static DEFINE_READ_MOSTLY_HASHTABLE(napi_hash, 8); + +-static seqcount_t devnet_rename_seq; ++static DECLARE_RWSEM(devnet_rename_sem); + + static inline void dev_base_seq_inc(struct net *net) + { +@@ -816,33 +817,28 @@ EXPORT_SYMBOL(dev_get_by_napi_id); + * @net: network namespace + * @name: a pointer to the buffer where the name will be stored. + * @ifindex: the ifindex of the interface to get the name from. +- * +- * The use of raw_seqcount_begin() and cond_resched() before +- * retrying is required as we want to give the writers a chance +- * to complete when CONFIG_PREEMPTION is not set. + */ + int netdev_get_name(struct net *net, char *name, int ifindex) + { + struct net_device *dev; +- unsigned int seq; ++ int ret; + +-retry: +- seq = raw_seqcount_begin(&devnet_rename_seq); ++ down_read(&devnet_rename_sem); + rcu_read_lock(); ++ + dev = dev_get_by_index_rcu(net, ifindex); + if (!dev) { +- rcu_read_unlock(); +- return -ENODEV; ++ ret = -ENODEV; ++ goto out; + } + + strcpy(name, dev->name); +- rcu_read_unlock(); +- if (read_seqcount_retry(&devnet_rename_seq, seq)) { +- cond_resched(); +- goto retry; +- } + +- return 0; ++ ret = 0; ++out: ++ rcu_read_unlock(); ++ up_read(&devnet_rename_sem); ++ return ret; + } + + /** +@@ -1115,10 +1111,10 @@ int dev_change_name(struct net_device *dev, const char *newname) + likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) + return -EBUSY; + +- write_seqcount_begin(&devnet_rename_seq); ++ down_write(&devnet_rename_sem); + + if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { +- write_seqcount_end(&devnet_rename_seq); ++ up_write(&devnet_rename_sem); + return 0; + } + +@@ -1126,7 +1122,7 @@ int dev_change_name(struct net_device *dev, const char *newname) + + err = dev_get_valid_name(net, dev, newname); + if (err < 0) { +- write_seqcount_end(&devnet_rename_seq); ++ up_write(&devnet_rename_sem); + return err; + } + +@@ -1141,11 +1137,11 @@ rollback: + if (ret) { + memcpy(dev->name, oldname, IFNAMSIZ); + dev->name_assign_type = old_assign_type; +- write_seqcount_end(&devnet_rename_seq); ++ up_write(&devnet_rename_sem); + return ret; + } + +- write_seqcount_end(&devnet_rename_seq); ++ up_write(&devnet_rename_sem); + + netdev_adjacent_rename_links(dev, oldname); + +@@ -1166,7 +1162,7 @@ rollback: + /* err >= 0 after dev_alloc_name() or stores the first errno */ + if (err >= 0) { + err = ret; +- write_seqcount_begin(&devnet_rename_seq); ++ down_write(&devnet_rename_sem); + memcpy(dev->name, oldname, IFNAMSIZ); + memcpy(oldname, newname, IFNAMSIZ); + dev->name_assign_type = old_assign_type; +-- +2.25.1 + diff --git a/queue-5.4/sched-rt-net-use-config_preemption.patch.patch b/queue-5.4/sched-rt-net-use-config_preemption.patch.patch new file mode 100644 index 00000000000..9f497489d3b --- /dev/null +++ b/queue-5.4/sched-rt-net-use-config_preemption.patch.patch @@ -0,0 +1,45 @@ +From 70271c251b13ae20eafb1173b8273e864a60d419 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Oct 2019 21:18:08 +0200 +Subject: sched/rt, net: Use CONFIG_PREEMPTION.patch + +From: Thomas Gleixner + +[ Upstream commit 2da2b32fd9346009e9acdb68c570ca8d3966aba7 ] + +CONFIG_PREEMPTION is selected by CONFIG_PREEMPT and by CONFIG_PREEMPT_RT. +Both PREEMPT and PREEMPT_RT require the same functionality which today +depends on CONFIG_PREEMPT. + +Update the comment to use CONFIG_PREEMPTION. + +Signed-off-by: Thomas Gleixner +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Thomas Gleixner +Acked-by: David S. Miller +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: netdev@vger.kernel.org +Link: https://lore.kernel.org/r/20191015191821.11479-22-bigeasy@linutronix.de +Signed-off-by: Ingo Molnar +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 8552874e5aac1..b127f022d8bd9 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -819,7 +819,7 @@ EXPORT_SYMBOL(dev_get_by_napi_id); + * + * The use of raw_seqcount_begin() and cond_resched() before + * retrying is required as we want to give the writers a chance +- * to complete when CONFIG_PREEMPT is not set. ++ * to complete when CONFIG_PREEMPTION is not set. + */ + int netdev_get_name(struct net *net, char *name, int ifindex) + { +-- +2.25.1 + diff --git a/queue-5.4/series b/queue-5.4/series index c2c384667c4..786fd7d267e 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -310,3 +310,5 @@ kretprobe-prevent-triggering-kretprobe-from-within-kprobe_flush_task.patch e1000e-do-not-wake-up-the-system-via-wol-if-device-wakeup-is-disabled.patch net-octeon-mgmt-repair-filling-of-rx-ring.patch pwm-jz4740-enhance-precision-in-calculation-of-duty-cycle.patch +sched-rt-net-use-config_preemption.patch.patch +net-core-device_rename-use-rwsem-instead-of-a-seqcou.patch