diff options
author | Weston Andros Adamson <dros@netapp.com> | 2011-05-31 19:05:47 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-12 13:40:27 -0400 |
commit | 78fe0f41d9937ee62817912ac8d627e06243c269 (patch) | |
tree | 7ae4ac3f9675ecbddb5ec0c4615313ae899c10da | |
parent | 7e574f0d3911c5cc60d4d2b57fee975c462d6cd0 (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.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 32 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 9 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 8 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 3 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
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 | ||
53 | enum nfs4_session_state { | 54 | enum nfs4_session_state { |
@@ -349,6 +350,8 @@ extern void nfs4_schedule_state_manager(struct nfs_client *); | |||
349 | extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); | 350 | extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); |
350 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); | 351 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); |
351 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); | 352 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); |
353 | extern void nfs41_handle_server_scope(struct nfs_client *, | ||
354 | struct server_scope **); | ||
352 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 355 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
353 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 356 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
354 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t); | 357 | extern 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 | ||
4784 | static bool | ||
4785 | nfs41_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; | |||
16 | struct nfs4_sequence_res; | 16 | struct nfs4_sequence_res; |
17 | struct nfs_server; | 17 | struct nfs_server; |
18 | struct nfs4_minor_version_ops; | 18 | struct nfs4_minor_version_ops; |
19 | struct 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 { | |||
1060 | struct nfs41_exchange_id_res { | 1060 | struct 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 | ||
1065 | struct nfs41_create_session_args { | 1066 | struct nfs41_create_session_args { |