nfs_swap_activate() calls rpc_clnt_swap_activate(), which unconditionally increments the cl_swapper refcount via atomic_inc_return(). If the subsequent call to rpc_clnt_iterate_for_each_xprt() fails (e.g. the callback xprt_enable_swap() returns an error), rpc_clnt_swap_activate() returns the error without decrementing the refcount. Back in nfs_swap_activate(), a nonzero return value is treated as a fatal error and causes an immediate return, so the elevated cl_swapper count is never released. Fix this by adding an atomic_dec() in the error path of rpc_clnt_swap_activate() before returning the error code, so that a failed activation properly cleans up the refcount. Cc: stable@vger.kernel.org Fixes: 15001e5a7e1e ("SUNRPC: Make NFS swap work with multipath") Signed-off-by: WenTao Liang --- net/sunrpc/clnt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index bc8ca470718b..97ab7aa71997 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -3396,9 +3396,13 @@ rpc_clnt_swap_activate(struct rpc_clnt *clnt) { while (clnt != clnt->cl_parent) clnt = clnt->cl_parent; - if (atomic_inc_return(&clnt->cl_swapper) == 1) - return rpc_clnt_iterate_for_each_xprt(clnt, + if (atomic_inc_return(&clnt->cl_swapper) == 1) { + int ret = rpc_clnt_iterate_for_each_xprt(clnt, rpc_clnt_swap_activate_callback, NULL); + if (ret) + atomic_dec(&clnt->cl_swapper); + return ret; + } return 0; } EXPORT_SYMBOL_GPL(rpc_clnt_swap_activate); -- 2.50.1 (Apple Git-155)