SOURCES: linux-2.6.22-NFS_ALL.dif (NEW), linux-2.6.22-rc5-CITI_NFS...

baggins baggins at pld-linux.org
Mon Aug 13 19:18:34 CEST 2007


Author: baggins                      Date: Mon Aug 13 17:18:34 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- NFS fixes and improvements

---- Files affected:
SOURCES:
   linux-2.6.22-NFS_ALL.dif (NONE -> 1.1)  (NEW), linux-2.6.22-rc5-CITI_NFS4_ALL-1.diff (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.6.22-NFS_ALL.dif
diff -u /dev/null SOURCES/linux-2.6.22-NFS_ALL.dif:1.1
--- /dev/null	Mon Aug 13 19:18:34 2007
+++ SOURCES/linux-2.6.22-NFS_ALL.dif	Mon Aug 13 19:18:29 2007
@@ -0,0 +1,9738 @@
+All of the above
+---
+ fs/lockd/host.c                      |   39 +
+ fs/lockd/mon.c                       |    2 
+ fs/lockd/svc.c                       |    6 
+ fs/nfs/Makefile                      |    4 
+ fs/nfs/client.c                      |   28 -
+ fs/nfs/delegation.c                  |  186 +++--
+ fs/nfs/delegation.h                  |   26 -
+ fs/nfs/dir.c                         |   16 
+ fs/nfs/direct.c                      |   34 +
+ fs/nfs/inode.c                       |   73 +-
+ fs/nfs/internal.h                    |    4 
+ fs/nfs/mount_clnt.c                  |  169 +++--
+ fs/nfs/nfs2xdr.c                     |    6 
+ fs/nfs/nfs3proc.c                    |    4 
+ fs/nfs/nfs3xdr.c                     |    8 
+ fs/nfs/nfs4_fs.h                     |   40 +
+ fs/nfs/nfs4proc.c                    |  760 +++++++++++++---------
+ fs/nfs/nfs4state.c                   |  310 ++++++---
+ fs/nfs/nfs4xdr.c                     |  126 ++--
+ fs/nfs/nfsroot.c                     |    5 
+ fs/nfs/pagelist.c                    |   60 +-
+ fs/nfs/read.c                        |   40 +
+ fs/nfs/super.c                       | 1189 +++++++++++++++++++++++++++++-----
+ fs/nfs/write.c                       |  149 ++--
+ fs/nfsd/nfs4callback.c               |   18 -
+ fs/nfsd/nfs4state.c                  |    1 
+ include/linux/lockd/lockd.h          |    1 
+ include/linux/nfs4.h                 |    1 
+ include/linux/nfs4_mount.h           |    3 
+ include/linux/nfs_fs.h               |   28 -
+ include/linux/nfs_fs_sb.h            |    8 
+ include/linux/nfs_mount.h            |    3 
+ include/linux/nfs_page.h             |   25 -
+ include/linux/nfs_xdr.h              |    5 
+ include/linux/sunrpc/auth.h          |   48 +
+ include/linux/sunrpc/auth_gss.h      |    6 
+ include/linux/sunrpc/clnt.h          |   33 -
+ include/linux/sunrpc/gss_api.h       |    2 
+ include/linux/sunrpc/rpc_pipe_fs.h   |    2 
+ include/linux/sunrpc/sched.h         |    6 
+ include/linux/sunrpc/svcsock.h       |    1 
+ include/linux/sunrpc/xprt.h          |   16 
+ kernel/auditsc.c                     |    1 
+ net/sunrpc/auth.c                    |  357 +++++++---
+ net/sunrpc/auth_gss/auth_gss.c       |  339 ++++++----
+ net/sunrpc/auth_gss/gss_krb5_mech.c  |    2 
+ net/sunrpc/auth_gss/gss_spkm3_mech.c |    2 
+ net/sunrpc/auth_null.c               |   10 
+ net/sunrpc/auth_unix.c               |   54 +-
+ net/sunrpc/clnt.c                    |  367 +++++++---
+ net/sunrpc/rpc_pipe.c                |   87 ++
+ net/sunrpc/rpcb_clnt.c               |   65 +-
+ net/sunrpc/sched.c                   |  209 ++----
+ net/sunrpc/sunrpc_syms.c             |    8 
+ net/sunrpc/svcsock.c                 |   20 +
+ net/sunrpc/xprt.c                    |   19 -
+ net/sunrpc/xprtsock.c                |   81 +-
+ 57 files changed, 3305 insertions(+), 1807 deletions(-)
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index 96070bf..572601e 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -44,9 +44,8 @@ static struct nsm_handle *	nsm_find(const struct sockaddr_in *sin,
+  */
+ static struct nlm_host *
+ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+-					int proto, int version,
+-					const char *hostname,
+-					int hostname_len)
++		int proto, int version, const char *hostname,
++		int hostname_len, const struct sockaddr_in *ssin)
+ {
+ 	struct hlist_head *chain;
+ 	struct hlist_node *pos;
+@@ -54,7 +53,9 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ 	struct nsm_handle *nsm = NULL;
+ 	int		hash;
+ 
+-	dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n",
++	dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
++			", p=%d, v=%d, my role=%s, name=%.*s)\n",
++			NIPQUAD(ssin->sin_addr.s_addr),
+ 			NIPQUAD(sin->sin_addr.s_addr), proto, version,
+ 			server? "server" : "client",
+ 			hostname_len,
+@@ -91,6 +92,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ 			continue;
+ 		if (host->h_server != server)
+ 			continue;
++		if (!nlm_cmp_addr(&host->h_saddr, ssin))
++			continue;
+ 
+ 		/* Move to head of hash chain. */
+ 		hlist_del(&host->h_hash);
+@@ -118,6 +121,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ 	host->h_name	   = nsm->sm_name;
+ 	host->h_addr       = *sin;
+ 	host->h_addr.sin_port = 0;	/* ouch! */
++	host->h_saddr	   = *ssin;
+ 	host->h_version    = version;
+ 	host->h_proto      = proto;
+ 	host->h_rpcclnt    = NULL;
+@@ -161,15 +165,9 @@ nlm_destroy_host(struct nlm_host *host)
+ 	 */
+ 	nsm_unmonitor(host);
+ 
+-	if ((clnt = host->h_rpcclnt) != NULL) {
+-		if (atomic_read(&clnt->cl_users)) {
+-			printk(KERN_WARNING
+-				"lockd: active RPC handle\n");
+-			clnt->cl_dead = 1;
+-		} else {
+-			rpc_destroy_client(host->h_rpcclnt);
+-		}
+-	}
++	clnt = host->h_rpcclnt;
++	if (clnt != NULL)
++		rpc_shutdown_client(clnt);
+ 	kfree(host);
+ }
+ 
+@@ -180,8 +178,10 @@ struct nlm_host *
+ nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
+ 			const char *hostname, int hostname_len)
+ {
++	struct sockaddr_in ssin = {0};
++
+ 	return nlm_lookup_host(0, sin, proto, version,
+-			       hostname, hostname_len);
++			       hostname, hostname_len, &ssin);
+ }
+ 
+ /*
+@@ -191,9 +191,12 @@ struct nlm_host *
+ nlmsvc_lookup_host(struct svc_rqst *rqstp,
+ 			const char *hostname, int hostname_len)
+ {
++	struct sockaddr_in ssin = {0};
++
++	ssin.sin_addr = rqstp->rq_daddr.addr;
+ 	return nlm_lookup_host(1, svc_addr_in(rqstp),
+ 			       rqstp->rq_prot, rqstp->rq_vers,
+-			       hostname, hostname_len);
++			       hostname, hostname_len, &ssin);
+ }
+ 
+ /*
+@@ -204,8 +207,9 @@ nlm_bind_host(struct nlm_host *host)
+ {
+ 	struct rpc_clnt	*clnt;
+ 
+-	dprintk("lockd: nlm_bind_host(%08x)\n",
+-			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
++	dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n",
++			NIPQUAD(host->h_saddr.sin_addr),
++			NIPQUAD(host->h_addr.sin_addr));
+ 
+ 	/* Lock host handle */
+ 	mutex_lock(&host->h_mutex);
+@@ -232,6 +236,7 @@ nlm_bind_host(struct nlm_host *host)
+ 			.protocol	= host->h_proto,
+ 			.address	= (struct sockaddr *)&host->h_addr,
+ 			.addrsize	= sizeof(host->h_addr),
++			.saddress	= (struct sockaddr *)&host->h_saddr,
+ 			.timeout	= &timeparms,
+ 			.servername	= host->h_name,
+ 			.program	= &nlm_program,
+diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
+index 2102e2d..3353ed8 100644
+--- a/fs/lockd/mon.c
++++ b/fs/lockd/mon.c
+@@ -61,6 +61,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
+ 			status);
+ 	else
+ 		status = 0;
++	rpc_shutdown_client(clnt);
+  out:
+ 	return status;
+ }
+@@ -138,7 +139,6 @@ nsm_create(void)
+ 		.program	= &nsm_program,
+ 		.version	= SM_VERSION,
+ 		.authflavor	= RPC_AUTH_NULL,
+-		.flags		= (RPC_CLNT_CREATE_ONESHOT),
+ 	};
+ 
+ 	return rpc_create(&args);
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index 126b1bf..2680932 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -123,9 +123,6 @@ lockd(struct svc_rqst *rqstp)
+ 	/* Process request with signals blocked, but allow SIGKILL.  */
+ 	allow_signal(SIGKILL);
+ 
+-	/* kick rpciod */
+-	rpciod_up();
+-
+ 	dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
+ 
+ 	if (!nlm_timeout)
+@@ -202,9 +199,6 @@ lockd(struct svc_rqst *rqstp)
+ 	/* Exit the RPC thread */
+ 	svc_exit_thread(rqstp);
+ 
+-	/* release rpciod */
+-	rpciod_down();
+-
+ 	/* Release module */
+ 	unlock_kernel();
+ 	module_put_and_exit(0);
+diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
+index f4580b4..b55cb23 100644
+--- a/fs/nfs/Makefile
++++ b/fs/nfs/Makefile
+@@ -6,8 +6,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o
+ 
+ nfs-y 			:= client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
+ 			   pagelist.o proc.o read.o symlink.o unlink.o \
+-			   write.o namespace.o
+-nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o mount_clnt.o      
++			   write.o namespace.o mount_clnt.o
++nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o
+ nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
+ nfs-$(CONFIG_NFS_V3_ACL)	+= nfs3acl.o
+ nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index 881fa49..ccb4550 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -102,19 +102,10 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
+ 					   int nfsversion)
+ {
+ 	struct nfs_client *clp;
+-	int error;
+ 
+ 	if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
+ 		goto error_0;
+ 
+-	error = rpciod_up();
+-	if (error < 0) {
+-		dprintk("%s: couldn't start rpciod! Error = %d\n",
+-				__FUNCTION__, error);
+-		goto error_1;
+-	}
+-	__set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
+-
+ 	if (nfsversion == 4) {
+ 		if (nfs_callback_up() < 0)
+ 			goto error_2;
+@@ -139,8 +130,6 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
+ #ifdef CONFIG_NFS_V4
+ 	init_rwsem(&clp->cl_sem);
+ 	INIT_LIST_HEAD(&clp->cl_delegations);
+-	INIT_LIST_HEAD(&clp->cl_state_owners);
+-	INIT_LIST_HEAD(&clp->cl_unused);
+ 	spin_lock_init(&clp->cl_lock);
+ 	INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
+ 	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+@@ -154,9 +143,6 @@ error_3:
+ 	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ 		nfs_callback_down();
+ error_2:
+-	rpciod_down();
+-	__clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
+-error_1:
+ 	kfree(clp);
+ error_0:
+ 	return NULL;
+@@ -167,16 +153,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
+ #ifdef CONFIG_NFS_V4
+ 	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+ 		nfs4_kill_renewd(clp);
+-	while (!list_empty(&clp->cl_unused)) {
+-		struct nfs4_state_owner *sp;
+-
+-		sp = list_entry(clp->cl_unused.next,
+-				struct nfs4_state_owner,
+-				so_list);
+-		list_del(&sp->so_list);
+-		kfree(sp);
+-	}
+-	BUG_ON(!list_empty(&clp->cl_state_owners));
++	BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
+ 	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ 		nfs_idmap_delete(clp);
+ #endif
+@@ -198,9 +175,6 @@ static void nfs_free_client(struct nfs_client *clp)
+ 	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ 		nfs_callback_down();
+ 
+-	if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
+-		rpciod_down();
+-
+ 	kfree(clp->cl_hostname);
+ 	kfree(clp);
+ 
+diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
+index 7f37d1b..20ac403 100644
+--- a/fs/nfs/delegation.c
++++ b/fs/nfs/delegation.c
+@@ -27,6 +27,13 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
+ 	kfree(delegation);
+ }
+ 
++static void nfs_free_delegation_callback(struct rcu_head *head)
++{
++	struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
++
++	nfs_free_delegation(delegation);
++}
++
+ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
+ {
+ 	struct inode *inode = state->inode;
+@@ -57,7 +64,7 @@ out_err:
+ 	return status;
+ }
+ 
+-static void nfs_delegation_claim_opens(struct inode *inode)
++static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
+ {
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+ 	struct nfs_open_context *ctx;
+@@ -72,9 +79,11 @@ again:
+ 			continue;
+ 		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+ 			continue;
++		if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
++			continue;
+ 		get_nfs_open_context(ctx);
+ 		spin_unlock(&inode->i_lock);
+-		err = nfs4_open_delegation_recall(ctx->dentry, state);
++		err = nfs4_open_delegation_recall(ctx, state, stateid);
+ 		if (err >= 0)
+ 			err = nfs_delegation_claim_locks(ctx, state);
+ 		put_nfs_open_context(ctx);
+@@ -115,10 +124,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
+ 	struct nfs_delegation *delegation;
+ 	int status = 0;
+ 
+-	/* Ensure we first revalidate the attributes and page cache! */
+-	if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)))
+-		__nfs_revalidate_inode(NFS_SERVER(inode), inode);
+-
+ 	delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
+ 	if (delegation == NULL)
+ 		return -ENOMEM;
+@@ -131,10 +136,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
+ 	delegation->inode = inode;
+ 
+ 	spin_lock(&clp->cl_lock);
+-	if (nfsi->delegation == NULL) {
+-		list_add(&delegation->super_list, &clp->cl_delegations);
+-		nfsi->delegation = delegation;
++	if (rcu_dereference(nfsi->delegation) == NULL) {
++		list_add_rcu(&delegation->super_list, &clp->cl_delegations);
+ 		nfsi->delegation_state = delegation->type;
++		rcu_assign_pointer(nfsi->delegation, delegation);
+ 		delegation = NULL;
+ 	} else {
+ 		if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
+@@ -145,6 +150,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
+ 			status = -EIO;
+ 		}
+ 	}
++
++	/* Ensure we revalidate the attributes and page cache! */
++	spin_lock(&inode->i_lock);
++	nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
++	spin_unlock(&inode->i_lock);
++
+ 	spin_unlock(&clp->cl_lock);
+ 	kfree(delegation);
+ 	return status;
+@@ -155,7 +166,7 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
+ 	int res = 0;
+ 
+ 	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
+-	nfs_free_delegation(delegation);
++	call_rcu(&delegation->rcu, nfs_free_delegation_callback);
+ 	return res;
+ }
+ 
+@@ -170,33 +181,55 @@ static void nfs_msync_inode(struct inode *inode)
+ /*
+  * Basic procedure for returning a delegation to the server
+  */
+-int __nfs_inode_return_delegation(struct inode *inode)
++static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+ {
+ 	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+-	struct nfs_delegation *delegation;
+-	int res = 0;
+ 
+ 	nfs_msync_inode(inode);
+ 	down_read(&clp->cl_sem);
+ 	/* Guard against new delegated open calls */
+ 	down_write(&nfsi->rwsem);
+-	spin_lock(&clp->cl_lock);
+-	delegation = nfsi->delegation;
+-	if (delegation != NULL) {
+-		list_del_init(&delegation->super_list);
+-		nfsi->delegation = NULL;
+-		nfsi->delegation_state = 0;
+-	}
+-	spin_unlock(&clp->cl_lock);
+-	nfs_delegation_claim_opens(inode);
++	nfs_delegation_claim_opens(inode, &delegation->stateid);
+ 	up_write(&nfsi->rwsem);
+ 	up_read(&clp->cl_sem);
+ 	nfs_msync_inode(inode);
+ 
+-	if (delegation != NULL)
+-		res = nfs_do_return_delegation(inode, delegation);
+-	return res;
++	return nfs_do_return_delegation(inode, delegation);
++}
++
++static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
++{
++	struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
++
++	if (delegation == NULL)
++		goto nomatch;
++	if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
++				sizeof(delegation->stateid.data)) != 0)
++		goto nomatch;
++	list_del_rcu(&delegation->super_list);
++	nfsi->delegation_state = 0;
++	rcu_assign_pointer(nfsi->delegation, NULL);
++	return delegation;
++nomatch:
++	return NULL;
++}
++
++int nfs_inode_return_delegation(struct inode *inode)
++{
++	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
++	struct nfs_inode *nfsi = NFS_I(inode);
++	struct nfs_delegation *delegation;
++	int err = 0;
++
++	if (rcu_dereference(nfsi->delegation) != NULL) {
++		spin_lock(&clp->cl_lock);
++		delegation = nfs_detach_delegation_locked(nfsi, NULL);
++		spin_unlock(&clp->cl_lock);
++		if (delegation != NULL)
++			err = __nfs_inode_return_delegation(inode, delegation);
++	}
++	return err;
+ }
+ 
+ /*
+@@ -211,19 +244,23 @@ void nfs_return_all_delegations(struct super_block *sb)
+ 	if (clp == NULL)
+ 		return;
+ restart:
+-	spin_lock(&clp->cl_lock);
+-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
++	rcu_read_lock();
++	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
+ 		if (delegation->inode->i_sb != sb)
+ 			continue;
+ 		inode = igrab(delegation->inode);
+ 		if (inode == NULL)
+ 			continue;
++		spin_lock(&clp->cl_lock);
++		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
+ 		spin_unlock(&clp->cl_lock);
+-		nfs_inode_return_delegation(inode);
++		rcu_read_unlock();
++		if (delegation != NULL)
++			__nfs_inode_return_delegation(inode, delegation);
+ 		iput(inode);
+ 		goto restart;
+ 	}
+-	spin_unlock(&clp->cl_lock);
++	rcu_read_unlock();
+ }
+ 
+ static int nfs_do_expire_all_delegations(void *ptr)
+@@ -234,22 +271,26 @@ static int nfs_do_expire_all_delegations(void *ptr)
+ 
+ 	allow_signal(SIGKILL);
+ restart:
+-	spin_lock(&clp->cl_lock);
+ 	if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
+ 		goto out;
+ 	if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
+ 		goto out;
+-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
++	rcu_read_lock();
++	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
+ 		inode = igrab(delegation->inode);
+ 		if (inode == NULL)
+ 			continue;
++		spin_lock(&clp->cl_lock);
++		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
+ 		spin_unlock(&clp->cl_lock);
+-		nfs_inode_return_delegation(inode);
++		rcu_read_unlock();
++		if (delegation)
++			__nfs_inode_return_delegation(inode, delegation);
+ 		iput(inode);
+ 		goto restart;
+ 	}
++	rcu_read_unlock();
+ out:
+-	spin_unlock(&clp->cl_lock);
+ 	nfs_put_client(clp);
+ 	module_put_and_exit(0);
+ }
+@@ -280,17 +321,21 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp)
+ 	if (clp == NULL)
+ 		return;
+ restart:
+-	spin_lock(&clp->cl_lock);
+-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
++	rcu_read_lock();
++	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
+ 		inode = igrab(delegation->inode);
+ 		if (inode == NULL)
+ 			continue;
++		spin_lock(&clp->cl_lock);
++		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
+ 		spin_unlock(&clp->cl_lock);
+-		nfs_inode_return_delegation(inode);
++		rcu_read_unlock();
++		if (delegation != NULL)
++			__nfs_inode_return_delegation(inode, delegation);
+ 		iput(inode);
+ 		goto restart;
+ 	}
+-	spin_unlock(&clp->cl_lock);
++	rcu_read_unlock();
+ }
+ 
+ struct recall_threadargs {
+@@ -316,21 +361,14 @@ static int recall_thread(void *data)
+ 	down_read(&clp->cl_sem);
+ 	down_write(&nfsi->rwsem);
+ 	spin_lock(&clp->cl_lock);
+-	delegation = nfsi->delegation;
+-	if (delegation != NULL && memcmp(delegation->stateid.data,
+-				args->stateid->data,
+-				sizeof(delegation->stateid.data)) == 0) {
+-		list_del_init(&delegation->super_list);
+-		nfsi->delegation = NULL;
+-		nfsi->delegation_state = 0;
++	delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
++	if (delegation != NULL)
+ 		args->result = 0;
+-	} else {
+-		delegation = NULL;
++	else
+ 		args->result = -ENOENT;
+-	}
+ 	spin_unlock(&clp->cl_lock);
+ 	complete(&args->started);
+-	nfs_delegation_claim_opens(inode);
++	nfs_delegation_claim_opens(inode, args->stateid);
+ 	up_write(&nfsi->rwsem);
+ 	up_read(&clp->cl_sem);
+ 	nfs_msync_inode(inode);
+@@ -371,14 +409,14 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
+ {
+ 	struct nfs_delegation *delegation;
+ 	struct inode *res = NULL;
+-	spin_lock(&clp->cl_lock);
+-	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
++	rcu_read_lock();
++	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
+ 		if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
+ 			res = igrab(delegation->inode);
+ 			break;
+ 		}
+ 	}
+-	spin_unlock(&clp->cl_lock);
++	rcu_read_unlock();
+ 	return res;
+ }
+ 
+@@ -388,10 +426,10 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
+ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
+ {
+ 	struct nfs_delegation *delegation;
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list