diff options
-rw-r--r-- | include/linux/sunrpc/svc_xprt.h | 2 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 56 |
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 | ||
18 | struct svc_xprt_class { | 20 | struct 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); | |||
85 | static int svc_udp_recvfrom(struct svc_rqst *); | 85 | static int svc_udp_recvfrom(struct svc_rqst *); |
86 | static int svc_udp_sendto(struct svc_rqst *); | 86 | static int svc_udp_sendto(struct svc_rqst *); |
87 | static void svc_close_socket(struct svc_sock *svsk); | 87 | static void svc_close_socket(struct svc_sock *svsk); |
88 | static void svc_sock_detach(struct svc_xprt *); | ||
89 | static void svc_sock_free(struct svc_xprt *); | ||
88 | 90 | ||
89 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk); | 91 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk); |
90 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 92 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
@@ -376,16 +378,8 @@ static inline void | |||
376 | svc_sock_put(struct svc_sock *svsk) | 378 | svc_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 | ||
908 | static struct svc_xprt_class svc_udp_class = { | 904 | static 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 | ||
1363 | static struct svc_xprt_class svc_tcp_class = { | 1361 | static 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 | */ | ||
1819 | static 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 | */ | ||
1835 | static 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 | */ |
1820 | static void | 1852 | static 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 | ||