diff options
Diffstat (limited to 'fs/lockd/mon.c')
| -rw-r--r-- | fs/lockd/mon.c | 57 |
1 files changed, 32 insertions, 25 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e4fb3ba5a58a..3d7e09bcc0e9 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
| @@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net) | |||
| 85 | return rpc_create(&args); | 85 | return rpc_create(&args); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static struct rpc_clnt *nsm_client_set(struct lockd_net *ln, | ||
| 89 | struct rpc_clnt *clnt) | ||
| 90 | { | ||
| 91 | spin_lock(&ln->nsm_clnt_lock); | ||
| 92 | if (ln->nsm_users == 0) { | ||
| 93 | if (clnt == NULL) | ||
| 94 | goto out; | ||
| 95 | ln->nsm_clnt = clnt; | ||
| 96 | } | ||
| 97 | clnt = ln->nsm_clnt; | ||
| 98 | ln->nsm_users++; | ||
| 99 | out: | ||
| 100 | spin_unlock(&ln->nsm_clnt_lock); | ||
| 101 | return clnt; | ||
| 102 | } | ||
| 103 | |||
| 88 | static struct rpc_clnt *nsm_client_get(struct net *net) | 104 | static struct rpc_clnt *nsm_client_get(struct net *net) |
| 89 | { | 105 | { |
| 90 | static DEFINE_MUTEX(nsm_create_mutex); | 106 | struct rpc_clnt *clnt, *new; |
| 91 | struct rpc_clnt *clnt; | ||
| 92 | struct lockd_net *ln = net_generic(net, lockd_net_id); | 107 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
| 93 | 108 | ||
| 94 | spin_lock(&ln->nsm_clnt_lock); | 109 | clnt = nsm_client_set(ln, NULL); |
| 95 | if (ln->nsm_users) { | 110 | if (clnt != NULL) |
| 96 | ln->nsm_users++; | ||
| 97 | clnt = ln->nsm_clnt; | ||
| 98 | spin_unlock(&ln->nsm_clnt_lock); | ||
| 99 | goto out; | 111 | goto out; |
| 100 | } | ||
| 101 | spin_unlock(&ln->nsm_clnt_lock); | ||
| 102 | 112 | ||
| 103 | mutex_lock(&nsm_create_mutex); | 113 | clnt = new = nsm_create(net); |
| 104 | clnt = nsm_create(net); | 114 | if (IS_ERR(clnt)) |
| 105 | if (!IS_ERR(clnt)) { | 115 | goto out; |
| 106 | ln->nsm_clnt = clnt; | 116 | |
| 107 | smp_wmb(); | 117 | clnt = nsm_client_set(ln, new); |
| 108 | ln->nsm_users = 1; | 118 | if (clnt != new) |
| 109 | } | 119 | rpc_shutdown_client(new); |
| 110 | mutex_unlock(&nsm_create_mutex); | ||
| 111 | out: | 120 | out: |
| 112 | return clnt; | 121 | return clnt; |
| 113 | } | 122 | } |
| @@ -115,18 +124,16 @@ out: | |||
| 115 | static void nsm_client_put(struct net *net) | 124 | static void nsm_client_put(struct net *net) |
| 116 | { | 125 | { |
| 117 | struct lockd_net *ln = net_generic(net, lockd_net_id); | 126 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
| 118 | struct rpc_clnt *clnt = ln->nsm_clnt; | 127 | struct rpc_clnt *clnt = NULL; |
| 119 | int shutdown = 0; | ||
| 120 | 128 | ||
| 121 | spin_lock(&ln->nsm_clnt_lock); | 129 | spin_lock(&ln->nsm_clnt_lock); |
| 122 | if (ln->nsm_users) { | 130 | ln->nsm_users--; |
| 123 | if (--ln->nsm_users) | 131 | if (ln->nsm_users == 0) { |
| 124 | ln->nsm_clnt = NULL; | 132 | clnt = ln->nsm_clnt; |
| 125 | shutdown = !ln->nsm_users; | 133 | ln->nsm_clnt = NULL; |
| 126 | } | 134 | } |
| 127 | spin_unlock(&ln->nsm_clnt_lock); | 135 | spin_unlock(&ln->nsm_clnt_lock); |
| 128 | 136 | if (clnt != NULL) | |
| 129 | if (shutdown) | ||
| 130 | rpc_shutdown_client(clnt); | 137 | rpc_shutdown_client(clnt); |
| 131 | } | 138 | } |
| 132 | 139 | ||
