aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-05 12:55:57 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:25:01 -0400
commit6b6ca86b77b62b798cf9ca2599036420abce7796 (patch)
treecf631a3c293be45fa4bed54bca5dcbfc96a57df1
parentda45828e2835057045150b318c4fbe9bb91f18dd (diff)
SUNRPC: Add refcounting to the struct rpc_xprt
In a subsequent patch, this will allow the portmapper to take a reference to the rpc_xprt for which it is updating the port number, fixing an Oops. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--include/linux/sunrpc/xprt.h5
-rw-r--r--net/sunrpc/clnt.c8
-rw-r--r--net/sunrpc/xprt.c28
3 files changed, 32 insertions, 9 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index de4efea7c856..bdeba8538c71 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -12,6 +12,7 @@
12#include <linux/uio.h> 12#include <linux/uio.h>
13#include <linux/socket.h> 13#include <linux/socket.h>
14#include <linux/in.h> 14#include <linux/in.h>
15#include <linux/kref.h>
15#include <linux/sunrpc/sched.h> 16#include <linux/sunrpc/sched.h>
16#include <linux/sunrpc/xdr.h> 17#include <linux/sunrpc/xdr.h>
17 18
@@ -129,6 +130,7 @@ struct rpc_xprt_ops {
129}; 130};
130 131
131struct rpc_xprt { 132struct rpc_xprt {
133 struct kref kref; /* Reference count */
132 struct rpc_xprt_ops * ops; /* transport methods */ 134 struct rpc_xprt_ops * ops; /* transport methods */
133 struct socket * sock; /* BSD socket layer */ 135 struct socket * sock; /* BSD socket layer */
134 struct sock * inet; /* INET layer */ 136 struct sock * inet; /* INET layer */
@@ -248,7 +250,8 @@ int xprt_adjust_timeout(struct rpc_rqst *req);
248void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); 250void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
249void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); 251void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
250void xprt_release(struct rpc_task *task); 252void xprt_release(struct rpc_task *task);
251int xprt_destroy(struct rpc_xprt *xprt); 253struct rpc_xprt * xprt_get(struct rpc_xprt *xprt);
254void xprt_put(struct rpc_xprt *xprt);
252 255
253static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p) 256static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
254{ 257{
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ceadb728f0da..084a0ad5c64e 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -177,7 +177,7 @@ out_no_path:
177 kfree(clnt->cl_server); 177 kfree(clnt->cl_server);
178 kfree(clnt); 178 kfree(clnt);
179out_err: 179out_err:
180 xprt_destroy(xprt); 180 xprt_put(xprt);
181out_no_xprt: 181out_no_xprt:
182 return ERR_PTR(err); 182 return ERR_PTR(err);
183} 183}
@@ -261,6 +261,7 @@ rpc_clone_client(struct rpc_clnt *clnt)
261 atomic_set(&new->cl_users, 0); 261 atomic_set(&new->cl_users, 0);
262 new->cl_parent = clnt; 262 new->cl_parent = clnt;
263 atomic_inc(&clnt->cl_count); 263 atomic_inc(&clnt->cl_count);
264 new->cl_xprt = xprt_get(clnt->cl_xprt);
264 /* Turn off autobind on clones */ 265 /* Turn off autobind on clones */
265 new->cl_autobind = 0; 266 new->cl_autobind = 0;
266 new->cl_oneshot = 0; 267 new->cl_oneshot = 0;
@@ -337,15 +338,12 @@ rpc_destroy_client(struct rpc_clnt *clnt)
337 rpc_rmdir(clnt->cl_dentry); 338 rpc_rmdir(clnt->cl_dentry);
338 rpc_put_mount(); 339 rpc_put_mount();
339 } 340 }
340 if (clnt->cl_xprt) {
341 xprt_destroy(clnt->cl_xprt);
342 clnt->cl_xprt = NULL;
343 }
344 if (clnt->cl_server != clnt->cl_inline_name) 341 if (clnt->cl_server != clnt->cl_inline_name)
345 kfree(clnt->cl_server); 342 kfree(clnt->cl_server);
346out_free: 343out_free:
347 rpc_free_iostats(clnt->cl_metrics); 344 rpc_free_iostats(clnt->cl_metrics);
348 clnt->cl_metrics = NULL; 345 clnt->cl_metrics = NULL;
346 xprt_put(clnt->cl_xprt);
349 kfree(clnt); 347 kfree(clnt);
350 return 0; 348 return 0;
351} 349}
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index a85f82baefc1..1f786f68729d 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -926,6 +926,7 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
926 return ERR_PTR(result); 926 return ERR_PTR(result);
927 } 927 }
928 928
929 kref_init(&xprt->kref);
929 spin_lock_init(&xprt->transport_lock); 930 spin_lock_init(&xprt->transport_lock);
930 spin_lock_init(&xprt->reserve_lock); 931 spin_lock_init(&xprt->reserve_lock);
931 932
@@ -958,16 +959,37 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
958 959
959/** 960/**
960 * xprt_destroy - destroy an RPC transport, killing off all requests. 961 * xprt_destroy - destroy an RPC transport, killing off all requests.
961 * @xprt: transport to destroy 962 * @kref: kref for the transport to destroy
962 * 963 *
963 */ 964 */
964int xprt_destroy(struct rpc_xprt *xprt) 965static void xprt_destroy(struct kref *kref)
965{ 966{
967 struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
968
966 dprintk("RPC: destroying transport %p\n", xprt); 969 dprintk("RPC: destroying transport %p\n", xprt);
967 xprt->shutdown = 1; 970 xprt->shutdown = 1;
968 del_timer_sync(&xprt->timer); 971 del_timer_sync(&xprt->timer);
969 xprt->ops->destroy(xprt); 972 xprt->ops->destroy(xprt);
970 kfree(xprt); 973 kfree(xprt);
974}
971 975
972 return 0; 976/**
977 * xprt_put - release a reference to an RPC transport.
978 * @xprt: pointer to the transport
979 *
980 */
981void xprt_put(struct rpc_xprt *xprt)
982{
983 kref_put(&xprt->kref, xprt_destroy);
984}
985
986/**
987 * xprt_get - return a reference to an RPC transport.
988 * @xprt: pointer to the transport
989 *
990 */
991struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
992{
993 kref_get(&xprt->kref);
994 return xprt;
973} 995}