svc: Add svc API that queries for a transport instance

Add a new svc function that allows a service to query whether a
transport instance has already been created. This is used in lockd
to determine whether or not a transport needs to be created when
a lockd instance is brought up.

Specifying 0 for the address family or port is effectively a wild-card,
and will result in matching the first transport in the service's list
that has a matching class name.

Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
Acked-by: Neil Brown <neilb@suse.de>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Greg Banks <gnb@sgi.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

authored by Tom Tucker and committed by J. Bruce Fields 7fcb98d5 dc9a16e4

+38 -14
+2 -14
fs/lockd/svc.c
··· 219 module_put_and_exit(0); 220 } 221 222 - static int find_xprt(struct svc_serv *serv, char *proto) 223 - { 224 - struct svc_xprt *xprt; 225 - int found = 0; 226 - list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) 227 - if (strcmp(xprt->xpt_class->xcl_name, proto) == 0) { 228 - found = 1; 229 - break; 230 - } 231 - return found; 232 - } 233 - 234 /* 235 * Make any sockets that are needed but not present. 236 * If nlm_udpport or nlm_tcpport were set as module ··· 230 int err = 0; 231 232 if (proto == IPPROTO_UDP || nlm_udpport) 233 - if (!find_xprt(serv, "udp")) 234 err = svc_create_xprt(serv, "udp", nlm_udpport, 235 SVC_SOCK_DEFAULTS); 236 if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) 237 - if (!find_xprt(serv, "tcp")) 238 err = svc_create_xprt(serv, "tcp", nlm_tcpport, 239 SVC_SOCK_DEFAULTS); 240
··· 219 module_put_and_exit(0); 220 } 221 222 /* 223 * Make any sockets that are needed but not present. 224 * If nlm_udpport or nlm_tcpport were set as module ··· 242 int err = 0; 243 244 if (proto == IPPROTO_UDP || nlm_udpport) 245 + if (!svc_find_xprt(serv, "udp", 0, 0)) 246 err = svc_create_xprt(serv, "udp", nlm_udpport, 247 SVC_SOCK_DEFAULTS); 248 if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) 249 + if (!svc_find_xprt(serv, "tcp", 0, 0)) 250 err = svc_create_xprt(serv, "tcp", nlm_tcpport, 251 SVC_SOCK_DEFAULTS); 252
+1
include/linux/sunrpc/svc_xprt.h
··· 80 void svc_delete_xprt(struct svc_xprt *xprt); 81 int svc_port_is_privileged(struct sockaddr *sin); 82 int svc_print_xprts(char *buf, int maxlen); 83 84 static inline void svc_xprt_get(struct svc_xprt *xprt) 85 {
··· 80 void svc_delete_xprt(struct svc_xprt *xprt); 81 int svc_port_is_privileged(struct sockaddr *sin); 82 int svc_print_xprts(char *buf, int maxlen); 83 + struct svc_xprt *svc_find_xprt(struct svc_serv *, char *, int, int); 84 85 static inline void svc_xprt_get(struct svc_xprt *xprt) 86 {
+35
net/sunrpc/svc_xprt.c
··· 977 spin_unlock(&xprt->xpt_lock); 978 return dr; 979 }
··· 977 spin_unlock(&xprt->xpt_lock); 978 return dr; 979 } 980 + 981 + /* 982 + * Return the transport instance pointer for the endpoint accepting 983 + * connections/peer traffic from the specified transport class, 984 + * address family and port. 985 + * 986 + * Specifying 0 for the address family or port is effectively a 987 + * wild-card, and will result in matching the first transport in the 988 + * service's list that has a matching class name. 989 + */ 990 + struct svc_xprt *svc_find_xprt(struct svc_serv *serv, char *xcl_name, 991 + int af, int port) 992 + { 993 + struct svc_xprt *xprt; 994 + struct svc_xprt *found = NULL; 995 + 996 + /* Sanity check the args */ 997 + if (!serv || !xcl_name) 998 + return found; 999 + 1000 + spin_lock_bh(&serv->sv_lock); 1001 + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { 1002 + if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) 1003 + continue; 1004 + if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) 1005 + continue; 1006 + if (port && port != svc_xprt_local_port(xprt)) 1007 + continue; 1008 + found = xprt; 1009 + break; 1010 + } 1011 + spin_unlock_bh(&serv->sv_lock); 1012 + return found; 1013 + } 1014 + EXPORT_SYMBOL_GPL(svc_find_xprt);