]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Sun, 13 Oct 2024 02:48:16 +0000 (22:48 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 13 Oct 2024 02:48:16 +0000 (22:48 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
14 files changed:
queue-4.19/bluetooth-rfcomm-fix-possible-deadlock-in-rfcomm_sk_.patch [new file with mode: 0644]
queue-4.19/clk-add-devm_-clk_get_optional-functions.patch [new file with mode: 0644]
queue-4.19/clk-generalize-devm_clk_get-a-bit.patch [new file with mode: 0644]
queue-4.19/clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch [new file with mode: 0644]
queue-4.19/gpio-aspeed-add-the-flush-write-to-ensure-the-write-.patch [new file with mode: 0644]
queue-4.19/gpio-aspeed-use-devm_clk-api-to-manage-clock-source.patch [new file with mode: 0644]
queue-4.19/igb-do-not-bring-the-device-up-after-non-fatal-error.patch [new file with mode: 0644]
queue-4.19/net-ibm-emac-mal-fix-wrong-goto.patch [new file with mode: 0644]
queue-4.19/netfilter-br_netfilter-fix-panic-with-metadata_dst-s.patch [new file with mode: 0644]
queue-4.19/nfs-remove-print_overflow_msg.patch [new file with mode: 0644]
queue-4.19/ppp-fix-ppp_async_encode-illegal-access.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/sunrpc-fix-integer-overflow-in-decode_rc_list.patch [new file with mode: 0644]
queue-4.19/tcp-fix-tcp_enter_recovery-to-zero-retrans_stamp-whe.patch [new file with mode: 0644]

diff --git a/queue-4.19/bluetooth-rfcomm-fix-possible-deadlock-in-rfcomm_sk_.patch b/queue-4.19/bluetooth-rfcomm-fix-possible-deadlock-in-rfcomm_sk_.patch
new file mode 100644 (file)
index 0000000..68c462c
--- /dev/null
@@ -0,0 +1,51 @@
+From 4dd4d2d7c091dd321be9b4381fd15e7e07759530 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Sep 2024 13:26:21 -0400
+Subject: Bluetooth: RFCOMM: FIX possible deadlock in rfcomm_sk_state_change
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 08d1914293dae38350b8088980e59fbc699a72fe ]
+
+rfcomm_sk_state_change attempts to use sock_lock so it must never be
+called with it locked but rfcomm_sock_ioctl always attempt to lock it
+causing the following trace:
+
+======================================================
+WARNING: possible circular locking dependency detected
+6.8.0-syzkaller-08951-gfe46a7dd189e #0 Not tainted
+------------------------------------------------------
+syz-executor386/5093 is trying to acquire lock:
+ffff88807c396258 (sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1671 [inline]
+ffff88807c396258 (sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM){+.+.}-{0:0}, at: rfcomm_sk_state_change+0x5b/0x310 net/bluetooth/rfcomm/sock.c:73
+
+but task is already holding lock:
+ffff88807badfd28 (&d->lock){+.+.}-{3:3}, at: __rfcomm_dlc_close+0x226/0x6a0 net/bluetooth/rfcomm/core.c:491
+
+Reported-by: syzbot+d7ce59b06b3eb14fd218@syzkaller.appspotmail.com
+Tested-by: syzbot+d7ce59b06b3eb14fd218@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=d7ce59b06b3eb14fd218
+Fixes: 3241ad820dbb ("[Bluetooth] Add timestamp support to L2CAP, RFCOMM and SCO")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/rfcomm/sock.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index 78830efe89d73..8f53cc0d9682a 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -872,9 +872,7 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
+       if (err == -ENOIOCTLCMD) {
+ #ifdef CONFIG_BT_RFCOMM_TTY
+-              lock_sock(sk);
+               err = rfcomm_dev_ioctl(sk, cmd, (void __user *) arg);
+-              release_sock(sk);
+ #else
+               err = -EOPNOTSUPP;
+ #endif
+-- 
+2.43.0
+
diff --git a/queue-4.19/clk-add-devm_-clk_get_optional-functions.patch b/queue-4.19/clk-add-devm_-clk_get_optional-functions.patch
new file mode 100644 (file)
index 0000000..82c0227
--- /dev/null
@@ -0,0 +1,129 @@
+From 95fb980022b8dca629ee43003bb5204f7af43f85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Dec 2018 11:13:09 +0000
+Subject: clk: Add (devm_)clk_get_optional() functions
+
+From: Phil Edworthy <phil.edworthy@renesas.com>
+
+[ Upstream commit 60b8f0ddf1a927ef02141a6610fd52575134f821 ]
+
+This adds clk_get_optional() and devm_clk_get_optional() functions to get
+optional clocks.
+
+They behave the same as (devm_)clk_get() except where there is no clock
+producer. In this case, instead of returning -ENOENT, the function
+returns NULL. This makes error checking simpler and allows
+clk_prepare_enable, etc to be called on the returned reference
+without additional checks.
+
+Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: Russell King <linux@armlinux.org.uk>
+[sboyd@kernel.org: Document in devres.txt]
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: a6191a3d1811 ("gpio: aspeed: Use devm_clk api to manage clock source")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-model/devres.txt |  1 +
+ drivers/clk/clk-devres.c              | 11 ++++++++
+ include/linux/clk.h                   | 36 +++++++++++++++++++++++++++
+ 3 files changed, 48 insertions(+)
+
+diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
+index 43681ca0837f8..5a2d8c7ce2474 100644
+--- a/Documentation/driver-model/devres.txt
++++ b/Documentation/driver-model/devres.txt
+@@ -235,6 +235,7 @@ certainly invest a bit more effort into libata core layer).
+ CLOCK
+   devm_clk_get()
++  devm_clk_get_optional()
+   devm_clk_put()
+   devm_clk_hw_register()
+   devm_of_clk_add_hw_provider()
+diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
+index d854e26a8ddbc..a062389ccd3d5 100644
+--- a/drivers/clk/clk-devres.c
++++ b/drivers/clk/clk-devres.c
+@@ -34,6 +34,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
+ }
+ EXPORT_SYMBOL(devm_clk_get);
++struct clk *devm_clk_get_optional(struct device *dev, const char *id)
++{
++      struct clk *clk = devm_clk_get(dev, id);
++
++      if (clk == ERR_PTR(-ENOENT))
++              return NULL;
++
++      return clk;
++}
++EXPORT_SYMBOL(devm_clk_get_optional);
++
+ struct clk_bulk_devres {
+       struct clk_bulk_data *clks;
+       int num_clks;
+diff --git a/include/linux/clk.h b/include/linux/clk.h
+index 0a2382d3f68c8..55b08adaaa3c1 100644
+--- a/include/linux/clk.h
++++ b/include/linux/clk.h
+@@ -388,6 +388,17 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+  */
+ struct clk *devm_clk_get(struct device *dev, const char *id);
++/**
++ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
++ *                       clock producer.
++ * @dev: device for clock "consumer"
++ * @id: clock consumer ID
++ *
++ * Behaves the same as devm_clk_get() except where there is no clock producer.
++ * In this case, instead of returning -ENOENT, the function returns NULL.
++ */
++struct clk *devm_clk_get_optional(struct device *dev, const char *id);
++
+ /**
+  * devm_get_clk_from_child - lookup and obtain a managed reference to a
+  *                         clock producer from child node.
+@@ -655,6 +666,12 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
+       return NULL;
+ }
++static inline struct clk *devm_clk_get_optional(struct device *dev,
++                                              const char *id)
++{
++      return NULL;
++}
++
+ static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+                                                struct clk_bulk_data *clks)
+ {
+@@ -774,6 +791,25 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
+       clk_bulk_unprepare(num_clks, clks);
+ }
++/**
++ * clk_get_optional - lookup and obtain a reference to an optional clock
++ *                  producer.
++ * @dev: device for clock "consumer"
++ * @id: clock consumer ID
++ *
++ * Behaves the same as clk_get() except where there is no clock producer. In
++ * this case, instead of returning -ENOENT, the function returns NULL.
++ */
++static inline struct clk *clk_get_optional(struct device *dev, const char *id)
++{
++      struct clk *clk = clk_get(dev, id);
++
++      if (clk == ERR_PTR(-ENOENT))
++              return NULL;
++
++      return clk;
++}
++
+ #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
+ struct clk *of_clk_get(struct device_node *np, int index);
+ struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
+-- 
+2.43.0
+
diff --git a/queue-4.19/clk-generalize-devm_clk_get-a-bit.patch b/queue-4.19/clk-generalize-devm_clk_get-a-bit.patch
new file mode 100644 (file)
index 0000000..5908cdb
--- /dev/null
@@ -0,0 +1,124 @@
+From 1583f97aa966964d56d12a7d4ce0600fc0357956 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 May 2022 09:57:35 +0200
+Subject: clk: generalize devm_clk_get() a bit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit abae8e57e49aa75f6db76aa866c775721523908f ]
+
+Allow to add an exit hook to devm managed clocks. Also use
+clk_get_optional() in devm_clk_get_optional instead of open coding it.
+The generalisation will be used in the next commit to add some more
+devm_clk helpers.
+
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Alexandru Ardelean <aardelean@deviqon.com>
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20220520075737.758761-3-u.kleine-koenig@pengutronix.de
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: a6191a3d1811 ("gpio: aspeed: Use devm_clk api to manage clock source")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk-devres.c | 66 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 49 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
+index a062389ccd3d5..3a45b4d0d502d 100644
+--- a/drivers/clk/clk-devres.c
++++ b/drivers/clk/clk-devres.c
+@@ -9,39 +9,71 @@
+ #include <linux/export.h>
+ #include <linux/gfp.h>
++struct devm_clk_state {
++      struct clk *clk;
++      void (*exit)(struct clk *clk);
++};
++
+ static void devm_clk_release(struct device *dev, void *res)
+ {
+-      clk_put(*(struct clk **)res);
++      struct devm_clk_state *state = *(struct devm_clk_state **)res;
++
++      if (state->exit)
++              state->exit(state->clk);
++
++      clk_put(state->clk);
+ }
+-struct clk *devm_clk_get(struct device *dev, const char *id)
++static struct clk *__devm_clk_get(struct device *dev, const char *id,
++                                struct clk *(*get)(struct device *dev, const char *id),
++                                int (*init)(struct clk *clk),
++                                void (*exit)(struct clk *clk))
+ {
+-      struct clk **ptr, *clk;
++      struct devm_clk_state *state;
++      struct clk *clk;
++      int ret;
+-      ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+-      if (!ptr)
++      state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
++      if (!state)
+               return ERR_PTR(-ENOMEM);
+-      clk = clk_get(dev, id);
+-      if (!IS_ERR(clk)) {
+-              *ptr = clk;
+-              devres_add(dev, ptr);
+-      } else {
+-              devres_free(ptr);
++      clk = get(dev, id);
++      if (IS_ERR(clk)) {
++              ret = PTR_ERR(clk);
++              goto err_clk_get;
+       }
++      if (init) {
++              ret = init(clk);
++              if (ret)
++                      goto err_clk_init;
++      }
++
++      state->clk = clk;
++      state->exit = exit;
++
++      devres_add(dev, state);
++
+       return clk;
++
++err_clk_init:
++
++      clk_put(clk);
++err_clk_get:
++
++      devres_free(state);
++      return ERR_PTR(ret);
++}
++
++struct clk *devm_clk_get(struct device *dev, const char *id)
++{
++      return __devm_clk_get(dev, id, clk_get, NULL, NULL);
+ }
+ EXPORT_SYMBOL(devm_clk_get);
+ struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+ {
+-      struct clk *clk = devm_clk_get(dev, id);
+-
+-      if (clk == ERR_PTR(-ENOENT))
+-              return NULL;
+-
+-      return clk;
++      return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
+ }
+ EXPORT_SYMBOL(devm_clk_get_optional);
+-- 
+2.43.0
+
diff --git a/queue-4.19/clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch b/queue-4.19/clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch
new file mode 100644 (file)
index 0000000..19efda7
--- /dev/null
@@ -0,0 +1,214 @@
+From 06cb2e94f188cb1eecbb0b6138cc1ec2257a3e1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 May 2022 09:57:36 +0200
+Subject: clk: Provide new devm_clk helpers for prepared and enabled clocks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 7ef9651e9792b08eb310c6beb202cbc947f43cab ]
+
+When a driver keeps a clock prepared (or enabled) during the whole
+lifetime of the driver, these helpers allow to simplify the drivers.
+
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Alexandru Ardelean <aardelean@deviqon.com>
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20220520075737.758761-4-u.kleine-koenig@pengutronix.de
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: a6191a3d1811 ("gpio: aspeed: Use devm_clk api to manage clock source")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk-devres.c |  27 ++++++++++
+ include/linux/clk.h      | 109 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 136 insertions(+)
+
+diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
+index 3a45b4d0d502d..cec0e58d92d65 100644
+--- a/drivers/clk/clk-devres.c
++++ b/drivers/clk/clk-devres.c
+@@ -71,12 +71,39 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
+ }
+ EXPORT_SYMBOL(devm_clk_get);
++struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
++{
++      return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
++}
++EXPORT_SYMBOL_GPL(devm_clk_get_prepared);
++
++struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
++{
++      return __devm_clk_get(dev, id, clk_get,
++                            clk_prepare_enable, clk_disable_unprepare);
++}
++EXPORT_SYMBOL_GPL(devm_clk_get_enabled);
++
+ struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+ {
+       return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
+ }
+ EXPORT_SYMBOL(devm_clk_get_optional);
++struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
++{
++      return __devm_clk_get(dev, id, clk_get_optional,
++                            clk_prepare, clk_unprepare);
++}
++EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);
++
++struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
++{
++      return __devm_clk_get(dev, id, clk_get_optional,
++                            clk_prepare_enable, clk_disable_unprepare);
++}
++EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
++
+ struct clk_bulk_devres {
+       struct clk_bulk_data *clks;
+       int num_clks;
+diff --git a/include/linux/clk.h b/include/linux/clk.h
+index 55b08adaaa3c1..fb4c86360e5ad 100644
+--- a/include/linux/clk.h
++++ b/include/linux/clk.h
+@@ -388,6 +388,47 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+  */
+ struct clk *devm_clk_get(struct device *dev, const char *id);
++/**
++ * devm_clk_get_prepared - devm_clk_get() + clk_prepare()
++ * @dev: device for clock "consumer"
++ * @id: clock consumer ID
++ *
++ * Context: May sleep.
++ *
++ * Return: a struct clk corresponding to the clock producer, or
++ * valid IS_ERR() condition containing errno.  The implementation
++ * uses @dev and @id to determine the clock consumer, and thereby
++ * the clock producer.  (IOW, @id may be identical strings, but
++ * clk_get may return different clock producers depending on @dev.)
++ *
++ * The returned clk (if valid) is prepared. Drivers must however assume
++ * that the clock is not enabled.
++ *
++ * The clock will automatically be unprepared and freed when the device
++ * is unbound from the bus.
++ */
++struct clk *devm_clk_get_prepared(struct device *dev, const char *id);
++
++/**
++ * devm_clk_get_enabled - devm_clk_get() + clk_prepare_enable()
++ * @dev: device for clock "consumer"
++ * @id: clock consumer ID
++ *
++ * Context: May sleep.
++ *
++ * Return: a struct clk corresponding to the clock producer, or
++ * valid IS_ERR() condition containing errno.  The implementation
++ * uses @dev and @id to determine the clock consumer, and thereby
++ * the clock producer.  (IOW, @id may be identical strings, but
++ * clk_get may return different clock producers depending on @dev.)
++ *
++ * The returned clk (if valid) is prepared and enabled.
++ *
++ * The clock will automatically be disabled, unprepared and freed
++ * when the device is unbound from the bus.
++ */
++struct clk *devm_clk_get_enabled(struct device *dev, const char *id);
++
+ /**
+  * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+  *                       clock producer.
+@@ -399,6 +440,50 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
+  */
+ struct clk *devm_clk_get_optional(struct device *dev, const char *id);
++/**
++ * devm_clk_get_optional_prepared - devm_clk_get_optional() + clk_prepare()
++ * @dev: device for clock "consumer"
++ * @id: clock consumer ID
++ *
++ * Context: May sleep.
++ *
++ * Return: a struct clk corresponding to the clock producer, or
++ * valid IS_ERR() condition containing errno.  The implementation
++ * uses @dev and @id to determine the clock consumer, and thereby
++ * the clock producer.  If no such clk is found, it returns NULL
++ * which serves as a dummy clk.  That's the only difference compared
++ * to devm_clk_get_prepared().
++ *
++ * The returned clk (if valid) is prepared. Drivers must however
++ * assume that the clock is not enabled.
++ *
++ * The clock will automatically be unprepared and freed when the
++ * device is unbound from the bus.
++ */
++struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id);
++
++/**
++ * devm_clk_get_optional_enabled - devm_clk_get_optional() +
++ *                                 clk_prepare_enable()
++ * @dev: device for clock "consumer"
++ * @id: clock consumer ID
++ *
++ * Context: May sleep.
++ *
++ * Return: a struct clk corresponding to the clock producer, or
++ * valid IS_ERR() condition containing errno.  The implementation
++ * uses @dev and @id to determine the clock consumer, and thereby
++ * the clock producer.  If no such clk is found, it returns NULL
++ * which serves as a dummy clk.  That's the only difference compared
++ * to devm_clk_get_enabled().
++ *
++ * The returned clk (if valid) is prepared and enabled.
++ *
++ * The clock will automatically be disabled, unprepared and freed
++ * when the device is unbound from the bus.
++ */
++struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id);
++
+ /**
+  * devm_get_clk_from_child - lookup and obtain a managed reference to a
+  *                         clock producer from child node.
+@@ -666,12 +751,36 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
+       return NULL;
+ }
++static inline struct clk *devm_clk_get_prepared(struct device *dev,
++                                              const char *id)
++{
++      return NULL;
++}
++
++static inline struct clk *devm_clk_get_enabled(struct device *dev,
++                                             const char *id)
++{
++      return NULL;
++}
++
+ static inline struct clk *devm_clk_get_optional(struct device *dev,
+                                               const char *id)
+ {
+       return NULL;
+ }
++static inline struct clk *devm_clk_get_optional_prepared(struct device *dev,
++                                                       const char *id)
++{
++      return NULL;
++}
++
++static inline struct clk *devm_clk_get_optional_enabled(struct device *dev,
++                                                      const char *id)
++{
++      return NULL;
++}
++
+ static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+                                                struct clk_bulk_data *clks)
+ {
+-- 
+2.43.0
+
diff --git a/queue-4.19/gpio-aspeed-add-the-flush-write-to-ensure-the-write-.patch b/queue-4.19/gpio-aspeed-add-the-flush-write-to-ensure-the-write-.patch
new file mode 100644 (file)
index 0000000..b6b7ca8
--- /dev/null
@@ -0,0 +1,44 @@
+From c336c9f98eb83f2b7f0956f9a95f4fa22c9801b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Oct 2024 16:14:44 +0800
+Subject: gpio: aspeed: Add the flush write to ensure the write complete.
+
+From: Billy Tsai <billy_tsai@aspeedtech.com>
+
+[ Upstream commit 1bb5a99e1f3fd27accb804aa0443a789161f843c ]
+
+Performing a dummy read ensures that the register write operation is fully
+completed, mitigating any potential bus delays that could otherwise impact
+the frequency of bitbang usage. E.g., if the JTAG application uses GPIO to
+control the JTAG pins (TCK, TMS, TDI, TDO, and TRST), and the application
+sets the TCK clock to 1 MHz, the GPIO's high/low transitions will rely on
+a delay function to ensure the clock frequency does not exceed 1 MHz.
+However, this can lead to rapid toggling of the GPIO because the write
+operation is POSTed and does not wait for a bus acknowledgment.
+
+Fixes: 361b79119a4b ("gpio: Add Aspeed driver")
+Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
+Link: https://lore.kernel.org/r/20241008081450.1490955-2-billy_tsai@aspeedtech.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-aspeed.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index ba1cd971d50b6..5cc80678ac352 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -407,6 +407,8 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
+       gpio->dcache[GPIO_BANK(offset)] = reg;
+       iowrite32(reg, addr);
++      /* Flush write */
++      ioread32(addr);
+ }
+ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
+-- 
+2.43.0
+
diff --git a/queue-4.19/gpio-aspeed-use-devm_clk-api-to-manage-clock-source.patch b/queue-4.19/gpio-aspeed-use-devm_clk-api-to-manage-clock-source.patch
new file mode 100644 (file)
index 0000000..b2d3fdc
--- /dev/null
@@ -0,0 +1,37 @@
+From 4519ac5ee265d3c03cb6248dd9d29badb61dc5cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Oct 2024 16:14:45 +0800
+Subject: gpio: aspeed: Use devm_clk api to manage clock source
+
+From: Billy Tsai <billy_tsai@aspeedtech.com>
+
+[ Upstream commit a6191a3d18119184237f4ee600039081ad992320 ]
+
+Replace of_clk_get with devm_clk_get_enabled to manage the clock source.
+
+Fixes: 5ae4cb94b313 ("gpio: aspeed: Add debounce support")
+Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>
+Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
+Link: https://lore.kernel.org/r/20241008081450.1490955-3-billy_tsai@aspeedtech.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-aspeed.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index 5cc80678ac352..cab3d9a4018ab 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -1176,7 +1176,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+       if (!gpio_id)
+               return -EINVAL;
+-      gpio->clk = of_clk_get(pdev->dev.of_node, 0);
++      gpio->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+       if (IS_ERR(gpio->clk)) {
+               dev_warn(&pdev->dev,
+                               "Failed to get clock from devicetree, debouncing disabled\n");
+-- 
+2.43.0
+
diff --git a/queue-4.19/igb-do-not-bring-the-device-up-after-non-fatal-error.patch b/queue-4.19/igb-do-not-bring-the-device-up-after-non-fatal-error.patch
new file mode 100644 (file)
index 0000000..2bd91aa
--- /dev/null
@@ -0,0 +1,96 @@
+From 8a8386bf8ad87733b52024e3700f93961b426d37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Sep 2024 15:06:01 -0600
+Subject: igb: Do not bring the device up after non-fatal error
+
+From: Mohamed Khalfella <mkhalfella@purestorage.com>
+
+[ Upstream commit 330a699ecbfc9c26ec92c6310686da1230b4e7eb ]
+
+Commit 004d25060c78 ("igb: Fix igb_down hung on surprise removal")
+changed igb_io_error_detected() to ignore non-fatal pcie errors in order
+to avoid hung task that can happen when igb_down() is called multiple
+times. This caused an issue when processing transient non-fatal errors.
+igb_io_resume(), which is called after igb_io_error_detected(), assumes
+that device is brought down by igb_io_error_detected() if the interface
+is up. This resulted in panic with stacktrace below.
+
+[ T3256] igb 0000:09:00.0 haeth0: igb: haeth0 NIC Link is Down
+[  T292] pcieport 0000:00:1c.5: AER: Uncorrected (Non-Fatal) error received: 0000:09:00.0
+[  T292] igb 0000:09:00.0: PCIe Bus Error: severity=Uncorrected (Non-Fatal), type=Transaction Layer, (Requester ID)
+[  T292] igb 0000:09:00.0:   device [8086:1537] error status/mask=00004000/00000000
+[  T292] igb 0000:09:00.0:    [14] CmpltTO [  200.105524,009][  T292] igb 0000:09:00.0: AER:   TLP Header: 00000000 00000000 00000000 00000000
+[  T292] pcieport 0000:00:1c.5: AER: broadcast error_detected message
+[  T292] igb 0000:09:00.0: Non-correctable non-fatal error reported.
+[  T292] pcieport 0000:00:1c.5: AER: broadcast mmio_enabled message
+[  T292] pcieport 0000:00:1c.5: AER: broadcast resume message
+[  T292] ------------[ cut here ]------------
+[  T292] kernel BUG at net/core/dev.c:6539!
+[  T292] invalid opcode: 0000 [#1] PREEMPT SMP
+[  T292] RIP: 0010:napi_enable+0x37/0x40
+[  T292] Call Trace:
+[  T292]  <TASK>
+[  T292]  ? die+0x33/0x90
+[  T292]  ? do_trap+0xdc/0x110
+[  T292]  ? napi_enable+0x37/0x40
+[  T292]  ? do_error_trap+0x70/0xb0
+[  T292]  ? napi_enable+0x37/0x40
+[  T292]  ? napi_enable+0x37/0x40
+[  T292]  ? exc_invalid_op+0x4e/0x70
+[  T292]  ? napi_enable+0x37/0x40
+[  T292]  ? asm_exc_invalid_op+0x16/0x20
+[  T292]  ? napi_enable+0x37/0x40
+[  T292]  igb_up+0x41/0x150
+[  T292]  igb_io_resume+0x25/0x70
+[  T292]  report_resume+0x54/0x70
+[  T292]  ? report_frozen_detected+0x20/0x20
+[  T292]  pci_walk_bus+0x6c/0x90
+[  T292]  ? aer_print_port_info+0xa0/0xa0
+[  T292]  pcie_do_recovery+0x22f/0x380
+[  T292]  aer_process_err_devices+0x110/0x160
+[  T292]  aer_isr+0x1c1/0x1e0
+[  T292]  ? disable_irq_nosync+0x10/0x10
+[  T292]  irq_thread_fn+0x1a/0x60
+[  T292]  irq_thread+0xe3/0x1a0
+[  T292]  ? irq_set_affinity_notifier+0x120/0x120
+[  T292]  ? irq_affinity_notify+0x100/0x100
+[  T292]  kthread+0xe2/0x110
+[  T292]  ? kthread_complete_and_exit+0x20/0x20
+[  T292]  ret_from_fork+0x2d/0x50
+[  T292]  ? kthread_complete_and_exit+0x20/0x20
+[  T292]  ret_from_fork_asm+0x11/0x20
+[  T292]  </TASK>
+
+To fix this issue igb_io_resume() checks if the interface is running and
+the device is not down this means igb_io_error_detected() did not bring
+the device down and there is no need to bring it up.
+
+Signed-off-by: Mohamed Khalfella <mkhalfella@purestorage.com>
+Reviewed-by: Yuanyuan Zhong <yzhong@purestorage.com>
+Fixes: 004d25060c78 ("igb: Fix igb_down hung on surprise removal")
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igb/igb_main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 01138fc93ea10..3a65dccc08ba8 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -9151,6 +9151,10 @@ static void igb_io_resume(struct pci_dev *pdev)
+       struct igb_adapter *adapter = netdev_priv(netdev);
+       if (netif_running(netdev)) {
++              if (!test_bit(__IGB_DOWN, &adapter->state)) {
++                      dev_dbg(&pdev->dev, "Resuming from non-fatal error, do nothing.\n");
++                      return;
++              }
+               if (igb_up(adapter)) {
+                       dev_err(&pdev->dev, "igb_up failed after reset\n");
+                       return;
+-- 
+2.43.0
+
diff --git a/queue-4.19/net-ibm-emac-mal-fix-wrong-goto.patch b/queue-4.19/net-ibm-emac-mal-fix-wrong-goto.patch
new file mode 100644 (file)
index 0000000..7d122b0
--- /dev/null
@@ -0,0 +1,36 @@
+From c0ca70380a1ae91a910ef8c9a52753d8ebf99a2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Oct 2024 16:57:11 -0700
+Subject: net: ibm: emac: mal: fix wrong goto
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit 08c8acc9d8f3f70d62dd928571368d5018206490 ]
+
+dcr_map is called in the previous if and therefore needs to be unmapped.
+
+Fixes: 1ff0fcfcb1a6 ("ibm_newemac: Fix new MAL feature handling")
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://patch.msgid.link/20241007235711.5714-1-rosenp@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/emac/mal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
+index fff09dcf9e346..9b3ba4db3222f 100644
+--- a/drivers/net/ethernet/ibm/emac/mal.c
++++ b/drivers/net/ethernet/ibm/emac/mal.c
+@@ -581,7 +581,7 @@ static int mal_probe(struct platform_device *ofdev)
+               printk(KERN_ERR "%pOF: Support for 405EZ not enabled!\n",
+                               ofdev->dev.of_node);
+               err = -ENODEV;
+-              goto fail;
++              goto fail_unmap;
+ #endif
+       }
+-- 
+2.43.0
+
diff --git a/queue-4.19/netfilter-br_netfilter-fix-panic-with-metadata_dst-s.patch b/queue-4.19/netfilter-br_netfilter-fix-panic-with-metadata_dst-s.patch
new file mode 100644 (file)
index 0000000..16f3b7f
--- /dev/null
@@ -0,0 +1,179 @@
+From 647ce0012b65a215e2a3807ab3a6e5754afc6fbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 08:43:59 -0700
+Subject: netfilter: br_netfilter: fix panic with metadata_dst skb
+
+From: Andy Roulin <aroulin@nvidia.com>
+
+[ Upstream commit f9ff7665cd128012868098bbd07e28993e314fdb ]
+
+Fix a kernel panic in the br_netfilter module when sending untagged
+traffic via a VxLAN device.
+This happens during the check for fragmentation in br_nf_dev_queue_xmit.
+
+It is dependent on:
+1) the br_netfilter module being loaded;
+2) net.bridge.bridge-nf-call-iptables set to 1;
+3) a bridge with a VxLAN (single-vxlan-device) netdevice as a bridge port;
+4) untagged frames with size higher than the VxLAN MTU forwarded/flooded
+
+When forwarding the untagged packet to the VxLAN bridge port, before
+the netfilter hooks are called, br_handle_egress_vlan_tunnel is called and
+changes the skb_dst to the tunnel dst. The tunnel_dst is a metadata type
+of dst, i.e., skb_valid_dst(skb) is false, and metadata->dst.dev is NULL.
+
+Then in the br_netfilter hooks, in br_nf_dev_queue_xmit, there's a check
+for frames that needs to be fragmented: frames with higher MTU than the
+VxLAN device end up calling br_nf_ip_fragment, which in turns call
+ip_skb_dst_mtu.
+
+The ip_dst_mtu tries to use the skb_dst(skb) as if it was a valid dst
+with valid dst->dev, thus the crash.
+
+This case was never supported in the first place, so drop the packet
+instead.
+
+PING 10.0.0.2 (10.0.0.2) from 0.0.0.0 h1-eth0: 2000(2028) bytes of data.
+[  176.291791] Unable to handle kernel NULL pointer dereference at
+virtual address 0000000000000110
+[  176.292101] Mem abort info:
+[  176.292184]   ESR = 0x0000000096000004
+[  176.292322]   EC = 0x25: DABT (current EL), IL = 32 bits
+[  176.292530]   SET = 0, FnV = 0
+[  176.292709]   EA = 0, S1PTW = 0
+[  176.292862]   FSC = 0x04: level 0 translation fault
+[  176.293013] Data abort info:
+[  176.293104]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
+[  176.293488]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
+[  176.293787]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[  176.293995] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000043ef5000
+[  176.294166] [0000000000000110] pgd=0000000000000000,
+p4d=0000000000000000
+[  176.294827] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
+[  176.295252] Modules linked in: vxlan ip6_udp_tunnel udp_tunnel veth
+br_netfilter bridge stp llc ipv6 crct10dif_ce
+[  176.295923] CPU: 0 PID: 188 Comm: ping Not tainted
+6.8.0-rc3-g5b3fbd61b9d1 #2
+[  176.296314] Hardware name: linux,dummy-virt (DT)
+[  176.296535] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS
+BTYPE=--)
+[  176.296808] pc : br_nf_dev_queue_xmit+0x390/0x4ec [br_netfilter]
+[  176.297382] lr : br_nf_dev_queue_xmit+0x2ac/0x4ec [br_netfilter]
+[  176.297636] sp : ffff800080003630
+[  176.297743] x29: ffff800080003630 x28: 0000000000000008 x27:
+ffff6828c49ad9f8
+[  176.298093] x26: ffff6828c49ad000 x25: 0000000000000000 x24:
+00000000000003e8
+[  176.298430] x23: 0000000000000000 x22: ffff6828c4960b40 x21:
+ffff6828c3b16d28
+[  176.298652] x20: ffff6828c3167048 x19: ffff6828c3b16d00 x18:
+0000000000000014
+[  176.298926] x17: ffffb0476322f000 x16: ffffb7e164023730 x15:
+0000000095744632
+[  176.299296] x14: ffff6828c3f1c880 x13: 0000000000000002 x12:
+ffffb7e137926a70
+[  176.299574] x11: 0000000000000001 x10: ffff6828c3f1c898 x9 :
+0000000000000000
+[  176.300049] x8 : ffff6828c49bf070 x7 : 0008460f18d5f20e x6 :
+f20e0100bebafeca
+[  176.300302] x5 : ffff6828c7f918fe x4 : ffff6828c49bf070 x3 :
+0000000000000000
+[  176.300586] x2 : 0000000000000000 x1 : ffff6828c3c7ad00 x0 :
+ffff6828c7f918f0
+[  176.300889] Call trace:
+[  176.301123]  br_nf_dev_queue_xmit+0x390/0x4ec [br_netfilter]
+[  176.301411]  br_nf_post_routing+0x2a8/0x3e4 [br_netfilter]
+[  176.301703]  nf_hook_slow+0x48/0x124
+[  176.302060]  br_forward_finish+0xc8/0xe8 [bridge]
+[  176.302371]  br_nf_hook_thresh+0x124/0x134 [br_netfilter]
+[  176.302605]  br_nf_forward_finish+0x118/0x22c [br_netfilter]
+[  176.302824]  br_nf_forward_ip.part.0+0x264/0x290 [br_netfilter]
+[  176.303136]  br_nf_forward+0x2b8/0x4e0 [br_netfilter]
+[  176.303359]  nf_hook_slow+0x48/0x124
+[  176.303803]  __br_forward+0xc4/0x194 [bridge]
+[  176.304013]  br_flood+0xd4/0x168 [bridge]
+[  176.304300]  br_handle_frame_finish+0x1d4/0x5c4 [bridge]
+[  176.304536]  br_nf_hook_thresh+0x124/0x134 [br_netfilter]
+[  176.304978]  br_nf_pre_routing_finish+0x29c/0x494 [br_netfilter]
+[  176.305188]  br_nf_pre_routing+0x250/0x524 [br_netfilter]
+[  176.305428]  br_handle_frame+0x244/0x3cc [bridge]
+[  176.305695]  __netif_receive_skb_core.constprop.0+0x33c/0xecc
+[  176.306080]  __netif_receive_skb_one_core+0x40/0x8c
+[  176.306197]  __netif_receive_skb+0x18/0x64
+[  176.306369]  process_backlog+0x80/0x124
+[  176.306540]  __napi_poll+0x38/0x17c
+[  176.306636]  net_rx_action+0x124/0x26c
+[  176.306758]  __do_softirq+0x100/0x26c
+[  176.307051]  ____do_softirq+0x10/0x1c
+[  176.307162]  call_on_irq_stack+0x24/0x4c
+[  176.307289]  do_softirq_own_stack+0x1c/0x2c
+[  176.307396]  do_softirq+0x54/0x6c
+[  176.307485]  __local_bh_enable_ip+0x8c/0x98
+[  176.307637]  __dev_queue_xmit+0x22c/0xd28
+[  176.307775]  neigh_resolve_output+0xf4/0x1a0
+[  176.308018]  ip_finish_output2+0x1c8/0x628
+[  176.308137]  ip_do_fragment+0x5b4/0x658
+[  176.308279]  ip_fragment.constprop.0+0x48/0xec
+[  176.308420]  __ip_finish_output+0xa4/0x254
+[  176.308593]  ip_finish_output+0x34/0x130
+[  176.308814]  ip_output+0x6c/0x108
+[  176.308929]  ip_send_skb+0x50/0xf0
+[  176.309095]  ip_push_pending_frames+0x30/0x54
+[  176.309254]  raw_sendmsg+0x758/0xaec
+[  176.309568]  inet_sendmsg+0x44/0x70
+[  176.309667]  __sys_sendto+0x110/0x178
+[  176.309758]  __arm64_sys_sendto+0x28/0x38
+[  176.309918]  invoke_syscall+0x48/0x110
+[  176.310211]  el0_svc_common.constprop.0+0x40/0xe0
+[  176.310353]  do_el0_svc+0x1c/0x28
+[  176.310434]  el0_svc+0x34/0xb4
+[  176.310551]  el0t_64_sync_handler+0x120/0x12c
+[  176.310690]  el0t_64_sync+0x190/0x194
+[  176.311066] Code: f9402e61 79402aa2 927ff821 f9400023 (f9408860)
+[  176.315743] ---[ end trace 0000000000000000 ]---
+[  176.316060] Kernel panic - not syncing: Oops: Fatal exception in
+interrupt
+[  176.316371] Kernel Offset: 0x37e0e3000000 from 0xffff800080000000
+[  176.316564] PHYS_OFFSET: 0xffff97d780000000
+[  176.316782] CPU features: 0x0,88000203,3c020000,0100421b
+[  176.317210] Memory Limit: none
+[  176.317527] ---[ end Kernel panic - not syncing: Oops: Fatal
+Exception in interrupt ]---\
+
+Fixes: 11538d039ac6 ("bridge: vlan dst_metadata hooks in ingress and egress paths")
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Andy Roulin <aroulin@nvidia.com>
+Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20241001154400.22787-2-aroulin@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_netfilter_hooks.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index 35642dc96852a..75e35fae6f244 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -37,6 +37,7 @@
+ #include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/addrconf.h>
++#include <net/dst_metadata.h>
+ #include <net/route.h>
+ #include <net/netfilter/br_netfilter.h>
+ #include <net/netns/generic.h>
+@@ -737,6 +738,10 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff
+               return br_dev_queue_push_xmit(net, sk, skb);
+       }
++      /* Fragmentation on metadata/template dst is not supported */
++      if (unlikely(!skb_valid_dst(skb)))
++              goto drop;
++
+       /* This is wrong! We should preserve the original fragment
+        * boundaries by preserving frag_list rather than refragmenting.
+        */
+-- 
+2.43.0
+
diff --git a/queue-4.19/nfs-remove-print_overflow_msg.patch b/queue-4.19/nfs-remove-print_overflow_msg.patch
new file mode 100644 (file)
index 0000000..67212b3
--- /dev/null
@@ -0,0 +1,2608 @@
+From ab6c97c17638b1f02502162a7290a59730c6d32b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Feb 2019 11:24:21 -0500
+Subject: NFS: Remove print_overflow_msg()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit eb72f484a5eb94c53a241e6a7811270fb25200ad ]
+
+This issue is now captured by a trace point in the RPC client.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Stable-dep-of: 6dbf1f341b6b ("SUNRPC: Fix integer overflow in decode_rc_list()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/lockd/clnt4xdr.c    |  14 --
+ fs/lockd/clntxdr.c     |  14 --
+ fs/nfs/callback_xdr.c  |  59 +++---
+ fs/nfs/nfs2xdr.c       |  84 +++-----
+ fs/nfs/nfs3xdr.c       | 163 +++++----------
+ fs/nfs/nfs42xdr.c      |  21 +-
+ fs/nfs/nfs4xdr.c       | 451 +++++++++++------------------------------
+ fs/nfsd/nfs4callback.c |  13 --
+ 8 files changed, 219 insertions(+), 600 deletions(-)
+
+diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
+index 214a2fa1f1e39..7df6324ccb8ab 100644
+--- a/fs/lockd/clnt4xdr.c
++++ b/fs/lockd/clnt4xdr.c
+@@ -74,17 +74,6 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock,
+               *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
+ }
+-/*
+- * Handle decode buffer overflows out-of-line.
+- */
+-static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+-{
+-      dprintk("lockd: %s prematurely hit the end of our receive buffer. "
+-              "Remaining buffer length is %tu words.\n",
+-              func, xdr->end - xdr->p);
+-}
+-
+-
+ /*
+  * Encode/decode NLMv4 basic data types
+  *
+@@ -176,7 +165,6 @@ static int decode_cookie(struct xdr_stream *xdr,
+       dprintk("NFS: returned cookie was too long: %u\n", length);
+       return -EIO;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -236,7 +224,6 @@ static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
+                       __func__, be32_to_cpup(p));
+       return -EIO;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -309,7 +296,6 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
+ out:
+       return error;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
+index 747b9c8c940ac..4df62f6355295 100644
+--- a/fs/lockd/clntxdr.c
++++ b/fs/lockd/clntxdr.c
+@@ -70,17 +70,6 @@ static void nlm_compute_offsets(const struct nlm_lock *lock,
+               *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
+ }
+-/*
+- * Handle decode buffer overflows out-of-line.
+- */
+-static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+-{
+-      dprintk("lockd: %s prematurely hit the end of our receive buffer. "
+-              "Remaining buffer length is %tu words.\n",
+-              func, xdr->end - xdr->p);
+-}
+-
+-
+ /*
+  * Encode/decode NLMv3 basic data types
+  *
+@@ -173,7 +162,6 @@ static int decode_cookie(struct xdr_stream *xdr,
+       dprintk("NFS: returned cookie was too long: %u\n", length);
+       return -EIO;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -231,7 +219,6 @@ static int decode_nlm_stat(struct xdr_stream *xdr,
+               __func__, be32_to_cpup(p));
+       return -EIO;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -303,7 +290,6 @@ static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
+ out:
+       return error;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
+index 2f84c612838c4..38dc33c537ab6 100644
+--- a/fs/nfs/callback_xdr.c
++++ b/fs/nfs/callback_xdr.c
+@@ -72,16 +72,6 @@ static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p)
+       return xdr_ressize_check(rqstp, p);
+ }
+-static __be32 *read_buf(struct xdr_stream *xdr, size_t nbytes)
+-{
+-      __be32 *p;
+-
+-      p = xdr_inline_decode(xdr, nbytes);
+-      if (unlikely(p == NULL))
+-              printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n");
+-      return p;
+-}
+-
+ static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len,
+               const char **str, size_t maxlen)
+ {
+@@ -98,13 +88,13 @@ static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
+ {
+       __be32 *p;
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       fh->size = ntohl(*p);
+       if (fh->size > NFS4_FHSIZE)
+               return htonl(NFS4ERR_BADHANDLE);
+-      p = read_buf(xdr, fh->size);
++      p = xdr_inline_decode(xdr, fh->size);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       memcpy(&fh->data[0], p, fh->size);
+@@ -117,11 +107,11 @@ static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
+       __be32 *p;
+       unsigned int attrlen;
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       attrlen = ntohl(*p);
+-      p = read_buf(xdr, attrlen << 2);
++      p = xdr_inline_decode(xdr, attrlen << 2);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       if (likely(attrlen > 0))
+@@ -135,7 +125,7 @@ static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+ {
+       __be32 *p;
+-      p = read_buf(xdr, NFS4_STATEID_SIZE);
++      p = xdr_inline_decode(xdr, NFS4_STATEID_SIZE);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       memcpy(stateid->data, p, NFS4_STATEID_SIZE);
+@@ -156,7 +146,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
+       status = decode_string(xdr, &hdr->taglen, &hdr->tag, CB_OP_TAGLEN_MAXSZ);
+       if (unlikely(status != 0))
+               return status;
+-      p = read_buf(xdr, 12);
++      p = xdr_inline_decode(xdr, 12);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       hdr->minorversion = ntohl(*p++);
+@@ -176,7 +166,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
+ static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
+ {
+       __be32 *p;
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE_HDR);
+       *op = ntohl(*p);
+@@ -205,7 +195,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp,
+       status = decode_delegation_stateid(xdr, &args->stateid);
+       if (unlikely(status != 0))
+               return status;
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+       args->truncate = ntohl(*p);
+@@ -227,7 +217,7 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
+       __be32 status = 0;
+       uint32_t iomode;
+-      p = read_buf(xdr, 4 * sizeof(uint32_t));
++      p = xdr_inline_decode(xdr, 4 * sizeof(uint32_t));
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+@@ -245,14 +235,14 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
+               if (unlikely(status != 0))
+                       return status;
+-              p = read_buf(xdr, 2 * sizeof(uint64_t));
++              p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t));
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_BADXDR);
+               p = xdr_decode_hyper(p, &args->cbl_range.offset);
+               p = xdr_decode_hyper(p, &args->cbl_range.length);
+               return decode_layout_stateid(xdr, &args->cbl_stateid);
+       } else if (args->cbl_recall_type == RETURN_FSID) {
+-              p = read_buf(xdr, 2 * sizeof(uint64_t));
++              p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t));
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_BADXDR);
+               p = xdr_decode_hyper(p, &args->cbl_fsid.major);
+@@ -273,7 +263,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
+       __be32 status = 0;
+       /* Num of device notifications */
+-      p = read_buf(xdr, sizeof(uint32_t));
++      p = xdr_inline_decode(xdr, sizeof(uint32_t));
+       if (unlikely(p == NULL)) {
+               status = htonl(NFS4ERR_BADXDR);
+               goto out;
+@@ -292,7 +282,8 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
+       for (i = 0; i < n; i++) {
+               struct cb_devicenotifyitem *dev = &args->devs[i];
+-              p = read_buf(xdr, (4 * sizeof(uint32_t)) + NFS4_DEVICEID4_SIZE);
++              p = xdr_inline_decode(xdr, (4 * sizeof(uint32_t)) +
++                                    NFS4_DEVICEID4_SIZE);
+               if (unlikely(p == NULL)) {
+                       status = htonl(NFS4ERR_BADXDR);
+                       goto err;
+@@ -323,7 +314,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
+               p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
+               if (dev->cbd_layout_type == NOTIFY_DEVICEID4_CHANGE) {
+-                      p = read_buf(xdr, sizeof(uint32_t));
++                      p = xdr_inline_decode(xdr, sizeof(uint32_t));
+                       if (unlikely(p == NULL)) {
+                               status = htonl(NFS4ERR_BADXDR);
+                               goto err;
+@@ -355,7 +346,7 @@ static __be32 decode_sessionid(struct xdr_stream *xdr,
+ {
+       __be32 *p;
+-      p = read_buf(xdr, NFS4_MAX_SESSIONID_LEN);
++      p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+@@ -375,13 +366,13 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
+               goto out;
+       status = htonl(NFS4ERR_RESOURCE);
+-      p = read_buf(xdr, sizeof(uint32_t));
++      p = xdr_inline_decode(xdr, sizeof(uint32_t));
+       if (unlikely(p == NULL))
+               goto out;
+       rc_list->rcl_nrefcalls = ntohl(*p++);
+       if (rc_list->rcl_nrefcalls) {
+-              p = read_buf(xdr,
++              p = xdr_inline_decode(xdr,
+                            rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
+               if (unlikely(p == NULL))
+                       goto out;
+@@ -414,7 +405,7 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
+       if (status)
+               return status;
+-      p = read_buf(xdr, 5 * sizeof(uint32_t));
++      p = xdr_inline_decode(xdr, 5 * sizeof(uint32_t));
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
+@@ -457,7 +448,7 @@ static __be32 decode_recallany_args(struct svc_rqst *rqstp,
+       uint32_t bitmap[2];
+       __be32 *p, status;
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+       args->craa_objs_to_keep = ntohl(*p++);
+@@ -476,7 +467,7 @@ static __be32 decode_recallslot_args(struct svc_rqst *rqstp,
+       struct cb_recallslotargs *args = argp;
+       __be32 *p;
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+       args->crsa_target_highest_slotid = ntohl(*p++);
+@@ -488,14 +479,14 @@ static __be32 decode_lockowner(struct xdr_stream *xdr, struct cb_notify_lock_arg
+       __be32          *p;
+       unsigned int    len;
+-      p = read_buf(xdr, 12);
++      p = xdr_inline_decode(xdr, 12);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+       p = xdr_decode_hyper(p, &args->cbnl_owner.clientid);
+       len = be32_to_cpu(*p);
+-      p = read_buf(xdr, len);
++      p = xdr_inline_decode(xdr, len);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+@@ -533,7 +524,7 @@ static __be32 decode_write_response(struct xdr_stream *xdr,
+       __be32 *p;
+       /* skip the always zero field */
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out;
+       p++;
+@@ -573,7 +564,7 @@ static __be32 decode_offload_args(struct svc_rqst *rqstp,
+               return status;
+       /* decode status */
+-      p = read_buf(xdr, 4);
++      p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out;
+       args->error = ntohl(*p++);
+diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
+index 040a05f0e61ef..6968d6ffe84fa 100644
+--- a/fs/nfs/nfs2xdr.c
++++ b/fs/nfs/nfs2xdr.c
+@@ -79,17 +79,6 @@ static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
+       xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
+ }
+-/*
+- * Handle decode buffer overflows out-of-line.
+- */
+-static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+-{
+-      dprintk("NFS: %s prematurely hit the end of our receive buffer. "
+-              "Remaining buffer length is %tu words.\n",
+-              func, xdr->end - xdr->p);
+-}
+-
+-
+ /*
+  * Encode/decode NFSv2 basic data types
+  *
+@@ -110,8 +99,8 @@ static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       count = be32_to_cpup(p);
+       recvd = xdr_read_pages(xdr, count);
+       if (unlikely(count > recvd))
+@@ -125,9 +114,6 @@ static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
+               "count %u > recvd %u\n", count, recvd);
+       count = recvd;
+       goto out;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -157,13 +143,10 @@ static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       *status = be32_to_cpup(p);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -205,14 +188,11 @@ static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS2_FHSIZE);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       fh->size = NFS2_FHSIZE;
+       memcpy(fh->data, p, NFS2_FHSIZE);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -282,8 +262,8 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       fattr->valid |= NFS_ATTR_FATTR_V2;
+@@ -325,9 +305,6 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+ out_gid:
+       dprintk("NFS: returned invalid gid\n");
+       return -EINVAL;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -416,23 +393,20 @@ static int decode_filename_inline(struct xdr_stream *xdr,
+       u32 count;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       count = be32_to_cpup(p);
+       if (count > NFS3_MAXNAMLEN)
+               goto out_nametoolong;
+       p = xdr_inline_decode(xdr, count);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       *name = (const char *)p;
+       *length = count;
+       return 0;
+ out_nametoolong:
+       dprintk("NFS: returned filename too long: %u\n", count);
+       return -ENAMETOOLONG;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -455,8 +429,8 @@ static int decode_path(struct xdr_stream *xdr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       length = be32_to_cpup(p);
+       if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
+               goto out_size;
+@@ -472,9 +446,6 @@ static int decode_path(struct xdr_stream *xdr)
+       dprintk("NFS: server cheating in pathname result: "
+               "length %u > received %u\n", length, recvd);
+       return -EIO;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -951,12 +922,12 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       int error;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EAGAIN;
+       if (*p++ == xdr_zero) {
+               p = xdr_inline_decode(xdr, 4);
+-              if (unlikely(p == NULL))
+-                      goto out_overflow;
++              if (unlikely(!p))
++                      return -EAGAIN;
+               if (*p++ == xdr_zero)
+                       return -EAGAIN;
+               entry->eof = 1;
+@@ -964,8 +935,8 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       }
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EAGAIN;
+       entry->ino = be32_to_cpup(p);
+       error = decode_filename_inline(xdr, &entry->name, &entry->len);
+@@ -978,17 +949,13 @@ int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+        */
+       entry->prev_cookie = entry->cookie;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EAGAIN;
+       entry->cookie = be32_to_cpup(p);
+       entry->d_type = DT_UNKNOWN;
+       return 0;
+-
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EAGAIN;
+ }
+ /*
+@@ -1052,17 +1019,14 @@ static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS_info_sz << 2);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       result->tsize  = be32_to_cpup(p++);
+       result->bsize  = be32_to_cpup(p++);
+       result->blocks = be32_to_cpup(p++);
+       result->bfree  = be32_to_cpup(p++);
+       result->bavail = be32_to_cpup(p);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
+diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
+index 0ed419bb02b0f..ebe7d1ce00e39 100644
+--- a/fs/nfs/nfs3xdr.c
++++ b/fs/nfs/nfs3xdr.c
+@@ -119,17 +119,6 @@ static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
+       xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
+ }
+-/*
+- * Handle decode buffer overflows out-of-line.
+- */
+-static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+-{
+-      dprintk("NFS: %s prematurely hit the end of our receive buffer. "
+-              "Remaining buffer length is %tu words.\n",
+-              func, xdr->end - xdr->p);
+-}
+-
+-
+ /*
+  * Encode/decode NFSv3 basic data types
+  *
+@@ -152,13 +141,10 @@ static int decode_uint32(struct xdr_stream *xdr, u32 *value)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       *value = be32_to_cpup(p);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_uint64(struct xdr_stream *xdr, u64 *value)
+@@ -166,13 +152,10 @@ static int decode_uint64(struct xdr_stream *xdr, u64 *value)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 8);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       xdr_decode_hyper(p, value);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -212,14 +195,14 @@ static int decode_inline_filename3(struct xdr_stream *xdr,
+       u32 count;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       count = be32_to_cpup(p);
+       if (count > NFS3_MAXNAMLEN)
+               goto out_nametoolong;
+       p = xdr_inline_decode(xdr, count);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       *name = (const char *)p;
+       *length = count;
+       return 0;
+@@ -227,9 +210,6 @@ static int decode_inline_filename3(struct xdr_stream *xdr,
+ out_nametoolong:
+       dprintk("NFS: returned filename too long: %u\n", count);
+       return -ENAMETOOLONG;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -250,8 +230,8 @@ static int decode_nfspath3(struct xdr_stream *xdr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       count = be32_to_cpup(p);
+       if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
+               goto out_nametoolong;
+@@ -268,9 +248,6 @@ static int decode_nfspath3(struct xdr_stream *xdr)
+       dprintk("NFS: server cheating in pathname result: "
+               "count %u > recvd %u\n", count, recvd);
+       return -EIO;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -304,13 +281,10 @@ static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -331,13 +305,10 @@ static int decode_writeverf3(struct xdr_stream *xdr, struct nfs_write_verifier *
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       memcpy(verifier->data, p, NFS3_WRITEVERFSIZE);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -365,13 +336,10 @@ static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       *status = be32_to_cpup(p);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -454,23 +422,20 @@ static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       length = be32_to_cpup(p++);
+       if (unlikely(length > NFS3_FHSIZE))
+               goto out_toobig;
+       p = xdr_inline_decode(xdr, length);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       fh->size = length;
+       memcpy(fh->data, p, length);
+       return 0;
+ out_toobig:
+       dprintk("NFS: file handle size (%u) too big\n", length);
+       return -E2BIG;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static void zero_nfs_fh3(struct nfs_fh *fh)
+@@ -656,8 +621,8 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       p = xdr_decode_ftype3(p, &fmode);
+@@ -691,9 +656,6 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+ out_gid:
+       dprintk("NFS: returned invalid gid\n");
+       return -EINVAL;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -711,14 +673,11 @@ static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       if (*p != xdr_zero)
+               return decode_fattr3(xdr, fattr);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -734,8 +693,8 @@ static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       fattr->valid |= NFS_ATTR_FATTR_PRESIZE
+               | NFS_ATTR_FATTR_PRECHANGE
+@@ -748,9 +707,6 @@ static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+       fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -774,14 +730,11 @@ static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       if (*p != xdr_zero)
+               return decode_wcc_attr(xdr, fattr);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+@@ -809,15 +762,12 @@ static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+ static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
+ {
+       __be32 *p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       if (*p != xdr_zero)
+               return decode_nfs_fh3(xdr, fh);
+       zero_nfs_fh3(fh);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -1641,8 +1591,8 @@ static int decode_read3resok(struct xdr_stream *xdr,
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4 + 4 + 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       count = be32_to_cpup(p++);
+       eof = be32_to_cpup(p++);
+       ocount = be32_to_cpup(p++);
+@@ -1665,9 +1615,6 @@ static int decode_read3resok(struct xdr_stream *xdr,
+       count = recvd;
+       eof = 0;
+       goto out;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
+@@ -1726,22 +1673,18 @@ static int decode_write3resok(struct xdr_stream *xdr,
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4 + 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       result->count = be32_to_cpup(p++);
+       result->verf->committed = be32_to_cpup(p++);
+       if (unlikely(result->verf->committed > NFS_FILE_SYNC))
+               goto out_badvalue;
+       if (decode_writeverf3(xdr, &result->verf->verifier))
+-              goto out_eio;
++              return -EIO;
+       return result->count;
+ out_badvalue:
+       dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
+       return -EIO;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-out_eio:
+-      return -EIO;
+ }
+ static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
+@@ -2005,12 +1948,12 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       u64 new_cookie;
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EAGAIN;
+       if (*p == xdr_zero) {
+               p = xdr_inline_decode(xdr, 4);
+-              if (unlikely(p == NULL))
+-                      goto out_overflow;
++              if (unlikely(!p))
++                      return -EAGAIN;
+               if (*p == xdr_zero)
+                       return -EAGAIN;
+               entry->eof = 1;
+@@ -2046,8 +1989,8 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+               /* In fact, a post_op_fh3: */
+               p = xdr_inline_decode(xdr, 4);
+-              if (unlikely(p == NULL))
+-                      goto out_overflow;
++              if (unlikely(!p))
++                      return -EAGAIN;
+               if (*p != xdr_zero) {
+                       error = decode_nfs_fh3(xdr, entry->fh);
+                       if (unlikely(error)) {
+@@ -2064,9 +2007,6 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EAGAIN;
+ out_truncated:
+       dprintk("NFS: directory entry contains invalid file handle\n");
+       *entry = old;
+@@ -2178,8 +2118,8 @@ static int decode_fsstat3resok(struct xdr_stream *xdr,
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 8 * 6 + 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       p = xdr_decode_size3(p, &result->tbytes);
+       p = xdr_decode_size3(p, &result->fbytes);
+       p = xdr_decode_size3(p, &result->abytes);
+@@ -2188,9 +2128,6 @@ static int decode_fsstat3resok(struct xdr_stream *xdr,
+       xdr_decode_size3(p, &result->afiles);
+       /* ignore invarsec */
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
+@@ -2250,8 +2187,8 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr,
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       result->rtmax  = be32_to_cpup(p++);
+       result->rtpref = be32_to_cpup(p++);
+       result->rtmult = be32_to_cpup(p++);
+@@ -2265,9 +2202,6 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr,
+       /* ignore properties */
+       result->lease_time = 0;
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
+@@ -2323,15 +2257,12 @@ static int decode_pathconf3resok(struct xdr_stream *xdr,
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4 * 6);
+-      if (unlikely(p == NULL))
+-              goto out_overflow;
++      if (unlikely(!p))
++              return -EIO;
+       result->max_link = be32_to_cpup(p++);
+       result->max_namelen = be32_to_cpup(p);
+       /* ignore remaining fields */
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
+diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c
+index eee011de3f58b..d66e1025b4a4c 100644
+--- a/fs/nfs/nfs42xdr.c
++++ b/fs/nfs/nfs42xdr.c
+@@ -404,7 +404,7 @@ static int decode_write_response(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       count = be32_to_cpup(p);
+       if (count > 1)
+               return -EREMOTEIO;
+@@ -412,18 +412,14 @@ static int decode_write_response(struct xdr_stream *xdr,
+               status = decode_opaque_fixed(xdr, &res->stateid,
+                               NFS4_STATEID_SIZE);
+               if (unlikely(status))
+-                      goto out_overflow;
++                      return -EIO;
+       }
+       p = xdr_inline_decode(xdr, 8 + 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       p = xdr_decode_hyper(p, &res->count);
+       res->verifier.committed = be32_to_cpup(p);
+       return decode_verifier(xdr, &res->verifier.verifier);
+-
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_copy_requirements(struct xdr_stream *xdr,
+@@ -432,14 +428,11 @@ static int decode_copy_requirements(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 4 + 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->consecutive = be32_to_cpup(p++);
+       res->synchronous = be32_to_cpup(p++);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
+@@ -484,15 +477,11 @@ static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
+       p = xdr_inline_decode(xdr, 4 + 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->sr_eof = be32_to_cpup(p++);
+       p = xdr_decode_hyper(p, &res->sr_offset);
+       return 0;
+-
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_layoutstats(struct xdr_stream *xdr)
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index f0021e3b8efdd..767448b015cff 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -3144,22 +3144,12 @@ static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req,
+ }
+ #endif /* CONFIG_NFS_V4_1 */
+-static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+-{
+-      dprintk("nfs: %s: prematurely hit end of receive buffer. "
+-              "Remaining buffer length is %tu words.\n",
+-              func, xdr->end - xdr->p);
+-}
+-
+ static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
+ {
+       ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string,
+                       NFS4_OPAQUE_LIMIT);
+-      if (unlikely(ret < 0)) {
+-              if (ret == -EBADMSG)
+-                      print_overflow_msg(__func__, xdr);
++      if (unlikely(ret < 0))
+               return -EIO;
+-      }
+       *len = ret;
+       return 0;
+ }
+@@ -3170,22 +3160,19 @@ static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       hdr->status = be32_to_cpup(p++);
+       hdr->taglen = be32_to_cpup(p);
+       p = xdr_inline_decode(xdr, hdr->taglen + 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       hdr->tag = (char *)p;
+       p += XDR_QUADLEN(hdr->taglen);
+       hdr->nops = be32_to_cpup(p);
+       if (unlikely(hdr->nops < 1))
+               return nfs4_stat_to_errno(hdr->status);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
+@@ -3214,7 +3201,6 @@ static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
+       *nfs_retval = -EREMOTEIO;
+       return false;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       *nfs_retval = -EIO;
+       return false;
+ }
+@@ -3235,10 +3221,9 @@ static int decode_ace(struct xdr_stream *xdr, void *ace)
+       char *str;
+       p = xdr_inline_decode(xdr, 12);
+-      if (likely(p))
+-              return decode_opaque_inline(xdr, &strlen, &str);
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
++      if (unlikely(!p))
++              return -EIO;
++      return decode_opaque_inline(xdr, &strlen, &str);
+ }
+ static ssize_t
+@@ -3249,10 +3234,9 @@ decode_bitmap4(struct xdr_stream *xdr, uint32_t *bitmap, size_t sz)
+       ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz);
+       if (likely(ret >= 0))
+               return ret;
+-      if (ret == -EMSGSIZE)
+-              return sz;
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
++      if (ret != -EMSGSIZE)
++              return -EIO;
++      return sz;
+ }
+ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
+@@ -3268,13 +3252,10 @@ static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigne
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       *attrlen = be32_to_cpup(p);
+       *savep = xdr_stream_pos(xdr);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
+@@ -3303,7 +3284,7 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *
+       if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *type = be32_to_cpup(p);
+               if (*type < NF4REG || *type > NF4NAMEDATTR) {
+                       dprintk("%s: bad type %d\n", __func__, *type);
+@@ -3314,9 +3295,6 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *
+       }
+       dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_fh_expire_type(struct xdr_stream *xdr,
+@@ -3330,15 +3308,12 @@ static int decode_attr_fh_expire_type(struct xdr_stream *xdr,
+       if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *type = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE;
+       }
+       dprintk("%s: expire type=0x%x\n", __func__, *type);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
+@@ -3352,7 +3327,7 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t
+       if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, change);
+               bitmap[0] &= ~FATTR4_WORD0_CHANGE;
+               ret = NFS_ATTR_FATTR_CHANGE;
+@@ -3360,9 +3335,6 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t
+       dprintk("%s: change attribute=%Lu\n", __func__,
+                       (unsigned long long)*change);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
+@@ -3376,16 +3348,13 @@ static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *
+       if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, size);
+               bitmap[0] &= ~FATTR4_WORD0_SIZE;
+               ret = NFS_ATTR_FATTR_SIZE;
+       }
+       dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
+@@ -3398,15 +3367,12 @@ static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, ui
+       if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *res = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
+       }
+       dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
+@@ -3419,15 +3385,12 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap,
+       if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *res = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
+       }
+       dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
+@@ -3442,7 +3405,7 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs
+       if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
+               p = xdr_inline_decode(xdr, 16);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               p = xdr_decode_hyper(p, &fsid->major);
+               xdr_decode_hyper(p, &fsid->minor);
+               bitmap[0] &= ~FATTR4_WORD0_FSID;
+@@ -3452,9 +3415,6 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs
+                       (unsigned long long)fsid->major,
+                       (unsigned long long)fsid->minor);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
+@@ -3467,15 +3427,12 @@ static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint
+       if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *res = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
+       }
+       dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
+@@ -3487,14 +3444,11 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *
+       if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+               *res = -be32_to_cpup(p);
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_exclcreat_supported(struct xdr_stream *xdr,
+@@ -3526,13 +3480,13 @@ static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, stru
+       if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               len = be32_to_cpup(p);
+               if (len > NFS4_FHSIZE)
+                       return -EIO;
+               p = xdr_inline_decode(xdr, len);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               if (fh != NULL) {
+                       memcpy(fh->data, p, len);
+                       fh->size = len;
+@@ -3540,9 +3494,6 @@ static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, stru
+               bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
+@@ -3555,15 +3506,12 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint
+       if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *res = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
+       }
+       dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
+@@ -3577,16 +3525,13 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t
+       if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, fileid);
+               bitmap[0] &= ~FATTR4_WORD0_FILEID;
+               ret = NFS_ATTR_FATTR_FILEID;
+       }
+       dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
+@@ -3600,16 +3545,13 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma
+       if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, fileid);
+               bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+               ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
+       }
+       dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
+@@ -3623,15 +3565,12 @@ static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin
+       if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
+       }
+       dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
+@@ -3645,15 +3584,12 @@ static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint
+       if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
+       }
+       dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
+@@ -3667,15 +3603,12 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
+       if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
+       }
+       dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+@@ -3686,7 +3619,7 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       n = be32_to_cpup(p);
+       if (n == 0)
+               goto root_path;
+@@ -3718,9 +3651,6 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+       dprintk(" status %d", status);
+       status = -EIO;
+       goto out;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
+@@ -3745,7 +3675,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
+               goto out;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              goto out_eio;
+       n = be32_to_cpup(p);
+       for (res->nlocations = 0; res->nlocations < n; res->nlocations++) {
+               u32 m;
+@@ -3756,7 +3686,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
+               loc = &res->locations[res->nlocations];
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      goto out_eio;
+               m = be32_to_cpup(p);
+               dprintk("%s: servers:\n", __func__);
+@@ -3794,8 +3724,6 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
+ out:
+       dprintk("%s: fs_locations done, error = %d\n", __func__, status);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+ out_eio:
+       status = -EIO;
+       goto out;
+@@ -3812,15 +3740,12 @@ static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uin
+       if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
+       }
+       dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
+@@ -3834,15 +3759,12 @@ static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
+       if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *maxlink = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
+       }
+       dprintk("%s: maxlink=%u\n", __func__, *maxlink);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
+@@ -3856,15 +3778,12 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
+       if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *maxname = be32_to_cpup(p);
+               bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
+       }
+       dprintk("%s: maxname=%u\n", __func__, *maxname);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
+@@ -3879,7 +3798,7 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
+               uint64_t maxread;
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, &maxread);
+               if (maxread > 0x7FFFFFFF)
+                       maxread = 0x7FFFFFFF;
+@@ -3888,9 +3807,6 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
+       }
+       dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
+@@ -3905,7 +3821,7 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32
+               uint64_t maxwrite;
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, &maxwrite);
+               if (maxwrite > 0x7FFFFFFF)
+                       maxwrite = 0x7FFFFFFF;
+@@ -3914,9 +3830,6 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32
+       }
+       dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
+@@ -3931,7 +3844,7 @@ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *m
+       if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               tmp = be32_to_cpup(p);
+               *mode = tmp & ~S_IFMT;
+               bitmap[1] &= ~FATTR4_WORD1_MODE;
+@@ -3939,9 +3852,6 @@ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *m
+       }
+       dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
+@@ -3955,16 +3865,13 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t
+       if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               *nlink = be32_to_cpup(p);
+               bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
+               ret = NFS_ATTR_FATTR_NLINK;
+       }
+       dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static ssize_t decode_nfs4_string(struct xdr_stream *xdr,
+@@ -4009,10 +3916,9 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
+               return NFS_ATTR_FATTR_OWNER;
+       }
+ out:
+-      if (len != -EBADMSG)
+-              return 0;
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
++      if (len == -EBADMSG)
++              return -EIO;
++      return 0;
+ }
+ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
+@@ -4044,10 +3950,9 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
+               return NFS_ATTR_FATTR_GROUP;
+       }
+ out:
+-      if (len != -EBADMSG)
+-              return 0;
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
++      if (len == -EBADMSG)
++              return -EIO;
++      return 0;
+ }
+ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
+@@ -4064,7 +3969,7 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               major = be32_to_cpup(p++);
+               minor = be32_to_cpup(p);
+               tmp = MKDEV(major, minor);
+@@ -4075,9 +3980,6 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde
+       }
+       dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
+@@ -4091,15 +3993,12 @@ static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin
+       if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
+       }
+       dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
+@@ -4113,15 +4012,12 @@ static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint
+       if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
+       }
+       dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
+@@ -4135,15 +4031,12 @@ static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
+       if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+               bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
+       }
+       dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
+@@ -4157,7 +4050,7 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint
+       if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, used);
+               bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
+               ret = NFS_ATTR_FATTR_SPACE_USED;
+@@ -4165,9 +4058,6 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint
+       dprintk("%s: space used=%Lu\n", __func__,
+                       (unsigned long long)*used);
+       return ret;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static __be32 *
+@@ -4187,12 +4077,9 @@ static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
+       p = xdr_inline_decode(xdr, nfstime4_maxsz << 2);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       xdr_decode_nfstime4(p, time);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
+@@ -4263,19 +4150,19 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
+       if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               lfs = be32_to_cpup(p++);
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               pi = be32_to_cpup(p++);
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               len = be32_to_cpup(p++);
+               p = xdr_inline_decode(xdr, len);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               if (len < NFS4_MAXLABELLEN) {
+                       if (label && label->len) {
+                               if (label->len < len)
+@@ -4296,10 +4183,6 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
+                               label->len, label->pi, label->lfs);
+       }
+       return status;
+-
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
+@@ -4343,14 +4226,11 @@ static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *c
+       p = xdr_inline_decode(xdr, 20);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       cinfo->atomic = be32_to_cpup(p++);
+       p = xdr_decode_hyper(p, &cinfo->before);
+       xdr_decode_hyper(p, &cinfo->after);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
+@@ -4364,24 +4244,19 @@ static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
+               return status;
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       supp = be32_to_cpup(p++);
+       acc = be32_to_cpup(p);
+       *supported = supp;
+       *access = acc;
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
+ {
+       ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len);
+-      if (unlikely(ret < 0)) {
+-              print_overflow_msg(__func__, xdr);
++      if (unlikely(ret < 0))
+               return -EIO;
+-      }
+       return 0;
+ }
+@@ -4464,13 +4339,11 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
+               return status;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       bmlen = be32_to_cpup(p);
+       p = xdr_inline_decode(xdr, bmlen << 2);
+       if (likely(p))
+               return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -4578,13 +4451,10 @@ static int decode_threshold_hint(struct xdr_stream *xdr,
+       if (likely(bitmap[0] & hint_bit)) {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               xdr_decode_hyper(p, res);
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_first_threshold_item4(struct xdr_stream *xdr,
+@@ -4597,10 +4467,8 @@ static int decode_first_threshold_item4(struct xdr_stream *xdr,
+       /* layout type */
+       p = xdr_inline_decode(xdr, 4);
+-      if (unlikely(!p)) {
+-              print_overflow_msg(__func__, xdr);
++      if (unlikely(!p))
+               return -EIO;
+-      }
+       res->l_type = be32_to_cpup(p);
+       /* thi_hintset bitmap */
+@@ -4658,7 +4526,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
+                       return -EREMOTEIO;
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               num = be32_to_cpup(p);
+               if (num == 0)
+                       return 0;
+@@ -4671,9 +4539,6 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
+               bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD;
+       }
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+@@ -4861,7 +4726,7 @@ static int decode_pnfs_layout_types(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       fsinfo->nlayouttypes = be32_to_cpup(p);
+       /* pNFS is not supported by the underlying file system */
+@@ -4871,7 +4736,7 @@ static int decode_pnfs_layout_types(struct xdr_stream *xdr,
+       /* Decode and set first layout type, move xdr->p past unused types */
+       p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       /* If we get too many, then just cap it at the max */
+       if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) {
+@@ -4883,9 +4748,6 @@ static int decode_pnfs_layout_types(struct xdr_stream *xdr,
+       for(i = 0; i < fsinfo->nlayouttypes; ++i)
+               fsinfo->layouttype[i] = be32_to_cpup(p++);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ /*
+@@ -4919,10 +4781,8 @@ static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
+       *res = 0;
+       if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) {
+               p = xdr_inline_decode(xdr, 4);
+-              if (unlikely(!p)) {
+-                      print_overflow_msg(__func__, xdr);
++              if (unlikely(!p))
+                       return -EIO;
+-              }
+               *res = be32_to_cpup(p);
+               bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE;
+       }
+@@ -4941,10 +4801,8 @@ static int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
+       *res = 0;
+       if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) {
+               p = xdr_inline_decode(xdr, 4);
+-              if (unlikely(!p)) {
+-                      print_overflow_msg(__func__, xdr);
++              if (unlikely(!p))
+                       return -EIO;
+-              }
+               *res = be32_to_cpup(p);
+               bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE;
+       }
+@@ -5020,19 +4878,16 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       len = be32_to_cpup(p);
+       if (len > NFS4_FHSIZE)
+               return -EIO;
+       fh->size = len;
+       p = xdr_inline_decode(xdr, len);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       memcpy(fh->data, p, len);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
+@@ -5056,7 +4911,7 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
+       p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
+       p = xdr_decode_hyper(p, &length);
+       type = be32_to_cpup(p++); /* 4 byte read */
+@@ -5073,11 +4928,9 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
+       p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
+       namelen = be32_to_cpup(p); /* read 4 bytes */  /* have read all 32 bytes now */
+       p = xdr_inline_decode(xdr, namelen); /* variable size field */
+-      if (likely(p))
+-              return -NFS4ERR_DENIED;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
++      if (likely(!p))
++              return -EIO;
++      return -NFS4ERR_DENIED;
+ }
+ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
+@@ -5146,7 +4999,7 @@ static int decode_space_limit(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       limit_type = be32_to_cpup(p++);
+       switch (limit_type) {
+       case NFS4_LIMIT_SIZE:
+@@ -5160,9 +5013,6 @@ static int decode_space_limit(struct xdr_stream *xdr,
+       maxsize >>= PAGE_SHIFT;
+       *pagemod_limit = min_t(u64, maxsize, ULONG_MAX);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_rw_delegation(struct xdr_stream *xdr,
+@@ -5177,7 +5027,7 @@ static int decode_rw_delegation(struct xdr_stream *xdr,
+               return status;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->do_recall = be32_to_cpup(p);
+       switch (delegation_type) {
+@@ -5190,9 +5040,6 @@ static int decode_rw_delegation(struct xdr_stream *xdr,
+                               return -EIO;
+       }
+       return decode_ace(xdr, NULL);
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+@@ -5202,7 +5049,7 @@ static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       why_no_delegation = be32_to_cpup(p);
+       switch (why_no_delegation) {
+               case WND4_CONTENTION:
+@@ -5211,9 +5058,6 @@ static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+                       /* Ignore for now */
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+@@ -5223,7 +5067,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       delegation_type = be32_to_cpup(p);
+       res->delegation_type = 0;
+       switch (delegation_type) {
+@@ -5236,9 +5080,6 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+               return decode_no_delegation(xdr, res);
+       }
+       return -EIO;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+@@ -5260,7 +5101,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->rflags = be32_to_cpup(p++);
+       bmlen = be32_to_cpup(p);
+       if (bmlen > 10)
+@@ -5268,7 +5109,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+       p = xdr_inline_decode(xdr, bmlen << 2);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
+       for (i = 0; i < savewords; ++i)
+               res->attrset[i] = be32_to_cpup(p++);
+@@ -5279,9 +5120,6 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+ xdr_error:
+       dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
+       return -EIO;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
+@@ -5330,7 +5168,7 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req,
+               return status;
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       eof = be32_to_cpup(p++);
+       count = be32_to_cpup(p);
+       recvd = xdr_read_pages(xdr, count);
+@@ -5343,9 +5181,6 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req,
+       res->eof = eof;
+       res->count = count;
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
+@@ -5378,7 +5213,7 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
+       /* Convert length of symlink */
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       len = be32_to_cpup(p);
+       if (len >= rcvbuf->page_len || len <= 0) {
+               dprintk("nfs: server returned giant symlink!\n");
+@@ -5399,9 +5234,6 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
+        */
+       xdr_terminate_string(rcvbuf, len);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
+@@ -5504,7 +5336,6 @@ static int decode_setattr(struct xdr_stream *xdr)
+               return status;
+       if (decode_bitmap4(xdr, NULL, 0) >= 0)
+               return 0;
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -5516,7 +5347,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_re
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       opnum = be32_to_cpup(p++);
+       if (opnum != OP_SETCLIENTID) {
+               dprintk("nfs: decode_setclientid: Server returned operation"
+@@ -5527,7 +5358,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_re
+       if (nfserr == NFS_OK) {
+               p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               p = xdr_decode_hyper(p, &res->clientid);
+               memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE);
+       } else if (nfserr == NFSERR_CLID_INUSE) {
+@@ -5536,28 +5367,25 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_re
+               /* skip netid string */
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               len = be32_to_cpup(p);
+               p = xdr_inline_decode(xdr, len);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               /* skip uaddr string */
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               len = be32_to_cpup(p);
+               p = xdr_inline_decode(xdr, len);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               return -NFSERR_CLID_INUSE;
+       } else
+               return nfs4_stat_to_errno(nfserr);
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_setclientid_confirm(struct xdr_stream *xdr)
+@@ -5576,13 +5404,10 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res)
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->count = be32_to_cpup(p++);
+       res->verf->committed = be32_to_cpup(p++);
+       return decode_write_verifier(xdr, &res->verf->verifier);
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_delegreturn(struct xdr_stream *xdr)
+@@ -5598,30 +5423,24 @@ static int decode_secinfo_gss(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       oid_len = be32_to_cpup(p);
+       if (oid_len > GSS_OID_MAX_LEN)
+-              goto out_err;
++              return -EINVAL;
+       p = xdr_inline_decode(xdr, oid_len);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       memcpy(flavor->flavor_info.oid.data, p, oid_len);
+       flavor->flavor_info.oid.len = oid_len;
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       flavor->flavor_info.qop = be32_to_cpup(p++);
+       flavor->flavor_info.service = be32_to_cpup(p);
+       return 0;
+-
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+-out_err:
+-      return -EINVAL;
+ }
+ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+@@ -5633,7 +5452,7 @@ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->flavors->num_flavors = 0;
+       num_flavors = be32_to_cpup(p);
+@@ -5645,7 +5464,7 @@ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               sec_flavor->flavor = be32_to_cpup(p);
+               if (sec_flavor->flavor == RPC_AUTH_GSS) {
+@@ -5659,9 +5478,6 @@ static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res
+       status = 0;
+ out:
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+@@ -5715,11 +5531,11 @@ static int decode_exchange_id(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       xdr_decode_hyper(p, &res->clientid);
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->seqid = be32_to_cpup(p++);
+       res->flags = be32_to_cpup(p++);
+@@ -5743,7 +5559,7 @@ static int decode_exchange_id(struct xdr_stream *xdr,
+       /* server_owner4.so_minor_id */
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       p = xdr_decode_hyper(p, &res->server_owner->minor_id);
+       /* server_owner4.so_major_id */
+@@ -5763,7 +5579,7 @@ static int decode_exchange_id(struct xdr_stream *xdr,
+       /* Implementation Id */
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       impl_id_count = be32_to_cpup(p++);
+       if (impl_id_count) {
+@@ -5782,16 +5598,13 @@ static int decode_exchange_id(struct xdr_stream *xdr,
+               /* nii_date */
+               p = xdr_inline_decode(xdr, 12);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               p = xdr_decode_hyper(p, &res->impl_id->date.seconds);
+               res->impl_id->date.nseconds = be32_to_cpup(p);
+               /* if there's more than one entry, ignore the rest */
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_chan_attrs(struct xdr_stream *xdr,
+@@ -5802,7 +5615,7 @@ static int decode_chan_attrs(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 28);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       val = be32_to_cpup(p++);        /* headerpadsz */
+       if (val)
+               return -EINVAL;         /* no support for header padding yet */
+@@ -5820,12 +5633,9 @@ static int decode_chan_attrs(struct xdr_stream *xdr,
+       if (nr_attrs == 1) {
+               p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
+@@ -5848,7 +5658,7 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr,
+       /* dir flags, rdma mode bool */
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->dir = be32_to_cpup(p++);
+       if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH)
+@@ -5859,9 +5669,6 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr,
+               res->use_conn_in_rdma_mode = true;
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_create_session(struct xdr_stream *xdr,
+@@ -5879,7 +5686,7 @@ static int decode_create_session(struct xdr_stream *xdr,
+       /* seqid, flags */
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->seqid = be32_to_cpup(p++);
+       res->flags = be32_to_cpup(p);
+@@ -5888,9 +5695,6 @@ static int decode_create_session(struct xdr_stream *xdr,
+       if (!status)
+               status = decode_chan_attrs(xdr, &res->bc_attrs);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
+@@ -5971,7 +5775,6 @@ static int decode_sequence(struct xdr_stream *xdr,
+       res->sr_status = status;
+       return status;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       status = -EIO;
+       goto out_err;
+ #else  /* CONFIG_NFS_V4_1 */
+@@ -5999,7 +5802,7 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr,
+               if (status == -ETOOSMALL) {
+                       p = xdr_inline_decode(xdr, 4);
+                       if (unlikely(!p))
+-                              goto out_overflow;
++                              return -EIO;
+                       pdev->mincount = be32_to_cpup(p);
+                       dprintk("%s: Min count too small. mincnt = %u\n",
+                               __func__, pdev->mincount);
+@@ -6009,7 +5812,7 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       type = be32_to_cpup(p++);
+       if (type != pdev->layout_type) {
+               dprintk("%s: layout mismatch req: %u pdev: %u\n",
+@@ -6023,19 +5826,19 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr,
+        */
+       pdev->mincount = be32_to_cpup(p);
+       if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount)
+-              goto out_overflow;
++              return -EIO;
+       /* Parse notification bitmap, verifying that it is zero. */
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       len = be32_to_cpup(p);
+       if (len) {
+               uint32_t i;
+               p = xdr_inline_decode(xdr, 4 * len);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+               res->notification = be32_to_cpup(p++);
+               for (i = 1; i < len; i++) {
+@@ -6047,9 +5850,6 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr,
+               }
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+@@ -6119,7 +5919,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+       res->status = status;
+       return status;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       status = -EIO;
+       goto out;
+ }
+@@ -6135,16 +5934,13 @@ static int decode_layoutreturn(struct xdr_stream *xdr,
+               return status;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->lrs_present = be32_to_cpup(p);
+       if (res->lrs_present)
+               status = decode_layout_stateid(xdr, &res->stateid);
+       else
+               nfs4_stateid_copy(&res->stateid, &invalid_stateid);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_layoutcommit(struct xdr_stream *xdr,
+@@ -6162,19 +5958,16 @@ static int decode_layoutcommit(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       sizechanged = be32_to_cpup(p);
+       if (sizechanged) {
+               /* throw away new size */
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EIO;
+       }
+       return 0;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EIO;
+ }
+ static int decode_test_stateid(struct xdr_stream *xdr,
+@@ -6190,21 +5983,17 @@ static int decode_test_stateid(struct xdr_stream *xdr,
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       num_res = be32_to_cpup(p++);
+       if (num_res != 1)
+-              goto out;
++              return -EIO;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EIO;
+       res->status = be32_to_cpup(p++);
+       return status;
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-out:
+-      return -EIO;
+ }
+ static int decode_free_stateid(struct xdr_stream *xdr,
+@@ -7574,11 +7363,11 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       uint64_t new_cookie;
+       __be32 *p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EAGAIN;
+       if (*p == xdr_zero) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+-                      goto out_overflow;
++                      return -EAGAIN;
+               if (*p == xdr_zero)
+                       return -EAGAIN;
+               entry->eof = 1;
+@@ -7587,13 +7376,13 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EAGAIN;
+       p = xdr_decode_hyper(p, &new_cookie);
+       entry->len = be32_to_cpup(p);
+       p = xdr_inline_decode(xdr, entry->len);
+       if (unlikely(!p))
+-              goto out_overflow;
++              return -EAGAIN;
+       entry->name = (const char *) p;
+       /*
+@@ -7605,14 +7394,14 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       entry->fattr->valid = 0;
+       if (decode_attr_bitmap(xdr, bitmap) < 0)
+-              goto out_overflow;
++              return -EAGAIN;
+       if (decode_attr_length(xdr, &len, &savep) < 0)
+-              goto out_overflow;
++              return -EAGAIN;
+       if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
+                       NULL, entry->label, entry->server) < 0)
+-              goto out_overflow;
++              return -EAGAIN;
+       if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+               entry->ino = entry->fattr->mounted_on_fileid;
+       else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
+@@ -7626,10 +7415,6 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+       entry->cookie = new_cookie;
+       return 0;
+-
+-out_overflow:
+-      print_overflow_msg(__func__, xdr);
+-      return -EAGAIN;
+ }
+ /*
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 519d994c0c4c0..e6c7448d3d89a 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -59,16 +59,6 @@ struct nfs4_cb_compound_hdr {
+       int             status;
+ };
+-/*
+- * Handle decode buffer overflows out-of-line.
+- */
+-static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+-{
+-      dprintk("NFS: %s prematurely hit the end of our receive buffer. "
+-              "Remaining buffer length is %tu words.\n",
+-              func, xdr->end - xdr->p);
+-}
+-
+ static __be32 *xdr_encode_empty_array(__be32 *p)
+ {
+       *p++ = xdr_zero;
+@@ -238,7 +228,6 @@ static int decode_cb_op_status(struct xdr_stream *xdr,
+       *status = nfs_cb_stat_to_errno(be32_to_cpup(p));
+       return 0;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ out_unexpected:
+       dprintk("NFSD: Callback server returned operation %d but "
+@@ -307,7 +296,6 @@ static int decode_cb_compound4res(struct xdr_stream *xdr,
+       hdr->nops = be32_to_cpup(p);
+       return 0;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       return -EIO;
+ }
+@@ -435,7 +423,6 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
+       cb->cb_seq_status = status;
+       return status;
+ out_overflow:
+-      print_overflow_msg(__func__, xdr);
+       status = -EIO;
+       goto out;
+ }
+-- 
+2.43.0
+
diff --git a/queue-4.19/ppp-fix-ppp_async_encode-illegal-access.patch b/queue-4.19/ppp-fix-ppp_async_encode-illegal-access.patch
new file mode 100644 (file)
index 0000000..25a1330
--- /dev/null
@@ -0,0 +1,91 @@
+From 2953597552a45540c1b8cf9f4e51b92b1abbb5b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Oct 2024 18:58:02 +0000
+Subject: ppp: fix ppp_async_encode() illegal access
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 40dddd4b8bd08a69471efd96107a4e1c73fabefc ]
+
+syzbot reported an issue in ppp_async_encode() [1]
+
+In this case, pppoe_sendmsg() is called with a zero size.
+Then ppp_async_encode() is called with an empty skb.
+
+BUG: KMSAN: uninit-value in ppp_async_encode drivers/net/ppp/ppp_async.c:545 [inline]
+ BUG: KMSAN: uninit-value in ppp_async_push+0xb4f/0x2660 drivers/net/ppp/ppp_async.c:675
+  ppp_async_encode drivers/net/ppp/ppp_async.c:545 [inline]
+  ppp_async_push+0xb4f/0x2660 drivers/net/ppp/ppp_async.c:675
+  ppp_async_send+0x130/0x1b0 drivers/net/ppp/ppp_async.c:634
+  ppp_channel_bridge_input drivers/net/ppp/ppp_generic.c:2280 [inline]
+  ppp_input+0x1f1/0xe60 drivers/net/ppp/ppp_generic.c:2304
+  pppoe_rcv_core+0x1d3/0x720 drivers/net/ppp/pppoe.c:379
+  sk_backlog_rcv+0x13b/0x420 include/net/sock.h:1113
+  __release_sock+0x1da/0x330 net/core/sock.c:3072
+  release_sock+0x6b/0x250 net/core/sock.c:3626
+  pppoe_sendmsg+0x2b8/0xb90 drivers/net/ppp/pppoe.c:903
+  sock_sendmsg_nosec net/socket.c:729 [inline]
+  __sock_sendmsg+0x30f/0x380 net/socket.c:744
+  ____sys_sendmsg+0x903/0xb60 net/socket.c:2602
+  ___sys_sendmsg+0x28d/0x3c0 net/socket.c:2656
+  __sys_sendmmsg+0x3c1/0x960 net/socket.c:2742
+  __do_sys_sendmmsg net/socket.c:2771 [inline]
+  __se_sys_sendmmsg net/socket.c:2768 [inline]
+  __x64_sys_sendmmsg+0xbc/0x120 net/socket.c:2768
+  x64_sys_call+0xb6e/0x3ba0 arch/x86/include/generated/asm/syscalls_64.h:308
+  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+  do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Uninit was created at:
+  slab_post_alloc_hook mm/slub.c:4092 [inline]
+  slab_alloc_node mm/slub.c:4135 [inline]
+  kmem_cache_alloc_node_noprof+0x6bf/0xb80 mm/slub.c:4187
+  kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:587
+  __alloc_skb+0x363/0x7b0 net/core/skbuff.c:678
+  alloc_skb include/linux/skbuff.h:1322 [inline]
+  sock_wmalloc+0xfe/0x1a0 net/core/sock.c:2732
+  pppoe_sendmsg+0x3a7/0xb90 drivers/net/ppp/pppoe.c:867
+  sock_sendmsg_nosec net/socket.c:729 [inline]
+  __sock_sendmsg+0x30f/0x380 net/socket.c:744
+  ____sys_sendmsg+0x903/0xb60 net/socket.c:2602
+  ___sys_sendmsg+0x28d/0x3c0 net/socket.c:2656
+  __sys_sendmmsg+0x3c1/0x960 net/socket.c:2742
+  __do_sys_sendmmsg net/socket.c:2771 [inline]
+  __se_sys_sendmmsg net/socket.c:2768 [inline]
+  __x64_sys_sendmmsg+0xbc/0x120 net/socket.c:2768
+  x64_sys_call+0xb6e/0x3ba0 arch/x86/include/generated/asm/syscalls_64.h:308
+  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+  do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+CPU: 1 UID: 0 PID: 5411 Comm: syz.1.14 Not tainted 6.12.0-rc1-syzkaller-00165-g360c1f1f24c6 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+1d121645899e7692f92a@syzkaller.appspotmail.com
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20241009185802.3763282-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ppp/ppp_async.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
+index fb1e28a298929..14e8ad3f93544 100644
+--- a/drivers/net/ppp/ppp_async.c
++++ b/drivers/net/ppp/ppp_async.c
+@@ -555,7 +555,7 @@ ppp_async_encode(struct asyncppp *ap)
+        * and 7 (code-reject) must be sent as though no options
+        * had been negotiated.
+        */
+-      islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
++      islcp = proto == PPP_LCP && count >= 3 && 1 <= data[2] && data[2] <= 7;
+       if (i == 0) {
+               if (islcp)
+-- 
+2.43.0
+
index c5b7b9a1f63d0d552a4abc4c47fc56aabad48d09..796c9761af727be8402e04fa064afdf0af9da91a 100644 (file)
@@ -246,3 +246,16 @@ usb-chipidea-udc-enable-suspend-interrupt-after-usb-.patch
 tools-iio-add-memory-allocation-failure-check-for-tr.patch
 driver-core-bus-return-eio-instead-of-0-when-show-st.patch
 fbdev-sisfb-fix-strbuf-array-overflow.patch
+nfs-remove-print_overflow_msg.patch
+sunrpc-fix-integer-overflow-in-decode_rc_list.patch
+tcp-fix-tcp_enter_recovery-to-zero-retrans_stamp-whe.patch
+netfilter-br_netfilter-fix-panic-with-metadata_dst-s.patch
+bluetooth-rfcomm-fix-possible-deadlock-in-rfcomm_sk_.patch
+gpio-aspeed-add-the-flush-write-to-ensure-the-write-.patch
+clk-add-devm_-clk_get_optional-functions.patch
+clk-generalize-devm_clk_get-a-bit.patch
+clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch
+gpio-aspeed-use-devm_clk-api-to-manage-clock-source.patch
+igb-do-not-bring-the-device-up-after-non-fatal-error.patch
+net-ibm-emac-mal-fix-wrong-goto.patch
+ppp-fix-ppp_async_encode-illegal-access.patch
diff --git a/queue-4.19/sunrpc-fix-integer-overflow-in-decode_rc_list.patch b/queue-4.19/sunrpc-fix-integer-overflow-in-decode_rc_list.patch
new file mode 100644 (file)
index 0000000..f2a4192
--- /dev/null
@@ -0,0 +1,37 @@
+From 614be209eb1bed41caf677ab110c8b6e0b231fb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Sep 2024 11:50:33 +0300
+Subject: SUNRPC: Fix integer overflow in decode_rc_list()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 6dbf1f341b6b35bcc20ff95b6b315e509f6c5369 ]
+
+The math in "rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)" could have an
+integer overflow.  Add bounds checking on rc_list->rcl_nrefcalls to fix
+that.
+
+Fixes: 4aece6a19cf7 ("nfs41: cb_sequence xdr implementation")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/callback_xdr.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
+index 38dc33c537ab6..8f8b3a7868e8d 100644
+--- a/fs/nfs/callback_xdr.c
++++ b/fs/nfs/callback_xdr.c
+@@ -372,6 +372,8 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
+       rc_list->rcl_nrefcalls = ntohl(*p++);
+       if (rc_list->rcl_nrefcalls) {
++              if (unlikely(rc_list->rcl_nrefcalls > xdr->buf->len))
++                      goto out;
+               p = xdr_inline_decode(xdr,
+                            rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
+               if (unlikely(p == NULL))
+-- 
+2.43.0
+
diff --git a/queue-4.19/tcp-fix-tcp_enter_recovery-to-zero-retrans_stamp-whe.patch b/queue-4.19/tcp-fix-tcp_enter_recovery-to-zero-retrans_stamp-whe.patch
new file mode 100644 (file)
index 0000000..d36b82c
--- /dev/null
@@ -0,0 +1,153 @@
+From 22ee31626d04e3865cdd532c2d7eb17318b19ab4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 20:05:16 +0000
+Subject: tcp: fix tcp_enter_recovery() to zero retrans_stamp when it's safe
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit b41b4cbd9655bcebcce941bef3601db8110335be ]
+
+Fix tcp_enter_recovery() so that if there are no retransmits out then
+we zero retrans_stamp when entering fast recovery. This is necessary
+to fix two buggy behaviors.
+
+Currently a non-zero retrans_stamp value can persist across multiple
+back-to-back loss recovery episodes. This is because we generally only
+clears retrans_stamp if we are completely done with loss recoveries,
+and get to tcp_try_to_open() and find !tcp_any_retrans_done(sk). This
+behavior causes two bugs:
+
+(1) When a loss recovery episode (CA_Loss or CA_Recovery) is followed
+immediately by a new CA_Recovery, the retrans_stamp value can persist
+and can be a time before this new CA_Recovery episode starts. That
+means that timestamp-based undo will be using the wrong retrans_stamp
+(a value that is too old) when comparing incoming TS ecr values to
+retrans_stamp to see if the current fast recovery episode can be
+undone.
+
+(2) If there is a roughly minutes-long sequence of back-to-back fast
+recovery episodes, one after another (e.g. in a shallow-buffered or
+policed bottleneck), where each fast recovery successfully makes
+forward progress and recovers one window of sequence space (but leaves
+at least one retransmit in flight at the end of the recovery),
+followed by several RTOs, then the ETIMEDOUT check may be using the
+wrong retrans_stamp (a value set at the start of the first fast
+recovery in the sequence). This can cause a very premature ETIMEDOUT,
+killing the connection prematurely.
+
+This commit changes the code to zero retrans_stamp when entering fast
+recovery, when this is known to be safe (no retransmits are out in the
+network). That ensures that when starting a fast recovery episode, and
+it is safe to do so, retrans_stamp is set when we send the fast
+retransmit packet. That addresses both bug (1) and bug (2) by ensuring
+that (if no retransmits are out when we start a fast recovery) we use
+the initial fast retransmit of this fast recovery as the time value
+for undo and ETIMEDOUT calculations.
+
+This makes intuitive sense, since the start of a new fast recovery
+episode (in a scenario where no lost packets are out in the network)
+means that the connection has made forward progress since the last RTO
+or fast recovery, and we should thus "restart the clock" used for both
+undo and ETIMEDOUT logic.
+
+Note that if when we start fast recovery there *are* retransmits out
+in the network, there can still be undesirable (1)/(2) issues. For
+example, after this patch we can still have the (1) and (2) problems
+in cases like this:
+
++ round 1: sender sends flight 1
+
++ round 2: sender receives SACKs and enters fast recovery 1,
+  retransmits some packets in flight 1 and then sends some new data as
+  flight 2
+
++ round 3: sender receives some SACKs for flight 2, notes losses, and
+  retransmits some packets to fill the holes in flight 2
+
++ fast recovery has some lost retransmits in flight 1 and continues
+  for one or more rounds sending retransmits for flight 1 and flight 2
+
++ fast recovery 1 completes when snd_una reaches high_seq at end of
+  flight 1
+
++ there are still holes in the SACK scoreboard in flight 2, so we
+  enter fast recovery 2, but some retransmits in the flight 2 sequence
+  range are still in flight (retrans_out > 0), so we can't execute the
+  new retrans_stamp=0 added here to clear retrans_stamp
+
+It's not yet clear how to fix these remaining (1)/(2) issues in an
+efficient way without breaking undo behavior, given that retrans_stamp
+is currently used for undo and ETIMEDOUT. Perhaps the optimal (but
+expensive) strategy would be to set retrans_stamp to the timestamp of
+the earliest outstanding retransmit when entering fast recovery. But
+at least this commit makes things better.
+
+Note that this does not change the semantics of retrans_stamp; it
+simply makes retrans_stamp accurate in some cases where it was not
+before:
+
+(1) Some loss recovery, followed by an immediate entry into a fast
+recovery, where there are no retransmits out when entering the fast
+recovery.
+
+(2) When a TFO server has a SYNACK retransmit that sets retrans_stamp,
+and then the ACK that completes the 3-way handshake has SACK blocks
+that trigger a fast recovery. In this case when entering fast recovery
+we want to zero out the retrans_stamp from the TFO SYNACK retransmit,
+and set the retrans_stamp based on the timestamp of the fast recovery.
+
+We introduce a tcp_retrans_stamp_cleanup() helper, because this
+two-line sequence already appears in 3 places and is about to appear
+in 2 more as a result of this bug fix patch series. Once this bug fix
+patches series in the net branch makes it into the net-next branch
+we'll update the 3 other call sites to use the new helper.
+
+This is a long-standing issue. The Fixes tag below is chosen to be the
+oldest commit at which the patch will apply cleanly, which is from
+Linux v3.5 in 2012.
+
+Fixes: 1fbc340514fc ("tcp: early retransmit: tcp_enter_recovery()")
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Yuchung Cheng <ycheng@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20241001200517.2756803-3-ncardwell.sw@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 2437a196c1392..0f2320d821ffd 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -2320,6 +2320,16 @@ static bool tcp_any_retrans_done(const struct sock *sk)
+       return false;
+ }
++/* If loss recovery is finished and there are no retransmits out in the
++ * network, then we clear retrans_stamp so that upon the next loss recovery
++ * retransmits_timed_out() and timestamp-undo are using the correct value.
++ */
++static void tcp_retrans_stamp_cleanup(struct sock *sk)
++{
++      if (!tcp_any_retrans_done(sk))
++              tcp_sk(sk)->retrans_stamp = 0;
++}
++
+ static void DBGUNDO(struct sock *sk, const char *msg)
+ {
+ #if FASTRETRANS_DEBUG > 1
+@@ -2662,6 +2672,9 @@ void tcp_enter_recovery(struct sock *sk, bool ece_ack)
+       struct tcp_sock *tp = tcp_sk(sk);
+       int mib_idx;
++      /* Start the clock with our fast retransmit, for undo and ETIMEDOUT. */
++      tcp_retrans_stamp_cleanup(sk);
++
+       if (tcp_is_reno(tp))
+               mib_idx = LINUX_MIB_TCPRENORECOVERY;
+       else
+-- 
+2.43.0
+