diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-25 17:18:09 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-26 14:17:30 -0400 |
commit | 662455391040a783b89d0232e743c27c23617dbd (patch) | |
tree | aa1819778ac5005932edcbd844c54e6cab0dc4e5 /fs/nfs | |
parent | 2cf047c994c8a62f65e520342d0287fca8807a53 (diff) |
NFSv4.1: Add DESTROY_CLIENTID
Ensure that we destroy our lease on last unmount
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 59 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 52 |
4 files changed, 113 insertions, 0 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a50bdfbbc429..7d108753af81 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -209,6 +209,7 @@ static void nfs4_shutdown_session(struct nfs_client *clp) | |||
209 | if (nfs4_has_session(clp)) { | 209 | if (nfs4_has_session(clp)) { |
210 | nfs4_deviceid_purge_client(clp); | 210 | nfs4_deviceid_purge_client(clp); |
211 | nfs4_destroy_session(clp->cl_session); | 211 | nfs4_destroy_session(clp->cl_session); |
212 | nfs4_destroy_clientid(clp); | ||
212 | } | 213 | } |
213 | 214 | ||
214 | } | 215 | } |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index f7307304320a..b20b5164f70a 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -214,6 +214,7 @@ extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setcli | |||
214 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 214 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
215 | extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, struct rpc_cred *cred); | 215 | extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, struct rpc_cred *cred); |
216 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); | 216 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); |
217 | extern int nfs4_destroy_clientid(struct nfs_client *clp); | ||
217 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); | 218 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); |
218 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); | 219 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); |
219 | extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); | 220 | extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3fdff0cd558d..485a6c0cdc40 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -5261,6 +5261,65 @@ out: | |||
5261 | return status; | 5261 | return status; |
5262 | } | 5262 | } |
5263 | 5263 | ||
5264 | static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, | ||
5265 | struct rpc_cred *cred) | ||
5266 | { | ||
5267 | struct rpc_message msg = { | ||
5268 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_CLIENTID], | ||
5269 | .rpc_argp = clp, | ||
5270 | .rpc_cred = cred, | ||
5271 | }; | ||
5272 | int status; | ||
5273 | |||
5274 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | ||
5275 | if (status) | ||
5276 | pr_warn("NFS: Got error %d from the server %s on " | ||
5277 | "DESTROY_CLIENTID.", status, clp->cl_hostname); | ||
5278 | return status; | ||
5279 | } | ||
5280 | |||
5281 | static int nfs4_proc_destroy_clientid(struct nfs_client *clp, | ||
5282 | struct rpc_cred *cred) | ||
5283 | { | ||
5284 | unsigned int loop; | ||
5285 | int ret; | ||
5286 | |||
5287 | for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { | ||
5288 | ret = _nfs4_proc_destroy_clientid(clp, cred); | ||
5289 | switch (ret) { | ||
5290 | case -NFS4ERR_DELAY: | ||
5291 | case -NFS4ERR_CLIENTID_BUSY: | ||
5292 | ssleep(1); | ||
5293 | break; | ||
5294 | default: | ||
5295 | return ret; | ||
5296 | } | ||
5297 | } | ||
5298 | return 0; | ||
5299 | } | ||
5300 | |||
5301 | int nfs4_destroy_clientid(struct nfs_client *clp) | ||
5302 | { | ||
5303 | struct rpc_cred *cred; | ||
5304 | int ret = 0; | ||
5305 | |||
5306 | if (clp->cl_mvops->minor_version < 1) | ||
5307 | goto out; | ||
5308 | if (clp->cl_exchange_flags == 0) | ||
5309 | goto out; | ||
5310 | cred = nfs4_get_exchange_id_cred(clp); | ||
5311 | ret = nfs4_proc_destroy_clientid(clp, cred); | ||
5312 | if (cred) | ||
5313 | put_rpccred(cred); | ||
5314 | switch (ret) { | ||
5315 | case 0: | ||
5316 | case -NFS4ERR_STALE_CLIENTID: | ||
5317 | clp->cl_exchange_flags = 0; | ||
5318 | } | ||
5319 | out: | ||
5320 | return ret; | ||
5321 | } | ||
5322 | |||
5264 | struct nfs4_get_lease_time_data { | 5323 | struct nfs4_get_lease_time_data { |
5265 | struct nfs4_get_lease_time_args *args; | 5324 | struct nfs4_get_lease_time_args *args; |
5266 | struct nfs4_get_lease_time_res *res; | 5325 | struct nfs4_get_lease_time_res *res; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 1d4d259c5b3c..b9ce3fdb862a 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -338,6 +338,8 @@ static int nfs4_stat_to_errno(int); | |||
338 | 1 /* bctsr_use_conn_in_rdma_mode */) | 338 | 1 /* bctsr_use_conn_in_rdma_mode */) |
339 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) | 339 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) |
340 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) | 340 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) |
341 | #define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2) | ||
342 | #define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz) | ||
341 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ | 343 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ |
342 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) | 344 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4) |
343 | #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ | 345 | #define decode_sequence_maxsz (op_decode_hdr_maxsz + \ |
@@ -751,6 +753,10 @@ static int nfs4_stat_to_errno(int); | |||
751 | encode_destroy_session_maxsz) | 753 | encode_destroy_session_maxsz) |
752 | #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ | 754 | #define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \ |
753 | decode_destroy_session_maxsz) | 755 | decode_destroy_session_maxsz) |
756 | #define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \ | ||
757 | encode_destroy_clientid_maxsz) | ||
758 | #define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \ | ||
759 | decode_destroy_clientid_maxsz) | ||
754 | #define NFS4_enc_sequence_sz \ | 760 | #define NFS4_enc_sequence_sz \ |
755 | (compound_decode_hdr_maxsz + \ | 761 | (compound_decode_hdr_maxsz + \ |
756 | encode_sequence_maxsz) | 762 | encode_sequence_maxsz) |
@@ -1804,6 +1810,14 @@ static void encode_destroy_session(struct xdr_stream *xdr, | |||
1804 | encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | 1810 | encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
1805 | } | 1811 | } |
1806 | 1812 | ||
1813 | static void encode_destroy_clientid(struct xdr_stream *xdr, | ||
1814 | uint64_t clientid, | ||
1815 | struct compound_hdr *hdr) | ||
1816 | { | ||
1817 | encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr); | ||
1818 | encode_uint64(xdr, clientid); | ||
1819 | } | ||
1820 | |||
1807 | static void encode_reclaim_complete(struct xdr_stream *xdr, | 1821 | static void encode_reclaim_complete(struct xdr_stream *xdr, |
1808 | struct nfs41_reclaim_complete_args *args, | 1822 | struct nfs41_reclaim_complete_args *args, |
1809 | struct compound_hdr *hdr) | 1823 | struct compound_hdr *hdr) |
@@ -2724,6 +2738,22 @@ static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, | |||
2724 | } | 2738 | } |
2725 | 2739 | ||
2726 | /* | 2740 | /* |
2741 | * a DESTROY_CLIENTID request | ||
2742 | */ | ||
2743 | static void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req, | ||
2744 | struct xdr_stream *xdr, | ||
2745 | struct nfs_client *clp) | ||
2746 | { | ||
2747 | struct compound_hdr hdr = { | ||
2748 | .minorversion = clp->cl_mvops->minor_version, | ||
2749 | }; | ||
2750 | |||
2751 | encode_compound_hdr(xdr, req, &hdr); | ||
2752 | encode_destroy_clientid(xdr, clp->cl_clientid, &hdr); | ||
2753 | encode_nops(&hdr); | ||
2754 | } | ||
2755 | |||
2756 | /* | ||
2727 | * a SEQUENCE request | 2757 | * a SEQUENCE request |
2728 | */ | 2758 | */ |
2729 | static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, | 2759 | static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr, |
@@ -5479,6 +5509,11 @@ static int decode_destroy_session(struct xdr_stream *xdr, void *dummy) | |||
5479 | return decode_op_hdr(xdr, OP_DESTROY_SESSION); | 5509 | return decode_op_hdr(xdr, OP_DESTROY_SESSION); |
5480 | } | 5510 | } |
5481 | 5511 | ||
5512 | static int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy) | ||
5513 | { | ||
5514 | return decode_op_hdr(xdr, OP_DESTROY_CLIENTID); | ||
5515 | } | ||
5516 | |||
5482 | static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) | 5517 | static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy) |
5483 | { | 5518 | { |
5484 | return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); | 5519 | return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE); |
@@ -6789,6 +6824,22 @@ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, | |||
6789 | } | 6824 | } |
6790 | 6825 | ||
6791 | /* | 6826 | /* |
6827 | * Decode DESTROY_CLIENTID response | ||
6828 | */ | ||
6829 | static int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp, | ||
6830 | struct xdr_stream *xdr, | ||
6831 | void *res) | ||
6832 | { | ||
6833 | struct compound_hdr hdr; | ||
6834 | int status; | ||
6835 | |||
6836 | status = decode_compound_hdr(xdr, &hdr); | ||
6837 | if (!status) | ||
6838 | status = decode_destroy_clientid(xdr, res); | ||
6839 | return status; | ||
6840 | } | ||
6841 | |||
6842 | /* | ||
6792 | * Decode SEQUENCE response | 6843 | * Decode SEQUENCE response |
6793 | */ | 6844 | */ |
6794 | static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, | 6845 | static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, |
@@ -7237,6 +7288,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
7237 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), | 7288 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), |
7238 | PROC(BIND_CONN_TO_SESSION, | 7289 | PROC(BIND_CONN_TO_SESSION, |
7239 | enc_bind_conn_to_session, dec_bind_conn_to_session), | 7290 | enc_bind_conn_to_session, dec_bind_conn_to_session), |
7291 | PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid), | ||
7240 | #endif /* CONFIG_NFS_V4_1 */ | 7292 | #endif /* CONFIG_NFS_V4_1 */ |
7241 | }; | 7293 | }; |
7242 | 7294 | ||