aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@netapp.com>2011-05-31 19:05:47 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-12 13:40:27 -0400
commit78fe0f41d9937ee62817912ac8d627e06243c269 (patch)
tree7ae4ac3f9675ecbddb5ec0c4615313ae899c10da
parent7e574f0d3911c5cc60d4d2b57fee975c462d6cd0 (diff)
NFS: use scope from exchange_id to skip reclaim
can be skipped if the "eir_server_scope" from the exchange_id proc differs from previous calls. Also, in the future server_scope will be useful for determining whether client trunking is available Signed-off-by: Weston Andros Adamson <dros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/client.c1
-rw-r--r--fs/nfs/nfs4_fs.h3
-rw-r--r--fs/nfs/nfs4proc.c32
-rw-r--r--fs/nfs/nfs4state.c9
-rw-r--r--fs/nfs/nfs4xdr.c8
-rw-r--r--include/linux/nfs_fs_sb.h3
-rw-r--r--include/linux/nfs_xdr.h1
7 files changed, 55 insertions, 2 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index b3dc2b88b65b..006f8ff0a3c0 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -293,6 +293,7 @@ static void nfs_free_client(struct nfs_client *clp)
293 nfs4_deviceid_purge_client(clp); 293 nfs4_deviceid_purge_client(clp);
294 294
295 kfree(clp->cl_hostname); 295 kfree(clp->cl_hostname);
296 kfree(clp->server_scope);
296 kfree(clp); 297 kfree(clp);
297 298
298 dprintk("<-- nfs_free_client()\n"); 299 dprintk("<-- nfs_free_client()\n");
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c4a69833dd0d..b47f0d4710fa 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -48,6 +48,7 @@ enum nfs4_client_state {
48 NFS4CLNT_SESSION_RESET, 48 NFS4CLNT_SESSION_RESET,
49 NFS4CLNT_RECALL_SLOT, 49 NFS4CLNT_RECALL_SLOT,
50 NFS4CLNT_LEASE_CONFIRM, 50 NFS4CLNT_LEASE_CONFIRM,
51 NFS4CLNT_SERVER_SCOPE_MISMATCH,
51}; 52};
52 53
53enum nfs4_session_state { 54enum nfs4_session_state {
@@ -349,6 +350,8 @@ extern void nfs4_schedule_state_manager(struct nfs_client *);
349extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); 350extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
350extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 351extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
351extern void nfs41_handle_recall_slot(struct nfs_client *clp); 352extern void nfs41_handle_recall_slot(struct nfs_client *clp);
353extern void nfs41_handle_server_scope(struct nfs_client *,
354 struct server_scope **);
352extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 355extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
353extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); 356extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
354extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t); 357extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5879b23e0c99..5f4912f72282 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4781,6 +4781,16 @@ out_inval:
4781 return -NFS4ERR_INVAL; 4781 return -NFS4ERR_INVAL;
4782} 4782}
4783 4783
4784static bool
4785nfs41_same_server_scope(struct server_scope *a, struct server_scope *b)
4786{
4787 if (a->server_scope_sz == b->server_scope_sz &&
4788 memcmp(a->server_scope, b->server_scope, a->server_scope_sz) == 0)
4789 return true;
4790
4791 return false;
4792}
4793
4784/* 4794/*
4785 * nfs4_proc_exchange_id() 4795 * nfs4_proc_exchange_id()
4786 * 4796 *
@@ -4823,9 +4833,31 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4823 init_utsname()->domainname, 4833 init_utsname()->domainname,
4824 clp->cl_rpcclient->cl_auth->au_flavor); 4834 clp->cl_rpcclient->cl_auth->au_flavor);
4825 4835
4836 res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL);
4837 if (unlikely(!res.server_scope))
4838 return -ENOMEM;
4839
4826 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); 4840 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
4827 if (!status) 4841 if (!status)
4828 status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); 4842 status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
4843
4844 if (!status) {
4845 if (clp->server_scope &&
4846 !nfs41_same_server_scope(clp->server_scope,
4847 res.server_scope)) {
4848 dprintk("%s: server_scope mismatch detected\n",
4849 __func__);
4850 set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
4851 kfree(clp->server_scope);
4852 clp->server_scope = NULL;
4853 }
4854
4855 if (!clp->server_scope)
4856 clp->server_scope = res.server_scope;
4857 else
4858 kfree(res.server_scope);
4859 }
4860
4829 dprintk("<-- %s status= %d\n", __func__, status); 4861 dprintk("<-- %s status= %d\n", __func__, status);
4830 return status; 4862 return status;
4831} 4863}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e97dd219f84f..5d744a52b4e1 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1643,7 +1643,14 @@ static void nfs4_state_manager(struct nfs_client *clp)
1643 goto out_error; 1643 goto out_error;
1644 } 1644 }
1645 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); 1645 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
1646 set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); 1646
1647 if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH,
1648 &clp->cl_state))
1649 nfs4_state_start_reclaim_nograce(clp);
1650 else
1651 set_bit(NFS4CLNT_RECLAIM_REBOOT,
1652 &clp->cl_state);
1653
1647 pnfs_destroy_all_layouts(clp); 1654 pnfs_destroy_all_layouts(clp);
1648 } 1655 }
1649 1656
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e6e8f3b9a1de..1555c74dd336 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -4977,11 +4977,17 @@ static int decode_exchange_id(struct xdr_stream *xdr,
4977 if (unlikely(status)) 4977 if (unlikely(status))
4978 return status; 4978 return status;
4979 4979
4980 /* Throw away server_scope */ 4980 /* Save server_scope */
4981 status = decode_opaque_inline(xdr, &dummy, &dummy_str); 4981 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
4982 if (unlikely(status)) 4982 if (unlikely(status))
4983 return status; 4983 return status;
4984 4984
4985 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
4986 return -EIO;
4987
4988 memcpy(res->server_scope->server_scope, dummy_str, dummy);
4989 res->server_scope->server_scope_sz = dummy;
4990
4985 /* Throw away Implementation id array */ 4991 /* Throw away Implementation id array */
4986 status = decode_opaque_inline(xdr, &dummy, &dummy_str); 4992 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
4987 if (unlikely(status)) 4993 if (unlikely(status))
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 87694ca86914..f23b18831559 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -16,6 +16,7 @@ struct nfs4_sequence_args;
16struct nfs4_sequence_res; 16struct nfs4_sequence_res;
17struct nfs_server; 17struct nfs_server;
18struct nfs4_minor_version_ops; 18struct nfs4_minor_version_ops;
19struct server_scope;
19 20
20/* 21/*
21 * The nfs_client identifies our client state to the server. 22 * The nfs_client identifies our client state to the server.
@@ -83,6 +84,8 @@ struct nfs_client {
83#ifdef CONFIG_NFS_FSCACHE 84#ifdef CONFIG_NFS_FSCACHE
84 struct fscache_cookie *fscache; /* client index cache cookie */ 85 struct fscache_cookie *fscache; /* client index cache cookie */
85#endif 86#endif
87
88 struct server_scope *server_scope; /* from exchange_id */
86}; 89};
87 90
88/* 91/*
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 00848d86ffb2..c4d98df884f3 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1060,6 +1060,7 @@ struct server_scope {
1060struct nfs41_exchange_id_res { 1060struct nfs41_exchange_id_res {
1061 struct nfs_client *client; 1061 struct nfs_client *client;
1062 u32 flags; 1062 u32 flags;
1063 struct server_scope *server_scope;
1063}; 1064};
1064 1065
1065struct nfs41_create_session_args { 1066struct nfs41_create_session_args {