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>>
_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to