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>
This commit is contained in:
parent
da45828e28
commit
6b6ca86b77
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
#include <linux/socket.h>
|
#include <linux/socket.h>
|
||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
|
#include <linux/kref.h>
|
||||||
#include <linux/sunrpc/sched.h>
|
#include <linux/sunrpc/sched.h>
|
||||||
#include <linux/sunrpc/xdr.h>
|
#include <linux/sunrpc/xdr.h>
|
||||||
|
|
||||||
|
@ -129,6 +130,7 @@ struct rpc_xprt_ops {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rpc_xprt {
|
struct rpc_xprt {
|
||||||
|
struct kref kref; /* Reference count */
|
||||||
struct rpc_xprt_ops * ops; /* transport methods */
|
struct rpc_xprt_ops * ops; /* transport methods */
|
||||||
struct socket * sock; /* BSD socket layer */
|
struct socket * sock; /* BSD socket layer */
|
||||||
struct sock * inet; /* INET layer */
|
struct sock * inet; /* INET layer */
|
||||||
|
@ -248,7 +250,8 @@ int xprt_adjust_timeout(struct rpc_rqst *req);
|
||||||
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
|
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||||
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
|
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||||
void xprt_release(struct rpc_task *task);
|
void xprt_release(struct rpc_task *task);
|
||||||
int xprt_destroy(struct rpc_xprt *xprt);
|
struct rpc_xprt * xprt_get(struct rpc_xprt *xprt);
|
||||||
|
void xprt_put(struct rpc_xprt *xprt);
|
||||||
|
|
||||||
static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
|
static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
|
||||||
{
|
{
|
||||||
|
|
|
@ -177,7 +177,7 @@ out_no_path:
|
||||||
kfree(clnt->cl_server);
|
kfree(clnt->cl_server);
|
||||||
kfree(clnt);
|
kfree(clnt);
|
||||||
out_err:
|
out_err:
|
||||||
xprt_destroy(xprt);
|
xprt_put(xprt);
|
||||||
out_no_xprt:
|
out_no_xprt:
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
@ -261,6 +261,7 @@ rpc_clone_client(struct rpc_clnt *clnt)
|
||||||
atomic_set(&new->cl_users, 0);
|
atomic_set(&new->cl_users, 0);
|
||||||
new->cl_parent = clnt;
|
new->cl_parent = clnt;
|
||||||
atomic_inc(&clnt->cl_count);
|
atomic_inc(&clnt->cl_count);
|
||||||
|
new->cl_xprt = xprt_get(clnt->cl_xprt);
|
||||||
/* Turn off autobind on clones */
|
/* Turn off autobind on clones */
|
||||||
new->cl_autobind = 0;
|
new->cl_autobind = 0;
|
||||||
new->cl_oneshot = 0;
|
new->cl_oneshot = 0;
|
||||||
|
@ -337,15 +338,12 @@ rpc_destroy_client(struct rpc_clnt *clnt)
|
||||||
rpc_rmdir(clnt->cl_dentry);
|
rpc_rmdir(clnt->cl_dentry);
|
||||||
rpc_put_mount();
|
rpc_put_mount();
|
||||||
}
|
}
|
||||||
if (clnt->cl_xprt) {
|
|
||||||
xprt_destroy(clnt->cl_xprt);
|
|
||||||
clnt->cl_xprt = NULL;
|
|
||||||
}
|
|
||||||
if (clnt->cl_server != clnt->cl_inline_name)
|
if (clnt->cl_server != clnt->cl_inline_name)
|
||||||
kfree(clnt->cl_server);
|
kfree(clnt->cl_server);
|
||||||
out_free:
|
out_free:
|
||||||
rpc_free_iostats(clnt->cl_metrics);
|
rpc_free_iostats(clnt->cl_metrics);
|
||||||
clnt->cl_metrics = NULL;
|
clnt->cl_metrics = NULL;
|
||||||
|
xprt_put(clnt->cl_xprt);
|
||||||
kfree(clnt);
|
kfree(clnt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -926,6 +926,7 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
|
||||||
return ERR_PTR(result);
|
return ERR_PTR(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kref_init(&xprt->kref);
|
||||||
spin_lock_init(&xprt->transport_lock);
|
spin_lock_init(&xprt->transport_lock);
|
||||||
spin_lock_init(&xprt->reserve_lock);
|
spin_lock_init(&xprt->reserve_lock);
|
||||||
|
|
||||||
|
@ -958,16 +959,37 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xprt_destroy - destroy an RPC transport, killing off all requests.
|
* xprt_destroy - destroy an RPC transport, killing off all requests.
|
||||||
* @xprt: transport to destroy
|
* @kref: kref for the transport to destroy
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int xprt_destroy(struct rpc_xprt *xprt)
|
static void xprt_destroy(struct kref *kref)
|
||||||
{
|
{
|
||||||
|
struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
|
||||||
|
|
||||||
dprintk("RPC: destroying transport %p\n", xprt);
|
dprintk("RPC: destroying transport %p\n", xprt);
|
||||||
xprt->shutdown = 1;
|
xprt->shutdown = 1;
|
||||||
del_timer_sync(&xprt->timer);
|
del_timer_sync(&xprt->timer);
|
||||||
xprt->ops->destroy(xprt);
|
xprt->ops->destroy(xprt);
|
||||||
kfree(xprt);
|
kfree(xprt);
|
||||||
|
}
|
||||||
return 0;
|
|
||||||
|
/**
|
||||||
|
* xprt_put - release a reference to an RPC transport.
|
||||||
|
* @xprt: pointer to the transport
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void xprt_put(struct rpc_xprt *xprt)
|
||||||
|
{
|
||||||
|
kref_put(&xprt->kref, xprt_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xprt_get - return a reference to an RPC transport.
|
||||||
|
* @xprt: pointer to the transport
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
|
||||||
|
{
|
||||||
|
kref_get(&xprt->kref);
|
||||||
|
return xprt;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue