diff options
-rw-r--r-- | fs/nfsd/nfs4proc.c | 9 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 59 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 34 | ||||
-rw-r--r-- | fs/nfsd/state.h | 5 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 2 | ||||
-rw-r--r-- | include/linux/nfs4.h | 3 |
6 files changed, 102 insertions, 10 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index fd6694b49e1c..db52546143d1 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1004,8 +1004,8 @@ static const char *nfsd4_op_name(unsigned opnum); | |||
1004 | * Also note, enforced elsewhere: | 1004 | * Also note, enforced elsewhere: |
1005 | * - SEQUENCE other than as first op results in | 1005 | * - SEQUENCE other than as first op results in |
1006 | * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) | 1006 | * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) |
1007 | * - BIND_CONN_TO_SESSION must be the only op in its compound | 1007 | * - BIND_CONN_TO_SESSION must be the only op in its compound. |
1008 | * (Will be enforced in nfsd4_bind_conn_to_session().) | 1008 | * (Enforced in nfsd4_bind_conn_to_session().) |
1009 | * - DESTROY_SESSION must be the final operation in a compound, if | 1009 | * - DESTROY_SESSION must be the final operation in a compound, if |
1010 | * sessionid's in SEQUENCE and DESTROY_SESSION are the same. | 1010 | * sessionid's in SEQUENCE and DESTROY_SESSION are the same. |
1011 | * (Enforced in nfsd4_destroy_session().) | 1011 | * (Enforced in nfsd4_destroy_session().) |
@@ -1326,6 +1326,11 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1326 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, | 1326 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, |
1327 | .op_name = "OP_EXCHANGE_ID", | 1327 | .op_name = "OP_EXCHANGE_ID", |
1328 | }, | 1328 | }, |
1329 | [OP_BIND_CONN_TO_SESSION] = { | ||
1330 | .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session, | ||
1331 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, | ||
1332 | .op_name = "OP_BIND_CONN_TO_SESSION", | ||
1333 | }, | ||
1329 | [OP_CREATE_SESSION] = { | 1334 | [OP_CREATE_SESSION] = { |
1330 | .op_func = (nfsd4op_func)nfsd4_create_session, | 1335 | .op_func = (nfsd4op_func)nfsd4_create_session, |
1331 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, | 1336 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3cf9900d5f32..956174f488a7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -679,15 +679,12 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn) | |||
679 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); | 679 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); |
680 | } | 680 | } |
681 | 681 | ||
682 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | 682 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) |
683 | { | 683 | { |
684 | struct nfsd4_conn *conn; | 684 | struct nfsd4_conn *conn; |
685 | u32 flags = NFS4_CDFC4_FORE; | ||
686 | int ret; | 685 | int ret; |
687 | 686 | ||
688 | if (ses->se_flags & SESSION4_BACK_CHAN) | 687 | conn = alloc_conn(rqstp, dir); |
689 | flags |= NFS4_CDFC4_BACK; | ||
690 | conn = alloc_conn(rqstp, flags); | ||
691 | if (!conn) | 688 | if (!conn) |
692 | return nfserr_jukebox; | 689 | return nfserr_jukebox; |
693 | nfsd4_hash_conn(conn, ses); | 690 | nfsd4_hash_conn(conn, ses); |
@@ -698,6 +695,17 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | |||
698 | return nfs_ok; | 695 | return nfs_ok; |
699 | } | 696 | } |
700 | 697 | ||
698 | static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) | ||
699 | { | ||
700 | u32 dir = NFS4_CDFC4_FORE; | ||
701 | |||
702 | if (ses->se_flags & SESSION4_BACK_CHAN) | ||
703 | dir |= NFS4_CDFC4_BACK; | ||
704 | |||
705 | return nfsd4_new_conn(rqstp, ses, dir); | ||
706 | } | ||
707 | |||
708 | /* must be called under client_lock */ | ||
701 | static void nfsd4_del_conns(struct nfsd4_session *s) | 709 | static void nfsd4_del_conns(struct nfsd4_session *s) |
702 | { | 710 | { |
703 | struct nfs4_client *clp = s->se_client; | 711 | struct nfs4_client *clp = s->se_client; |
@@ -776,7 +784,7 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
776 | spin_unlock(&clp->cl_lock); | 784 | spin_unlock(&clp->cl_lock); |
777 | spin_unlock(&client_lock); | 785 | spin_unlock(&client_lock); |
778 | 786 | ||
779 | status = nfsd4_new_conn(rqstp, new); | 787 | status = nfsd4_new_conn_from_crses(rqstp, new); |
780 | /* whoops: benny points out, status is ignored! (err, or bogus) */ | 788 | /* whoops: benny points out, status is ignored! (err, or bogus) */ |
781 | if (status) { | 789 | if (status) { |
782 | free_session(&new->se_ref); | 790 | free_session(&new->se_ref); |
@@ -1597,6 +1605,45 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) | |||
1597 | return argp->opcnt == resp->opcnt; | 1605 | return argp->opcnt == resp->opcnt; |
1598 | } | 1606 | } |
1599 | 1607 | ||
1608 | static __be32 nfsd4_map_bcts_dir(u32 *dir) | ||
1609 | { | ||
1610 | switch (*dir) { | ||
1611 | case NFS4_CDFC4_FORE: | ||
1612 | case NFS4_CDFC4_BACK: | ||
1613 | return nfs_ok; | ||
1614 | case NFS4_CDFC4_FORE_OR_BOTH: | ||
1615 | case NFS4_CDFC4_BACK_OR_BOTH: | ||
1616 | *dir = NFS4_CDFC4_BOTH; | ||
1617 | return nfs_ok; | ||
1618 | }; | ||
1619 | return nfserr_inval; | ||
1620 | } | ||
1621 | |||
1622 | __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, | ||
1623 | struct nfsd4_compound_state *cstate, | ||
1624 | struct nfsd4_bind_conn_to_session *bcts) | ||
1625 | { | ||
1626 | __be32 status; | ||
1627 | |||
1628 | if (!nfsd4_last_compound_op(rqstp)) | ||
1629 | return nfserr_not_only_op; | ||
1630 | spin_lock(&client_lock); | ||
1631 | cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid); | ||
1632 | /* Sorta weird: we only need the refcnt'ing because new_conn acquires | ||
1633 | * client_lock iself: */ | ||
1634 | if (cstate->session) { | ||
1635 | nfsd4_get_session(cstate->session); | ||
1636 | atomic_inc(&cstate->session->se_client->cl_refcount); | ||
1637 | } | ||
1638 | spin_unlock(&client_lock); | ||
1639 | if (!cstate->session) | ||
1640 | return nfserr_badsession; | ||
1641 | |||
1642 | status = nfsd4_map_bcts_dir(&bcts->dir); | ||
1643 | nfsd4_new_conn(rqstp, cstate->session, bcts->dir); | ||
1644 | return nfs_ok; | ||
1645 | } | ||
1646 | |||
1600 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) | 1647 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) |
1601 | { | 1648 | { |
1602 | if (!session) | 1649 | if (!session) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index ca3786905dec..4ff2c9e0b276 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -421,6 +421,21 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access | |||
421 | DECODE_TAIL; | 421 | DECODE_TAIL; |
422 | } | 422 | } |
423 | 423 | ||
424 | static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts) | ||
425 | { | ||
426 | DECODE_HEAD; | ||
427 | u32 dummy; | ||
428 | |||
429 | READ_BUF(NFS4_MAX_SESSIONID_LEN + 8); | ||
430 | COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | ||
431 | READ32(bcts->dir); | ||
432 | /* XXX: Perhaps Tom Tucker could help us figure out how we | ||
433 | * should be using ctsa_use_conn_in_rdma_mode: */ | ||
434 | READ32(dummy); | ||
435 | |||
436 | DECODE_TAIL; | ||
437 | } | ||
438 | |||
424 | static __be32 | 439 | static __be32 |
425 | nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) | 440 | nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) |
426 | { | 441 | { |
@@ -1359,7 +1374,7 @@ static nfsd4_dec nfsd41_dec_ops[] = { | |||
1359 | 1374 | ||
1360 | /* new operations for NFSv4.1 */ | 1375 | /* new operations for NFSv4.1 */ |
1361 | [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, | 1376 | [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, |
1362 | [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp, | 1377 | [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session, |
1363 | [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, | 1378 | [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, |
1364 | [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, | 1379 | [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, |
1365 | [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, | 1380 | [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, |
@@ -2383,6 +2398,21 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
2383 | return nfserr; | 2398 | return nfserr; |
2384 | } | 2399 | } |
2385 | 2400 | ||
2401 | static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts) | ||
2402 | { | ||
2403 | __be32 *p; | ||
2404 | |||
2405 | if (!nfserr) { | ||
2406 | RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); | ||
2407 | WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | ||
2408 | WRITE32(bcts->dir); | ||
2409 | /* XXX: ? */ | ||
2410 | WRITE32(0); | ||
2411 | ADJUST_ARGS(); | ||
2412 | } | ||
2413 | return nfserr; | ||
2414 | } | ||
2415 | |||
2386 | static __be32 | 2416 | static __be32 |
2387 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) | 2417 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) |
2388 | { | 2418 | { |
@@ -3174,7 +3204,7 @@ static nfsd4_enc nfsd4_enc_ops[] = { | |||
3174 | 3204 | ||
3175 | /* NFSv4.1 operations */ | 3205 | /* NFSv4.1 operations */ |
3176 | [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, | 3206 | [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, |
3177 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_noop, | 3207 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, |
3178 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, | 3208 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, |
3179 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, | 3209 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, |
3180 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, | 3210 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index cf6dc83fd545..442f6d8e024c 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -148,6 +148,11 @@ struct nfsd4_create_session { | |||
148 | u32 gid; | 148 | u32 gid; |
149 | }; | 149 | }; |
150 | 150 | ||
151 | struct nfsd4_bind_conn_to_session { | ||
152 | struct nfs4_sessionid sessionid; | ||
153 | u32 dir; | ||
154 | }; | ||
155 | |||
151 | /* The single slot clientid cache structure */ | 156 | /* The single slot clientid cache structure */ |
152 | struct nfsd4_clid_slot { | 157 | struct nfsd4_clid_slot { |
153 | u32 sl_seqid; | 158 | u32 sl_seqid; |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 799c30c3b495..3a7aa4d98c1f 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -427,6 +427,7 @@ struct nfsd4_op { | |||
427 | 427 | ||
428 | /* NFSv4.1 */ | 428 | /* NFSv4.1 */ |
429 | struct nfsd4_exchange_id exchange_id; | 429 | struct nfsd4_exchange_id exchange_id; |
430 | struct nfsd4_bind_conn_to_session bind_conn_to_session; | ||
430 | struct nfsd4_create_session create_session; | 431 | struct nfsd4_create_session create_session; |
431 | struct nfsd4_destroy_session destroy_session; | 432 | struct nfsd4_destroy_session destroy_session; |
432 | struct nfsd4_sequence sequence; | 433 | struct nfsd4_sequence sequence; |
@@ -523,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | |||
523 | struct nfsd4_sequence *seq); | 524 | struct nfsd4_sequence *seq); |
524 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, | 525 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, |
525 | struct nfsd4_compound_state *, struct nfsd4_exchange_id *); | 526 | struct nfsd4_compound_state *, struct nfsd4_exchange_id *); |
527 | extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *); | ||
526 | extern __be32 nfsd4_create_session(struct svc_rqst *, | 528 | extern __be32 nfsd4_create_session(struct svc_rqst *, |
527 | struct nfsd4_compound_state *, | 529 | struct nfsd4_compound_state *, |
528 | struct nfsd4_create_session *); | 530 | struct nfsd4_create_session *); |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 26afa3021ed6..a5918938e41e 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -65,6 +65,9 @@ | |||
65 | 65 | ||
66 | #define NFS4_CDFC4_FORE 0x1 | 66 | #define NFS4_CDFC4_FORE 0x1 |
67 | #define NFS4_CDFC4_BACK 0x2 | 67 | #define NFS4_CDFC4_BACK 0x2 |
68 | #define NFS4_CDFC4_BOTH 0x3 | ||
69 | #define NFS4_CDFC4_FORE_OR_BOTH 0x3 | ||
70 | #define NFS4_CDFC4_BACK_OR_BOTH 0x7 | ||
68 | 71 | ||
69 | #define NFS4_SET_TO_SERVER_TIME 0 | 72 | #define NFS4_SET_TO_SERVER_TIME 0 |
70 | #define NFS4_SET_TO_CLIENT_TIME 1 | 73 | #define NFS4_SET_TO_CLIENT_TIME 1 |