From 69b6ba3712b796a66595cfaf0a5ab4dfe1cf964a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Dec 2008 16:30:11 -0500 Subject: SUNRPC: Ensure the server closes sockets in a timely fashion We want to ensure that connected sockets close down the connection when we set XPT_CLOSE, so that we don't keep it hanging while cleaning up all the stuff that is keeping a reference to the socket. Signed-off-by: Trond Myklebust Signed-off-by: J. Bruce Fields --- net/sunrpc/svcsock.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'net/sunrpc/svcsock.c') diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index ef3238d665e..cccfa7deb9a 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -59,6 +59,7 @@ static void svc_udp_data_ready(struct sock *, int); static int svc_udp_recvfrom(struct svc_rqst *); static int svc_udp_sendto(struct svc_rqst *); static void svc_sock_detach(struct svc_xprt *); +static void svc_tcp_sock_detach(struct svc_xprt *); static void svc_sock_free(struct svc_xprt *); static struct svc_xprt *svc_create_socket(struct svc_serv *, int, @@ -1017,7 +1018,7 @@ static struct svc_xprt_ops svc_tcp_ops = { .xpo_recvfrom = svc_tcp_recvfrom, .xpo_sendto = svc_tcp_sendto, .xpo_release_rqst = svc_release_skb, - .xpo_detach = svc_sock_detach, + .xpo_detach = svc_tcp_sock_detach, .xpo_free = svc_sock_free, .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, .xpo_has_wspace = svc_tcp_has_wspace, @@ -1287,6 +1288,24 @@ static void svc_sock_detach(struct svc_xprt *xprt) sk->sk_state_change = svsk->sk_ostate; sk->sk_data_ready = svsk->sk_odata; sk->sk_write_space = svsk->sk_owspace; + + if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + wake_up_interruptible(sk->sk_sleep); +} + +/* + * Disconnect the socket, and reset the callbacks + */ +static void svc_tcp_sock_detach(struct svc_xprt *xprt) +{ + struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); + + dprintk("svc: svc_tcp_sock_detach(%p)\n", svsk); + + svc_sock_detach(xprt); + + if (!test_bit(XPT_LISTENER, &xprt->xpt_flags)) + kernel_sock_shutdown(svsk->sk_sock, SHUT_RDWR); } /* -- cgit v1.2.3-70-g09d2 From 2779e3ae39645515cb6c1126634f47c28c9e7190 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Mon, 5 Jan 2009 11:12:52 -0600 Subject: svc: Move kfree of deferral record to common code The rqstp structure has a pointer to a svc_deferred_req record that is allocated when requests are deferred. This record is common to all transports and can be freed in common code. Move the kfree of the rq_deferred to the common svc_xprt_release function. This also fixes a memory leak in the RDMA transport which does not kfree the dr structure in it's version of the xpo_release_rqst callback. Signed-off-by: Tom Tucker Signed-off-by: J. Bruce Fields --- net/sunrpc/svc_xprt.c | 3 +++ net/sunrpc/svcsock.c | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'net/sunrpc/svcsock.c') diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 3fe4f100427..29619612b9f 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -448,6 +448,9 @@ static void svc_xprt_release(struct svc_rqst *rqstp) rqstp->rq_xprt->xpt_ops->xpo_release_rqst(rqstp); + kfree(rqstp->rq_deferred); + rqstp->rq_deferred = NULL; + svc_free_res_pages(rqstp); rqstp->rq_res.page_len = 0; rqstp->rq_res.page_base = 0; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index cccfa7deb9a..3c103404501 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -103,7 +103,6 @@ static void svc_reclassify_socket(struct socket *sock) static void svc_release_skb(struct svc_rqst *rqstp) { struct sk_buff *skb = rqstp->rq_xprt_ctxt; - struct svc_deferred_req *dr = rqstp->rq_deferred; if (skb) { struct svc_sock *svsk = @@ -113,10 +112,6 @@ static void svc_release_skb(struct svc_rqst *rqstp) dprintk("svc: service %p, releasing skb %p\n", rqstp, skb); skb_free_datagram(svsk->sk_sk, skb); } - if (dr) { - rqstp->rq_deferred = NULL; - kfree(dr); - } } union svc_pktinfo_u { -- cgit v1.2.3-70-g09d2 From 24c3767e41a6a59d32bb45abe899eb194e6bf1b8 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Dec 2008 16:30:12 -0500 Subject: SUNRPC: The sunrpc server code should not be used by out-of-tree modules Signed-off-by: Trond Myklebust Signed-off-by: J. Bruce Fields --- net/sunrpc/cache.c | 20 ++++++++++---------- net/sunrpc/stats.c | 6 +++--- net/sunrpc/svc.c | 14 +++++++------- net/sunrpc/svc_xprt.c | 8 ++++---- net/sunrpc/svcauth.c | 14 +++++++------- net/sunrpc/svcauth_unix.c | 12 ++++++------ net/sunrpc/svcsock.c | 4 ++-- 7 files changed, 39 insertions(+), 39 deletions(-) (limited to 'net/sunrpc/svcsock.c') diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index c9966713282..4735caad26e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -98,7 +98,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, return new; } -EXPORT_SYMBOL(sunrpc_cache_lookup); +EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); static void queue_loose(struct cache_detail *detail, struct cache_head *ch); @@ -173,7 +173,7 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, cache_put(old, detail); return tmp; } -EXPORT_SYMBOL(sunrpc_cache_update); +EXPORT_SYMBOL_GPL(sunrpc_cache_update); static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); /* @@ -245,7 +245,7 @@ int cache_check(struct cache_detail *detail, cache_put(h, detail); return rv; } -EXPORT_SYMBOL(cache_check); +EXPORT_SYMBOL_GPL(cache_check); /* * caches need to be periodically cleaned. @@ -373,7 +373,7 @@ int cache_register(struct cache_detail *cd) schedule_delayed_work(&cache_cleaner, 0); return 0; } -EXPORT_SYMBOL(cache_register); +EXPORT_SYMBOL_GPL(cache_register); void cache_unregister(struct cache_detail *cd) { @@ -399,7 +399,7 @@ void cache_unregister(struct cache_detail *cd) out: printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); } -EXPORT_SYMBOL(cache_unregister); +EXPORT_SYMBOL_GPL(cache_unregister); /* clean cache tries to find something to clean * and cleans it. @@ -514,7 +514,7 @@ void cache_flush(void) while (cache_clean() != -1) cond_resched(); } -EXPORT_SYMBOL(cache_flush); +EXPORT_SYMBOL_GPL(cache_flush); void cache_purge(struct cache_detail *detail) { @@ -523,7 +523,7 @@ void cache_purge(struct cache_detail *detail) cache_flush(); detail->flush_time = 1; } -EXPORT_SYMBOL(cache_purge); +EXPORT_SYMBOL_GPL(cache_purge); /* @@ -988,7 +988,7 @@ void qword_add(char **bpp, int *lp, char *str) *bpp = bp; *lp = len; } -EXPORT_SYMBOL(qword_add); +EXPORT_SYMBOL_GPL(qword_add); void qword_addhex(char **bpp, int *lp, char *buf, int blen) { @@ -1017,7 +1017,7 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen) *bpp = bp; *lp = len; } -EXPORT_SYMBOL(qword_addhex); +EXPORT_SYMBOL_GPL(qword_addhex); static void warn_no_listener(struct cache_detail *detail) { @@ -1140,7 +1140,7 @@ int qword_get(char **bpp, char *dest, int bufsize) *dest = '\0'; return len; } -EXPORT_SYMBOL(qword_get); +EXPORT_SYMBOL_GPL(qword_get); /* diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 50b049c6598..085372ef4fe 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -106,7 +106,7 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) { seq_putc(seq, '\n'); } } -EXPORT_SYMBOL(svc_seq_show); +EXPORT_SYMBOL_GPL(svc_seq_show); /** * rpc_alloc_iostats - allocate an rpc_iostats structure @@ -249,14 +249,14 @@ svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) { return do_register(statp->program->pg_name, statp, fops); } -EXPORT_SYMBOL(svc_proc_register); +EXPORT_SYMBOL_GPL(svc_proc_register); void svc_proc_unregister(const char *name) { remove_proc_entry(name, proc_net_rpc); } -EXPORT_SYMBOL(svc_proc_unregister); +EXPORT_SYMBOL_GPL(svc_proc_unregister); void rpc_proc_init(void) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 54c98d87684..c51fed4d1af 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -431,7 +431,7 @@ svc_create(struct svc_program *prog, unsigned int bufsize, { return __svc_create(prog, bufsize, /*npools*/1, family, shutdown); } -EXPORT_SYMBOL(svc_create); +EXPORT_SYMBOL_GPL(svc_create); struct svc_serv * svc_create_pooled(struct svc_program *prog, unsigned int bufsize, @@ -450,7 +450,7 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, return serv; } -EXPORT_SYMBOL(svc_create_pooled); +EXPORT_SYMBOL_GPL(svc_create_pooled); /* * Destroy an RPC service. Should be called with appropriate locking to @@ -492,7 +492,7 @@ svc_destroy(struct svc_serv *serv) kfree(serv->sv_pools); kfree(serv); } -EXPORT_SYMBOL(svc_destroy); +EXPORT_SYMBOL_GPL(svc_destroy); /* * Allocate an RPC server's buffer space. @@ -567,7 +567,7 @@ out_thread: out_enomem: return ERR_PTR(-ENOMEM); } -EXPORT_SYMBOL(svc_prepare_thread); +EXPORT_SYMBOL_GPL(svc_prepare_thread); /* * Choose a pool in which to create a new thread, for svc_set_num_threads @@ -689,7 +689,7 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) return error; } -EXPORT_SYMBOL(svc_set_num_threads); +EXPORT_SYMBOL_GPL(svc_set_num_threads); /* * Called from a server thread as it's exiting. Caller must hold the BKL or @@ -717,7 +717,7 @@ svc_exit_thread(struct svc_rqst *rqstp) if (serv) svc_destroy(serv); } -EXPORT_SYMBOL(svc_exit_thread); +EXPORT_SYMBOL_GPL(svc_exit_thread); #ifdef CONFIG_SUNRPC_REGISTER_V4 @@ -1231,7 +1231,7 @@ err_bad: svc_putnl(resv, ntohl(rpc_stat)); goto sendit; } -EXPORT_SYMBOL(svc_process); +EXPORT_SYMBOL_GPL(svc_process); /* * Return (transport-specific) limit on the rpc payload. diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index a78b87937c7..e588df5d6b3 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -440,7 +440,7 @@ void svc_reserve(struct svc_rqst *rqstp, int space) svc_xprt_enqueue(xprt); } } -EXPORT_SYMBOL(svc_reserve); +EXPORT_SYMBOL_GPL(svc_reserve); static void svc_xprt_release(struct svc_rqst *rqstp) { @@ -501,7 +501,7 @@ void svc_wake_up(struct svc_serv *serv) spin_unlock_bh(&pool->sp_lock); } } -EXPORT_SYMBOL(svc_wake_up); +EXPORT_SYMBOL_GPL(svc_wake_up); int svc_port_is_privileged(struct sockaddr *sin) { @@ -743,7 +743,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) serv->sv_stats->netcnt++; return len; } -EXPORT_SYMBOL(svc_recv); +EXPORT_SYMBOL_GPL(svc_recv); /* * Drop request @@ -753,7 +753,7 @@ void svc_drop(struct svc_rqst *rqstp) dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt); svc_xprt_release(rqstp); } -EXPORT_SYMBOL(svc_drop); +EXPORT_SYMBOL_GPL(svc_drop); /* * Return reply to client. diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index 8a73cbb1605..e64109b02ae 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c @@ -57,13 +57,13 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp) rqstp->rq_authop = aops; return aops->accept(rqstp, authp); } -EXPORT_SYMBOL(svc_authenticate); +EXPORT_SYMBOL_GPL(svc_authenticate); int svc_set_client(struct svc_rqst *rqstp) { return rqstp->rq_authop->set_client(rqstp); } -EXPORT_SYMBOL(svc_set_client); +EXPORT_SYMBOL_GPL(svc_set_client); /* A request, which was authenticated, has now executed. * Time to finalise the credentials and verifier @@ -95,7 +95,7 @@ svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops) spin_unlock(&authtab_lock); return rv; } -EXPORT_SYMBOL(svc_auth_register); +EXPORT_SYMBOL_GPL(svc_auth_register); void svc_auth_unregister(rpc_authflavor_t flavor) @@ -105,7 +105,7 @@ svc_auth_unregister(rpc_authflavor_t flavor) authtab[flavor] = NULL; spin_unlock(&authtab_lock); } -EXPORT_SYMBOL(svc_auth_unregister); +EXPORT_SYMBOL_GPL(svc_auth_unregister); /************************************************** * 'auth_domains' are stored in a hash table indexed by name. @@ -132,7 +132,7 @@ void auth_domain_put(struct auth_domain *dom) spin_unlock(&auth_domain_lock); } } -EXPORT_SYMBOL(auth_domain_put); +EXPORT_SYMBOL_GPL(auth_domain_put); struct auth_domain * auth_domain_lookup(char *name, struct auth_domain *new) @@ -157,10 +157,10 @@ auth_domain_lookup(char *name, struct auth_domain *new) spin_unlock(&auth_domain_lock); return new; } -EXPORT_SYMBOL(auth_domain_lookup); +EXPORT_SYMBOL_GPL(auth_domain_lookup); struct auth_domain *auth_domain_find(char *name) { return auth_domain_lookup(name, NULL); } -EXPORT_SYMBOL(auth_domain_find); +EXPORT_SYMBOL_GPL(auth_domain_find); diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 82240e6127b..5c865e2d299 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -64,7 +64,7 @@ struct auth_domain *unix_domain_find(char *name) rv = auth_domain_lookup(name, &new->h); } } -EXPORT_SYMBOL(unix_domain_find); +EXPORT_SYMBOL_GPL(unix_domain_find); static void svcauth_unix_domain_release(struct auth_domain *dom) { @@ -358,7 +358,7 @@ int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom) else return -ENOMEM; } -EXPORT_SYMBOL(auth_unix_add_addr); +EXPORT_SYMBOL_GPL(auth_unix_add_addr); int auth_unix_forget_old(struct auth_domain *dom) { @@ -370,7 +370,7 @@ int auth_unix_forget_old(struct auth_domain *dom) udom->addr_changes++; return 0; } -EXPORT_SYMBOL(auth_unix_forget_old); +EXPORT_SYMBOL_GPL(auth_unix_forget_old); struct auth_domain *auth_unix_lookup(struct in6_addr *addr) { @@ -395,13 +395,13 @@ struct auth_domain *auth_unix_lookup(struct in6_addr *addr) cache_put(&ipm->h, &ip_map_cache); return rv; } -EXPORT_SYMBOL(auth_unix_lookup); +EXPORT_SYMBOL_GPL(auth_unix_lookup); void svcauth_unix_purge(void) { cache_purge(&ip_map_cache); } -EXPORT_SYMBOL(svcauth_unix_purge); +EXPORT_SYMBOL_GPL(svcauth_unix_purge); static inline struct ip_map * ip_map_cached_get(struct svc_rqst *rqstp) @@ -714,7 +714,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) return SVC_OK; } -EXPORT_SYMBOL(svcauth_unix_set_client); +EXPORT_SYMBOL_GPL(svcauth_unix_set_client); static int svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 3c103404501..5763e6460fe 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -285,7 +285,7 @@ svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) return -ENOENT; return len; } -EXPORT_SYMBOL(svc_sock_names); +EXPORT_SYMBOL_GPL(svc_sock_names); /* * Check input queue length @@ -1097,7 +1097,7 @@ void svc_sock_update_bufs(struct svc_serv *serv) } spin_unlock_bh(&serv->sv_lock); } -EXPORT_SYMBOL(svc_sock_update_bufs); +EXPORT_SYMBOL_GPL(svc_sock_update_bufs); /* * Initialize socket for RPC use and create svc_sock struct -- cgit v1.2.3-70-g09d2