[HARDY 2/2] SRU: Bug:#253004 nfsd: move callback rpc_client creation into separate thread

Manoj Iyer manoj.iyer at canonical.com
Fri May 8 15:17:20 UTC 2009


SRU JUSTIFICATION:

IMPACT: Oops in sunrpc:rpc_shutdown_client
Fix: likely related to: #212485 kernel bug rpc nfs client. Backported
patch to Hardy.
TEST: Test kernel in http://people.ubuntu.com/~manjo/lp253004-hardy/ was
tested by community and reported to work.


The following changes since commit
7758896776e7991a8fe5dc62d83fae68648fdd7d:
   Brad Figg (1):
         UBUNTU: [Hardy SRU][SAUCE]Add information to recognize Toshiba
Satellite Pro M10 Alps Touchpad

are available in the git repository at:

   git://kernel.ubuntu.com/manjo/ubuntu-hardy.git lp253004

J. Bruce Fields (2):
       nfsd: move callback rpc_client creation into separate thread
       nfsd4: probe callback channel only once

  fs/nfsd/nfs4callback.c |   80
++++++++++++++++++++++++-----------------------
  fs/nfsd/nfs4state.c    |    3 +-
  2 files changed, 42 insertions(+), 41 deletions(-)

>From 2147d9683c53aaa9c43263a1d5e6d377a5d01278 Mon Sep 17 00:00:00 2001
From: J. Bruce Fields <bfields at citi.umich.edu>
Date: Thu, 25 Oct 2007 19:00:26 -0400
Subject: [PATCH] nfsd: move callback rpc_client creation into separate thread

Bug: #253004
BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/253004

The whole reason to move this callback-channel probe into a separate
thread was because (for now) we don't have an easy way to create the
rpc_client asynchronously.  But I forgot to move the rpc_create() to the
spawned thread.  Doh!  Fix that.

Signed-off-by: J. Bruce Fields <bfields at citi.umich.edu>
---
  fs/nfsd/nfs4callback.c |   76 ++++++++++++++++++++++++-----------------------
  1 files changed, 39 insertions(+), 37 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 9d536a8..698376b 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -350,30 +350,6 @@ static struct rpc_version *	nfs_cb_version[] = {
  static int do_probe_callback(void *data)
  {
  	struct nfs4_client *clp = data;
-	struct nfs4_callback *cb = &clp->cl_callback;
-	struct rpc_message msg = {
-		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
-		.rpc_argp       = clp,
-	};
-	int status;
-
-	status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT);
-
-	if (status) {
-		rpc_shutdown_client(cb->cb_client);
-		cb->cb_client = NULL;
-	} else
-		atomic_set(&cb->cb_set, 1);
-	put_nfs4_client(clp);
-	return 0;
-}
-
-/*
- * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
- */
-void
-nfsd4_probe_callback(struct nfs4_client *clp)
-{
  	struct sockaddr_in	addr;
  	struct nfs4_callback    *cb = &clp->cl_callback;
  	struct rpc_timeout	timeparms = {
@@ -390,13 +366,18 @@ nfsd4_probe_callback(struct nfs4_client *clp)
  		.timeout	= &timeparms,
  		.program	= program,
  		.version	= nfs_cb_version[1]->number,
-		.authflavor	= RPC_AUTH_UNIX,	/* XXX: need AUTH_GSS... */
+		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
  		.flags		= (RPC_CLNT_CREATE_NOPING),
  	};
-	struct task_struct *t;

  	if (atomic_read(&cb->cb_set))
  		return;
+	struct rpc_message msg = {
+		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
+		.rpc_argp       = clp,
+	};
+	struct rpc_clnt *client;
+	int status;

  	/* Initialize address */
  	memset(&addr, 0, sizeof(addr));
@@ -416,29 +397,50 @@ nfsd4_probe_callback(struct nfs4_client *clp)
  	program->stats->program = program;

  	/* Create RPC client */
-	cb->cb_client = rpc_create(&args);
-	if (IS_ERR(cb->cb_client)) {
+	client = rpc_create(&args);
+	if (IS_ERR(client)) {
  		dprintk("NFSD: couldn't create callback client\n");
+		status = PTR_ERR(client);
  		goto out_err;
  	}

+	status = rpc_call_sync(client, &msg, RPC_TASK_SOFT);
+
+	if (status)
+		goto out_release_client;
+
+	cb->cb_client = client;
+	atomic_set(&cb->cb_set, 1);
+	put_nfs4_client(clp);
+	return 0;
+out_release_client:
+	rpc_shutdown_client(client);
+out_err:
+	put_nfs4_client(clp);
+	dprintk("NFSD: warning: no callback path to client %.*s\n",
+		(int)clp->cl_name.len, clp->cl_name.data);
+	return status;
+}
+
+/*
+ * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+ */
+void
+nfsd4_probe_callback(struct nfs4_client *clp)
+{
+	struct task_struct *t;
+
+	BUG_ON(atomic_read(&clp->cl_callback.cb_set));
+
  	/* the task holds a reference to the nfs4_client struct */
  	atomic_inc(&clp->cl_count);

  	t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe");

  	if (IS_ERR(t))
-		goto out_release_clp;
+		atomic_dec(&clp->cl_count);

  	return;
-
-out_release_clp:
-	atomic_dec(&clp->cl_count);
-	rpc_shutdown_client(cb->cb_client);
-out_err:
-	cb->cb_client = NULL;
-	dprintk("NFSD: warning: no callback path to client %.*s\n",
-		(int)clp->cl_name.len, clp->cl_name.data);
  }

  /*
-- 
1.6.0.4


Cheers
--- manjo




More information about the kernel-team mailing list