diff options
author | Weston Andros Adamson <dros@netapp.com> | 2012-05-24 13:22:50 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-24 16:22:19 -0400 |
commit | 7c44f1ae4a21458a1ea3d6482ffb3136f1df6d2b (patch) | |
tree | a66f9b3fb7a5252a87dbcee40562a1e8ed47dc9b /fs/nfs | |
parent | d23d61c8d351f5ced44ce87caf1fa3baab4c3f89 (diff) |
nfs4.1: add BIND_CONN_TO_SESSION operation
This patch adds the BIND_CONN_TO_SESSION operation which is needed for
upcoming SP4_MACH_CRED work and useful for recovering from broken connections
without destroying the session.
Signed-off-by: Weston Andros Adamson <dros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 54 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 95 |
3 files changed, 150 insertions, 0 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index e6da02124c4e..2c7f1cf85b8f 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -211,6 +211,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *, | |||
211 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); | 211 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); |
212 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); | 212 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); |
213 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 213 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
214 | extern int nfs4_proc_bind_conn_to_session(struct nfs_client *); | ||
214 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); | 215 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); |
215 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); | 216 | extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); |
216 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); | 217 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e725736ff288..e8988c000e7f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -5100,6 +5100,60 @@ nfs41_same_server_scope(struct nfs41_server_scope *a, | |||
5100 | } | 5100 | } |
5101 | 5101 | ||
5102 | /* | 5102 | /* |
5103 | * nfs4_proc_bind_conn_to_session() | ||
5104 | * | ||
5105 | * The 4.1 client currently uses the same TCP connection for the | ||
5106 | * fore and backchannel. | ||
5107 | */ | ||
5108 | int nfs4_proc_bind_conn_to_session(struct nfs_client *clp) | ||
5109 | { | ||
5110 | int status; | ||
5111 | struct nfs41_bind_conn_to_session_res res; | ||
5112 | struct rpc_message msg = { | ||
5113 | .rpc_proc = | ||
5114 | &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION], | ||
5115 | .rpc_argp = clp, | ||
5116 | .rpc_resp = &res, | ||
5117 | }; | ||
5118 | |||
5119 | dprintk("--> %s\n", __func__); | ||
5120 | BUG_ON(clp == NULL); | ||
5121 | |||
5122 | res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | ||
5123 | if (unlikely(res.session == NULL)) { | ||
5124 | status = -ENOMEM; | ||
5125 | goto out; | ||
5126 | } | ||
5127 | |||
5128 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | ||
5129 | if (status == 0) { | ||
5130 | if (memcmp(res.session->sess_id.data, | ||
5131 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { | ||
5132 | dprintk("NFS: %s: Session ID mismatch\n", __func__); | ||
5133 | status = -EIO; | ||
5134 | goto out_session; | ||
5135 | } | ||
5136 | if (res.dir != NFS4_CDFS4_BOTH) { | ||
5137 | dprintk("NFS: %s: Unexpected direction from server\n", | ||
5138 | __func__); | ||
5139 | status = -EIO; | ||
5140 | goto out_session; | ||
5141 | } | ||
5142 | if (res.use_conn_in_rdma_mode) { | ||
5143 | dprintk("NFS: %s: Server returned RDMA mode = true\n", | ||
5144 | __func__); | ||
5145 | status = -EIO; | ||
5146 | goto out_session; | ||
5147 | } | ||
5148 | } | ||
5149 | out_session: | ||
5150 | kfree(res.session); | ||
5151 | out: | ||
5152 | dprintk("<-- %s status= %d\n", __func__, status); | ||
5153 | return status; | ||
5154 | } | ||
5155 | |||
5156 | /* | ||
5103 | * nfs4_proc_exchange_id() | 5157 | * nfs4_proc_exchange_id() |
5104 | * | 5158 | * |
5105 | * Since the clientid has expired, all compounds using sessions | 5159 | * Since the clientid has expired, all compounds using sessions |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index edb8ac7fce0e..a6b95b766220 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -326,6 +326,16 @@ static int nfs4_stat_to_errno(int); | |||
326 | 1 /* csr_flags */ + \ | 326 | 1 /* csr_flags */ + \ |
327 | decode_channel_attrs_maxsz + \ | 327 | decode_channel_attrs_maxsz + \ |
328 | decode_channel_attrs_maxsz) | 328 | decode_channel_attrs_maxsz) |
329 | #define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \ | ||
330 | /* bctsa_sessid */ \ | ||
331 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ | ||
332 | 1 /* bctsa_dir */ + \ | ||
333 | 1 /* bctsa_use_conn_in_rdma_mode */) | ||
334 | #define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \ | ||
335 | /* bctsr_sessid */ \ | ||
336 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ | ||
337 | 1 /* bctsr_dir */ + \ | ||
338 | 1 /* bctsr_use_conn_in_rdma_mode */) | ||
329 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) | 339 | #define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4) |
330 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) | 340 | #define decode_destroy_session_maxsz (op_decode_hdr_maxsz) |
331 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ | 341 | #define encode_sequence_maxsz (op_encode_hdr_maxsz + \ |
@@ -719,6 +729,12 @@ static int nfs4_stat_to_errno(int); | |||
719 | decode_putfh_maxsz + \ | 729 | decode_putfh_maxsz + \ |
720 | decode_secinfo_maxsz) | 730 | decode_secinfo_maxsz) |
721 | #if defined(CONFIG_NFS_V4_1) | 731 | #if defined(CONFIG_NFS_V4_1) |
732 | #define NFS4_enc_bind_conn_to_session_sz \ | ||
733 | (compound_encode_hdr_maxsz + \ | ||
734 | encode_bind_conn_to_session_maxsz) | ||
735 | #define NFS4_dec_bind_conn_to_session_sz \ | ||
736 | (compound_decode_hdr_maxsz + \ | ||
737 | decode_bind_conn_to_session_maxsz) | ||
722 | #define NFS4_enc_exchange_id_sz \ | 738 | #define NFS4_enc_exchange_id_sz \ |
723 | (compound_encode_hdr_maxsz + \ | 739 | (compound_encode_hdr_maxsz + \ |
724 | encode_exchange_id_maxsz) | 740 | encode_exchange_id_maxsz) |
@@ -1669,6 +1685,20 @@ static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, stru | |||
1669 | 1685 | ||
1670 | #if defined(CONFIG_NFS_V4_1) | 1686 | #if defined(CONFIG_NFS_V4_1) |
1671 | /* NFSv4.1 operations */ | 1687 | /* NFSv4.1 operations */ |
1688 | static void encode_bind_conn_to_session(struct xdr_stream *xdr, | ||
1689 | struct nfs4_session *session, | ||
1690 | struct compound_hdr *hdr) | ||
1691 | { | ||
1692 | __be32 *p; | ||
1693 | |||
1694 | encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, | ||
1695 | decode_bind_conn_to_session_maxsz, hdr); | ||
1696 | encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | ||
1697 | p = xdr_reserve_space(xdr, 8); | ||
1698 | *p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH); | ||
1699 | *p = 0; /* use_conn_in_rdma_mode = False */ | ||
1700 | } | ||
1701 | |||
1672 | static void encode_exchange_id(struct xdr_stream *xdr, | 1702 | static void encode_exchange_id(struct xdr_stream *xdr, |
1673 | struct nfs41_exchange_id_args *args, | 1703 | struct nfs41_exchange_id_args *args, |
1674 | struct compound_hdr *hdr) | 1704 | struct compound_hdr *hdr) |
@@ -2630,6 +2660,22 @@ static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, | |||
2630 | 2660 | ||
2631 | #if defined(CONFIG_NFS_V4_1) | 2661 | #if defined(CONFIG_NFS_V4_1) |
2632 | /* | 2662 | /* |
2663 | * BIND_CONN_TO_SESSION request | ||
2664 | */ | ||
2665 | static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req, | ||
2666 | struct xdr_stream *xdr, | ||
2667 | struct nfs_client *clp) | ||
2668 | { | ||
2669 | struct compound_hdr hdr = { | ||
2670 | .minorversion = clp->cl_mvops->minor_version, | ||
2671 | }; | ||
2672 | |||
2673 | encode_compound_hdr(xdr, req, &hdr); | ||
2674 | encode_bind_conn_to_session(xdr, clp->cl_session, &hdr); | ||
2675 | encode_nops(&hdr); | ||
2676 | } | ||
2677 | |||
2678 | /* | ||
2633 | * EXCHANGE_ID request | 2679 | * EXCHANGE_ID request |
2634 | */ | 2680 | */ |
2635 | static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, | 2681 | static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, |
@@ -5366,6 +5412,37 @@ static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid) | |||
5366 | return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); | 5412 | return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN); |
5367 | } | 5413 | } |
5368 | 5414 | ||
5415 | static int decode_bind_conn_to_session(struct xdr_stream *xdr, | ||
5416 | struct nfs41_bind_conn_to_session_res *res) | ||
5417 | { | ||
5418 | __be32 *p; | ||
5419 | int status; | ||
5420 | |||
5421 | status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION); | ||
5422 | if (!status) | ||
5423 | status = decode_sessionid(xdr, &res->session->sess_id); | ||
5424 | if (unlikely(status)) | ||
5425 | return status; | ||
5426 | |||
5427 | /* dir flags, rdma mode bool */ | ||
5428 | p = xdr_inline_decode(xdr, 8); | ||
5429 | if (unlikely(!p)) | ||
5430 | goto out_overflow; | ||
5431 | |||
5432 | res->dir = be32_to_cpup(p++); | ||
5433 | if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH) | ||
5434 | return -EIO; | ||
5435 | if (be32_to_cpup(p) == 0) | ||
5436 | res->use_conn_in_rdma_mode = false; | ||
5437 | else | ||
5438 | res->use_conn_in_rdma_mode = true; | ||
5439 | |||
5440 | return 0; | ||
5441 | out_overflow: | ||
5442 | print_overflow_msg(__func__, xdr); | ||
5443 | return -EIO; | ||
5444 | } | ||
5445 | |||
5369 | static int decode_create_session(struct xdr_stream *xdr, | 5446 | static int decode_create_session(struct xdr_stream *xdr, |
5370 | struct nfs41_create_session_res *res) | 5447 | struct nfs41_create_session_res *res) |
5371 | { | 5448 | { |
@@ -6648,6 +6725,22 @@ out: | |||
6648 | 6725 | ||
6649 | #if defined(CONFIG_NFS_V4_1) | 6726 | #if defined(CONFIG_NFS_V4_1) |
6650 | /* | 6727 | /* |
6728 | * Decode BIND_CONN_TO_SESSION response | ||
6729 | */ | ||
6730 | static int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp, | ||
6731 | struct xdr_stream *xdr, | ||
6732 | void *res) | ||
6733 | { | ||
6734 | struct compound_hdr hdr; | ||
6735 | int status; | ||
6736 | |||
6737 | status = decode_compound_hdr(xdr, &hdr); | ||
6738 | if (!status) | ||
6739 | status = decode_bind_conn_to_session(xdr, res); | ||
6740 | return status; | ||
6741 | } | ||
6742 | |||
6743 | /* | ||
6651 | * Decode EXCHANGE_ID response | 6744 | * Decode EXCHANGE_ID response |
6652 | */ | 6745 | */ |
6653 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, | 6746 | static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, |
@@ -7128,6 +7221,8 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
7128 | PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), | 7221 | PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), |
7129 | PROC(SECINFO, enc_secinfo, dec_secinfo), | 7222 | PROC(SECINFO, enc_secinfo, dec_secinfo), |
7130 | #if defined(CONFIG_NFS_V4_1) | 7223 | #if defined(CONFIG_NFS_V4_1) |
7224 | PROC(BIND_CONN_TO_SESSION, | ||
7225 | enc_bind_conn_to_session, dec_bind_conn_to_session), | ||
7131 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), | 7226 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), |
7132 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), | 7227 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), |
7133 | PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), | 7228 | PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), |