FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Ubuntu > Ubuntu Kernel Team

 
 
LinkBack Thread Tools
 
Old 03-24-2009, 12:55 PM
Stefan Bader
 
Default SUNRPC: Fix autobind on cloned rpc clients

From: Trond Myklebust <Trond.Myklebust@netapp.com>

Bug: #212485, #341783

commit 9a4bd29fe8f6d3f015fe1c8e5450eb62cfebfcc9 upstream

Despite the fact that cloned rpc clients won't have the cl_autobind flag
set, they may still find themselves calling rpcb_getport_async(). For this
to happen, it suffices for a _parent_ rpc_clnt to use autobinding, in which
case any clone may find itself triggering the !xprt_bound() case in
call_bind().

The correct fix for this is to walk back up the tree of cloned rpc clients,
in order to find the parent that 'owns' the transport, either because it
has clnt->cl_autobind set, or because it originally created the
transport...

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
---
net/sunrpc/rpcb_clnt.c | 36 +++++++++++++++++++++++++++++-------
1 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index f42433d..201a4ae 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -295,6 +295,28 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
}
EXPORT_SYMBOL_GPL(rpcb_getport_sync);

+/*
+ * In the case where rpc clients have been cloned, we want to make
+ * sure that we use the program number/version etc of the actual
+ * owner of the xprt. To do so, we walk back up the tree of parents
+ * to find whoever created the transport and/or whoever has the
+ * autobind flag set.
+ */
+static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
+{
+ struct rpc_clnt *parent = clnt->cl_parent;
+
+ while (parent != clnt) {
+ if (parent->cl_xprt != clnt->cl_xprt)
+ break;
+ if (clnt->cl_autobind)
+ break;
+ clnt = parent;
+ parent = parent->cl_parent;
+ }
+ return clnt;
+}
+
/**
* rpcb_getport_async - obtain the port for a given RPC service on a given host
* @task: task that is waiting for portmapper request
@@ -304,9 +326,9 @@ EXPORT_SYMBOL_GPL(rpcb_getport_sync);
*/
void rpcb_getport_async(struct rpc_task *task)
{
- struct rpc_clnt *clnt = task->tk_client;
+ struct rpc_clnt *clnt;
int bind_version;
- struct rpc_xprt *xprt = task->tk_xprt;
+ struct rpc_xprt *xprt;
struct rpc_clnt *rpcb_clnt;
static struct rpcbind_args *map;
struct rpc_task *child;
@@ -314,13 +336,13 @@ void rpcb_getport_async(struct rpc_task *task)
int status;
struct rpcb_info *info;

+ clnt = rpcb_find_transport_owner(task->tk_client);
+ xprt = clnt->cl_xprt;
+
dprintk("RPC: %5u %s(%s, %u, %u, %d)
",
task->tk_pid, __FUNCTION__,
clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);

- /* Autobind on cloned rpc clients is discouraged */
- BUG_ON(clnt->cl_parent != clnt);
-
if (xprt_test_and_set_binding(xprt)) {
status = -EAGAIN; /* tell caller to check again */
dprintk("RPC: %5u %s: waiting for another binder
",
@@ -401,9 +423,9 @@ void rpcb_getport_async(struct rpc_task *task)
task->tk_pid, __FUNCTION__);
goto bailout;
}
- rpc_put_task(child);

- task->tk_xprt->stat.bind_count++;
+ xprt->stat.bind_count++;
+ rpc_put_task(child);
return;

bailout:
--
1.5.4.3


--
kernel-team mailing list
kernel-team@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/kernel-team
 
Old 03-24-2009, 03:13 PM
Andy Whitcroft
 
Default SUNRPC: Fix autobind on cloned rpc clients

On Tue, Mar 24, 2009 at 02:55:20PM +0100, Stefan Bader wrote:
> From: Trond Myklebust <Trond.Myklebust@netapp.com>
>
> Bug: #212485, #341783
>
> commit 9a4bd29fe8f6d3f015fe1c8e5450eb62cfebfcc9 upstream
>
> Despite the fact that cloned rpc clients won't have the cl_autobind flag
> set, they may still find themselves calling rpcb_getport_async(). For this
> to happen, it suffices for a _parent_ rpc_clnt to use autobinding, in which
> case any clone may find itself triggering the !xprt_bound() case in
> call_bind().
>
> The correct fix for this is to walk back up the tree of cloned rpc clients,
> in order to find the parent that 'owns' the transport, either because it
> has clnt->cl_autobind set, or because it originally created the
> transport...
>
> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
> ---
> net/sunrpc/rpcb_clnt.c | 36 +++++++++++++++++++++++++++++-------
> 1 files changed, 29 insertions(+), 7 deletions(-)
>
> diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
> index f42433d..201a4ae 100644
> --- a/net/sunrpc/rpcb_clnt.c
> +++ b/net/sunrpc/rpcb_clnt.c
> @@ -295,6 +295,28 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
> }
> EXPORT_SYMBOL_GPL(rpcb_getport_sync);
>
> +/*
> + * In the case where rpc clients have been cloned, we want to make
> + * sure that we use the program number/version etc of the actual
> + * owner of the xprt. To do so, we walk back up the tree of parents
> + * to find whoever created the transport and/or whoever has the
> + * autobind flag set.
> + */
> +static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
> +{
> + struct rpc_clnt *parent = clnt->cl_parent;
> +
> + while (parent != clnt) {
> + if (parent->cl_xprt != clnt->cl_xprt)
> + break;
> + if (clnt->cl_autobind)
> + break;
> + clnt = parent;
> + parent = parent->cl_parent;
> + }
> + return clnt;
> +}
> +
> /**
> * rpcb_getport_async - obtain the port for a given RPC service on a given host
> * @task: task that is waiting for portmapper request
> @@ -304,9 +326,9 @@ EXPORT_SYMBOL_GPL(rpcb_getport_sync);
> */
> void rpcb_getport_async(struct rpc_task *task)
> {
> - struct rpc_clnt *clnt = task->tk_client;
> + struct rpc_clnt *clnt;
> int bind_version;
> - struct rpc_xprt *xprt = task->tk_xprt;
> + struct rpc_xprt *xprt;
> struct rpc_clnt *rpcb_clnt;
> static struct rpcbind_args *map;
> struct rpc_task *child;
> @@ -314,13 +336,13 @@ void rpcb_getport_async(struct rpc_task *task)
> int status;
> struct rpcb_info *info;
>
> + clnt = rpcb_find_transport_owner(task->tk_client);
> + xprt = clnt->cl_xprt;
> +
> dprintk("RPC: %5u %s(%s, %u, %u, %d)
",
> task->tk_pid, __FUNCTION__,
> clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
>
> - /* Autobind on cloned rpc clients is discouraged */
> - BUG_ON(clnt->cl_parent != clnt);
> -
> if (xprt_test_and_set_binding(xprt)) {
> status = -EAGAIN; /* tell caller to check again */
> dprintk("RPC: %5u %s: waiting for another binder
",
> @@ -401,9 +423,9 @@ void rpcb_getport_async(struct rpc_task *task)
> task->tk_pid, __FUNCTION__);
> goto bailout;
> }
> - rpc_put_task(child);
>
> - task->tk_xprt->stat.bind_count++;
> + xprt->stat.bind_count++;
> + rpc_put_task(child);

This change of order seems odd, but benign to my reading. I guess as
its this way upstream its ok.

> return;
>
> bailout:

Acked-by: Andy Whitcroft <apw@canonical.com>

-apw

--
kernel-team mailing list
kernel-team@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/kernel-team
 

Thread Tools




All times are GMT. The time now is 09:27 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org