diff options
author | Andy Adamson <andros@netapp.com> | 2016-09-09 09:22:25 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-09-19 13:08:36 -0400 |
commit | 39e5d2df959dd4aea81fa33d765d2a5cc67a0512 (patch) | |
tree | 6766a5080986cb7f416638d12494b2f5761a5d16 | |
parent | dd69171769cf4649a7ff3755e91cbd242a833727 (diff) |
SUNRPC search xprt switch for sockaddr
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | include/linux/sunrpc/clnt.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/xprtmultipath.h | 2 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 15 | ||||
-rw-r--r-- | net/sunrpc/xprtmultipath.c | 24 |
4 files changed, 42 insertions, 1 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index b069d6e2c3d6..35cc539e2921 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -202,5 +202,7 @@ const char *rpc_proc_name(const struct rpc_task *task); | |||
202 | 202 | ||
203 | void rpc_clnt_xprt_switch_put(struct rpc_clnt *); | 203 | void rpc_clnt_xprt_switch_put(struct rpc_clnt *); |
204 | void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *, struct rpc_xprt *); | 204 | void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *, struct rpc_xprt *); |
205 | bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt, | ||
206 | const struct sockaddr *sap); | ||
205 | #endif /* __KERNEL__ */ | 207 | #endif /* __KERNEL__ */ |
206 | #endif /* _LINUX_SUNRPC_CLNT_H */ | 208 | #endif /* _LINUX_SUNRPC_CLNT_H */ |
diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h index 5a9acffa41be..507418c1c69e 100644 --- a/include/linux/sunrpc/xprtmultipath.h +++ b/include/linux/sunrpc/xprtmultipath.h | |||
@@ -66,4 +66,6 @@ extern struct rpc_xprt *xprt_iter_xprt(struct rpc_xprt_iter *xpi); | |||
66 | extern struct rpc_xprt *xprt_iter_get_xprt(struct rpc_xprt_iter *xpi); | 66 | extern struct rpc_xprt *xprt_iter_get_xprt(struct rpc_xprt_iter *xpi); |
67 | extern struct rpc_xprt *xprt_iter_get_next(struct rpc_xprt_iter *xpi); | 67 | extern struct rpc_xprt *xprt_iter_get_next(struct rpc_xprt_iter *xpi); |
68 | 68 | ||
69 | extern bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps, | ||
70 | const struct sockaddr *sap); | ||
69 | #endif | 71 | #endif |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 43ec46547dc9..8d68efd2026f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -2708,6 +2708,21 @@ void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt) | |||
2708 | } | 2708 | } |
2709 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt); | 2709 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt); |
2710 | 2710 | ||
2711 | bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt, | ||
2712 | const struct sockaddr *sap) | ||
2713 | { | ||
2714 | struct rpc_xprt_switch *xps; | ||
2715 | bool ret; | ||
2716 | |||
2717 | xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch); | ||
2718 | |||
2719 | rcu_read_lock(); | ||
2720 | ret = rpc_xprt_switch_has_addr(xps, sap); | ||
2721 | rcu_read_unlock(); | ||
2722 | return ret; | ||
2723 | } | ||
2724 | EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_has_addr); | ||
2725 | |||
2711 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 2726 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
2712 | static void rpc_show_header(void) | 2727 | static void rpc_show_header(void) |
2713 | { | 2728 | { |
diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index 66c9d63f4797..ae92a9e9ba52 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/cmpxchg.h> | 15 | #include <asm/cmpxchg.h> |
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/sunrpc/xprt.h> | 17 | #include <linux/sunrpc/xprt.h> |
18 | #include <linux/sunrpc/addr.h> | ||
18 | #include <linux/sunrpc/xprtmultipath.h> | 19 | #include <linux/sunrpc/xprtmultipath.h> |
19 | 20 | ||
20 | typedef struct rpc_xprt *(*xprt_switch_find_xprt_t)(struct list_head *head, | 21 | typedef struct rpc_xprt *(*xprt_switch_find_xprt_t)(struct list_head *head, |
@@ -49,7 +50,8 @@ void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps, | |||
49 | if (xprt == NULL) | 50 | if (xprt == NULL) |
50 | return; | 51 | return; |
51 | spin_lock(&xps->xps_lock); | 52 | spin_lock(&xps->xps_lock); |
52 | if (xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) | 53 | if ((xps->xps_net == xprt->xprt_net || xps->xps_net == NULL) && |
54 | !rpc_xprt_switch_has_addr(xps, (struct sockaddr *)&xprt->addr)) | ||
53 | xprt_switch_add_xprt_locked(xps, xprt); | 55 | xprt_switch_add_xprt_locked(xps, xprt); |
54 | spin_unlock(&xps->xps_lock); | 56 | spin_unlock(&xps->xps_lock); |
55 | } | 57 | } |
@@ -232,6 +234,26 @@ struct rpc_xprt *xprt_iter_current_entry(struct rpc_xprt_iter *xpi) | |||
232 | return xprt_switch_find_current_entry(head, xpi->xpi_cursor); | 234 | return xprt_switch_find_current_entry(head, xpi->xpi_cursor); |
233 | } | 235 | } |
234 | 236 | ||
237 | bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps, | ||
238 | const struct sockaddr *sap) | ||
239 | { | ||
240 | struct list_head *head; | ||
241 | struct rpc_xprt *pos; | ||
242 | |||
243 | if (xps == NULL || sap == NULL) | ||
244 | return false; | ||
245 | |||
246 | head = &xps->xps_xprt_list; | ||
247 | list_for_each_entry_rcu(pos, head, xprt_switch) { | ||
248 | if (rpc_cmp_addr_port(sap, (struct sockaddr *)&pos->addr)) { | ||
249 | pr_info("RPC: addr %s already in xprt switch\n", | ||
250 | pos->address_strings[RPC_DISPLAY_ADDR]); | ||
251 | return true; | ||
252 | } | ||
253 | } | ||
254 | return false; | ||
255 | } | ||
256 | |||
235 | static | 257 | static |
236 | struct rpc_xprt *xprt_switch_find_next_entry(struct list_head *head, | 258 | struct rpc_xprt *xprt_switch_find_next_entry(struct list_head *head, |
237 | const struct rpc_xprt *cur) | 259 | const struct rpc_xprt *cur) |