aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2007-12-30 22:07:27 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-02-01 16:42:08 -0500
commit755cceaba7555027e61dfa79f1e55bdfc6906633 (patch)
tree13fa81b19e96af8130414b3535ced72b910a1aef
parent5148bf4ebc1f59dc6a0ec43a220c55ff0771246e (diff)
svc: Add per-transport delete functions
Add transport specific xpo_detach and xpo_free functions. The xpo_detach function causes the transport to stop delivering data-ready events and enqueing the transport for I/O. The xpo_free function frees all resources associated with the particular transport instance. 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>
-rw-r--r--include/linux/sunrpc/svc_xprt.h2
-rw-r--r--net/sunrpc/svcsock.c56
2 files changed, 45 insertions, 13 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 01ee7bc2c374..f032fb6b32e9 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -13,6 +13,8 @@ struct svc_xprt_ops {
13 int (*xpo_recvfrom)(struct svc_rqst *); 13 int (*xpo_recvfrom)(struct svc_rqst *);
14 int (*xpo_sendto)(struct svc_rqst *); 14 int (*xpo_sendto)(struct svc_rqst *);
15 void (*xpo_release_rqst)(struct svc_rqst *); 15 void (*xpo_release_rqst)(struct svc_rqst *);
16 void (*xpo_detach)(struct svc_xprt *);
17 void (*xpo_free)(struct svc_xprt *);
16}; 18};
17 19
18struct svc_xprt_class { 20struct svc_xprt_class {
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d46abc89b99a..44a729d6efea 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -85,6 +85,8 @@ static void svc_udp_data_ready(struct sock *, int);
85static int svc_udp_recvfrom(struct svc_rqst *); 85static int svc_udp_recvfrom(struct svc_rqst *);
86static int svc_udp_sendto(struct svc_rqst *); 86static int svc_udp_sendto(struct svc_rqst *);
87static void svc_close_socket(struct svc_sock *svsk); 87static void svc_close_socket(struct svc_sock *svsk);
88static void svc_sock_detach(struct svc_xprt *);
89static void svc_sock_free(struct svc_xprt *);
88 90
89static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk); 91static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk);
90static int svc_deferred_recv(struct svc_rqst *rqstp); 92static int svc_deferred_recv(struct svc_rqst *rqstp);
@@ -376,16 +378,8 @@ static inline void
376svc_sock_put(struct svc_sock *svsk) 378svc_sock_put(struct svc_sock *svsk)
377{ 379{
378 if (atomic_dec_and_test(&svsk->sk_inuse)) { 380 if (atomic_dec_and_test(&svsk->sk_inuse)) {
379 BUG_ON(! test_bit(SK_DEAD, &svsk->sk_flags)); 381 BUG_ON(!test_bit(SK_DEAD, &svsk->sk_flags));
380 382 svsk->sk_xprt.xpt_ops->xpo_free(&svsk->sk_xprt);
381 dprintk("svc: releasing dead socket\n");
382 if (svsk->sk_sock->file)
383 sockfd_put(svsk->sk_sock);
384 else
385 sock_release(svsk->sk_sock);
386 if (svsk->sk_info_authunix != NULL)
387 svcauth_unix_info_release(svsk->sk_info_authunix);
388 kfree(svsk);
389 } 383 }
390} 384}
391 385
@@ -903,6 +897,8 @@ static struct svc_xprt_ops svc_udp_ops = {
903 .xpo_recvfrom = svc_udp_recvfrom, 897 .xpo_recvfrom = svc_udp_recvfrom,
904 .xpo_sendto = svc_udp_sendto, 898 .xpo_sendto = svc_udp_sendto,
905 .xpo_release_rqst = svc_release_skb, 899 .xpo_release_rqst = svc_release_skb,
900 .xpo_detach = svc_sock_detach,
901 .xpo_free = svc_sock_free,
906}; 902};
907 903
908static struct svc_xprt_class svc_udp_class = { 904static struct svc_xprt_class svc_udp_class = {
@@ -1358,6 +1354,8 @@ static struct svc_xprt_ops svc_tcp_ops = {
1358 .xpo_recvfrom = svc_tcp_recvfrom, 1354 .xpo_recvfrom = svc_tcp_recvfrom,
1359 .xpo_sendto = svc_tcp_sendto, 1355 .xpo_sendto = svc_tcp_sendto,
1360 .xpo_release_rqst = svc_release_skb, 1356 .xpo_release_rqst = svc_release_skb,
1357 .xpo_detach = svc_sock_detach,
1358 .xpo_free = svc_sock_free,
1361}; 1359};
1362 1360
1363static struct svc_xprt_class svc_tcp_class = { 1361static struct svc_xprt_class svc_tcp_class = {
@@ -1815,6 +1813,40 @@ bummer:
1815} 1813}
1816 1814
1817/* 1815/*
1816 * Detach the svc_sock from the socket so that no
1817 * more callbacks occur.
1818 */
1819static void svc_sock_detach(struct svc_xprt *xprt)
1820{
1821 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1822 struct sock *sk = svsk->sk_sk;
1823
1824 dprintk("svc: svc_sock_detach(%p)\n", svsk);
1825
1826 /* put back the old socket callbacks */
1827 sk->sk_state_change = svsk->sk_ostate;
1828 sk->sk_data_ready = svsk->sk_odata;
1829 sk->sk_write_space = svsk->sk_owspace;
1830}
1831
1832/*
1833 * Free the svc_sock's socket resources and the svc_sock itself.
1834 */
1835static void svc_sock_free(struct svc_xprt *xprt)
1836{
1837 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1838 dprintk("svc: svc_sock_free(%p)\n", svsk);
1839
1840 if (svsk->sk_info_authunix != NULL)
1841 svcauth_unix_info_release(svsk->sk_info_authunix);
1842 if (svsk->sk_sock->file)
1843 sockfd_put(svsk->sk_sock);
1844 else
1845 sock_release(svsk->sk_sock);
1846 kfree(svsk);
1847}
1848
1849/*
1818 * Remove a dead socket 1850 * Remove a dead socket
1819 */ 1851 */
1820static void 1852static void
@@ -1828,9 +1860,7 @@ svc_delete_socket(struct svc_sock *svsk)
1828 serv = svsk->sk_server; 1860 serv = svsk->sk_server;
1829 sk = svsk->sk_sk; 1861 sk = svsk->sk_sk;
1830 1862
1831 sk->sk_state_change = svsk->sk_ostate; 1863 svsk->sk_xprt.xpt_ops->xpo_detach(&svsk->sk_xprt);
1832 sk->sk_data_ready = svsk->sk_odata;
1833 sk->sk_write_space = svsk->sk_owspace;
1834 1864
1835 spin_lock_bh(&serv->sv_lock); 1865 spin_lock_bh(&serv->sv_lock);
1836 1866