While running stress-ng on an ARM64 kernel, the following oops was observedi -
44837.761523: <6> Unable to handle kernel paging request at virtual address 0000004a88287000 44837.761651: <2> pc : in_dev_finish_destroy+0x4c/0xc8 44837.761654: <2> lr : in_dev_finish_destroy+0x2c/0xc8 44837.762393: <2> Call trace: 44837.762398: <2> in_dev_finish_destroy+0x4c/0xc8 44837.762404: <2> in_dev_rcu_put+0x24/0x30 44837.762412: <2> rcu_nocb_kthread+0x43c/0x468 44837.762418: <2> kthread+0x118/0x128 44837.762424: <2> ret_from_fork+0x10/0x1c Prior to this, it appeared as if some of the inet6_dev allocations were failing. From the memory dump, the last operation performed was dev_put(), however the pcpu_refcnt was NULL while the reg_state = NETREG_RELEASED. Effectively, the refcount memory was freed in free_netdev() before the last reference was dropped. Fix this by freeing the memory after all references are dropped and before the dev memory itself is freed. Fixes: 29b4433d991c ("net: percpu net_device refcount") Cc: Sean Tranchetti <stran...@codeaurora.org> Signed-off-by: Subash Abhinov Kasiviswanathan <subas...@codeaurora.org> --- net/core/dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 49589ed..bce40d8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9128,6 +9128,9 @@ void netdev_freemem(struct net_device *dev) { char *addr = (char *)dev - dev->padded; + free_percpu(dev->pcpu_refcnt); + dev->pcpu_refcnt = NULL; + kvfree(addr); } @@ -9272,9 +9275,6 @@ void free_netdev(struct net_device *dev) list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) netif_napi_del(p); - free_percpu(dev->pcpu_refcnt); - dev->pcpu_refcnt = NULL; - /* Compatibility with error handling in drivers */ if (dev->reg_state == NETREG_UNINITIALIZED) { netdev_freemem(dev); -- 1.9.1