Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b6ca86b authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent da45828e
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -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)
{
{
+3 −5
Original line number Original line Diff line number Diff line
@@ -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;
}
}
+25 −3
Original line number Original line Diff line number Diff line
@@ -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;
}
}