Merge tag 'xtensa-20210902' of git://github.com/jcmvbkbc/linux-xtensa
[linux-2.6-microblaze.git] / net / sunrpc / clnt.c
index 42623d6..8b4de70 100644 (file)
@@ -41,6 +41,7 @@
 #include <trace/events/sunrpc.h>
 
 #include "sunrpc.h"
+#include "sysfs.h"
 #include "netns.h"
 
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
@@ -327,6 +328,7 @@ err_auth:
 out:
        if (pipefs_sb)
                rpc_put_sb_net(net);
+       rpc_sysfs_client_destroy(clnt);
        rpc_clnt_debugfs_unregister(clnt);
        return err;
 }
@@ -410,6 +412,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
        }
 
        rpc_clnt_set_transport(clnt, xprt, timeout);
+       xprt->main = true;
        xprt_iter_init(&clnt->cl_xpi, xps);
        xprt_switch_put(xps);
 
@@ -423,6 +426,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
        /* save the nodename */
        rpc_clnt_set_nodename(clnt, nodename);
 
+       rpc_sysfs_client_setup(clnt, xps, rpc_net_ns(clnt));
        err = rpc_client_register(clnt, args->authflavor, args->client_name);
        if (err)
                goto out_no_path;
@@ -733,6 +737,7 @@ int rpc_switch_client_transport(struct rpc_clnt *clnt,
 
        rpc_unregister_client(clnt);
        __rpc_clnt_remove_pipedir(clnt);
+       rpc_sysfs_client_destroy(clnt);
        rpc_clnt_debugfs_unregister(clnt);
 
        /*
@@ -879,6 +884,7 @@ static void rpc_free_client_work(struct work_struct *work)
         * so they cannot be called in rpciod, so they are handled separately
         * here.
         */
+       rpc_sysfs_client_destroy(clnt);
        rpc_clnt_debugfs_unregister(clnt);
        rpc_free_clid(clnt);
        rpc_clnt_remove_pipedir(clnt);
@@ -2100,6 +2106,30 @@ call_connect_status(struct rpc_task *task)
        case -ENOTCONN:
        case -EAGAIN:
        case -ETIMEDOUT:
+               if (!(task->tk_flags & RPC_TASK_NO_ROUND_ROBIN) &&
+                   (task->tk_flags & RPC_TASK_MOVEABLE) &&
+                   test_bit(XPRT_REMOVE, &xprt->state)) {
+                       struct rpc_xprt *saved = task->tk_xprt;
+                       struct rpc_xprt_switch *xps;
+
+                       rcu_read_lock();
+                       xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
+                       rcu_read_unlock();
+                       if (xps->xps_nxprts > 1) {
+                               long value;
+
+                               xprt_release(task);
+                               value = atomic_long_dec_return(&xprt->queuelen);
+                               if (value == 0)
+                                       rpc_xprt_switch_remove_xprt(xps, saved);
+                               xprt_put(saved);
+                               task->tk_xprt = NULL;
+                               task->tk_action = call_start;
+                       }
+                       xprt_switch_put(xps);
+                       if (!task->tk_xprt)
+                               return;
+               }
                goto out_retry;
        case -ENOBUFS:
                rpc_delay(task, HZ >> 2);