diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-05 12:55:57 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-22 23:25:01 -0400 |
commit | 6b6ca86b77b62b798cf9ca2599036420abce7796 (patch) | |
tree | cf631a3c293be45fa4bed54bca5dcbfc96a57df1 | |
parent | da45828e2835057045150b318c4fbe9bb91f18dd (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.h | 5 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 8 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 28 |
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 | ||
131 | struct rpc_xprt { | 132 | struct 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); | |||
248 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); | 250 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
249 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); | 251 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
250 | void xprt_release(struct rpc_task *task); | 252 | void xprt_release(struct rpc_task *task); |
251 | int xprt_destroy(struct rpc_xprt *xprt); | 253 | struct rpc_xprt * xprt_get(struct rpc_xprt *xprt); |
254 | void xprt_put(struct rpc_xprt *xprt); | ||
252 | 255 | ||
253 | static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p) | 256 | static 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); |
179 | out_err: | 179 | out_err: |
180 | xprt_destroy(xprt); | 180 | xprt_put(xprt); |
181 | out_no_xprt: | 181 | out_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); |
346 | out_free: | 343 | out_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 | */ |
964 | int xprt_destroy(struct rpc_xprt *xprt) | 965 | static 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 | */ | ||
981 | void 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 | */ | ||
991 | struct rpc_xprt *xprt_get(struct rpc_xprt *xprt) | ||
992 | { | ||
993 | kref_get(&xprt->kref); | ||
994 | return xprt; | ||
973 | } | 995 | } |