Skip to content

Commit 1d1bc8f

Browse files
author
J. Bruce Fields
committed
nfsd4: support BIND_CONN_TO_SESSION
Basic xdr and processing for BIND_CONN_TO_SESSION. This adds a connection to the list of connections associated with a session. Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 4c64937 commit 1d1bc8f

File tree

6 files changed

+102
-10
lines changed

6 files changed

+102
-10
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,8 @@ static const char *nfsd4_op_name(unsigned opnum);
10041004
* Also note, enforced elsewhere:
10051005
* - SEQUENCE other than as first op results in
10061006
* NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().)
1007-
* - BIND_CONN_TO_SESSION must be the only op in its compound
1008-
* (Will be enforced in nfsd4_bind_conn_to_session().)
1007+
* - BIND_CONN_TO_SESSION must be the only op in its compound.
1008+
* (Enforced in nfsd4_bind_conn_to_session().)
10091009
* - DESTROY_SESSION must be the final operation in a compound, if
10101010
* sessionid's in SEQUENCE and DESTROY_SESSION are the same.
10111011
* (Enforced in nfsd4_destroy_session().)
@@ -1326,6 +1326,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
13261326
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
13271327
.op_name = "OP_EXCHANGE_ID",
13281328
},
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+
},
13291334
[OP_CREATE_SESSION] = {
13301335
.op_func = (nfsd4op_func)nfsd4_create_session,
13311336
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,

fs/nfsd/nfs4state.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -679,15 +679,12 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn)
679679
return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
680680
}
681681

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)
683683
{
684684
struct nfsd4_conn *conn;
685-
u32 flags = NFS4_CDFC4_FORE;
686685
int ret;
687686

688-
if (ses->se_flags & SESSION4_BACK_CHAN)
689-
flags |= NFS4_CDFC4_BACK;
690-
conn = alloc_conn(rqstp, flags);
687+
conn = alloc_conn(rqstp, dir);
691688
if (!conn)
692689
return nfserr_jukebox;
693690
nfsd4_hash_conn(conn, ses);
@@ -698,6 +695,17 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
698695
return nfs_ok;
699696
}
700697

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 */
701709
static void nfsd4_del_conns(struct nfsd4_session *s)
702710
{
703711
struct nfs4_client *clp = s->se_client;
@@ -776,7 +784,7 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
776784
spin_unlock(&clp->cl_lock);
777785
spin_unlock(&client_lock);
778786

779-
status = nfsd4_new_conn(rqstp, new);
787+
status = nfsd4_new_conn_from_crses(rqstp, new);
780788
/* whoops: benny points out, status is ignored! (err, or bogus) */
781789
if (status) {
782790
free_session(&new->se_ref);
@@ -1597,6 +1605,45 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
15971605
return argp->opcnt == resp->opcnt;
15981606
}
15991607

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+
16001647
static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
16011648
{
16021649
if (!session)

fs/nfsd/nfs4xdr.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,21 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
421421
DECODE_TAIL;
422422
}
423423

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+
424439
static __be32
425440
nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
426441
{
@@ -1359,7 +1374,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
13591374

13601375
/* new operations for NFSv4.1 */
13611376
[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,
13631378
[OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
13641379
[OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
13651380
[OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
@@ -2383,6 +2398,21 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
23832398
return nfserr;
23842399
}
23852400

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+
23862416
static __be32
23872417
nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
23882418
{
@@ -3174,7 +3204,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
31743204

31753205
/* NFSv4.1 operations */
31763206
[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,
31783208
[OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
31793209
[OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
31803210
[OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,

fs/nfsd/state.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ struct nfsd4_create_session {
148148
u32 gid;
149149
};
150150

151+
struct nfsd4_bind_conn_to_session {
152+
struct nfs4_sessionid sessionid;
153+
u32 dir;
154+
};
155+
151156
/* The single slot clientid cache structure */
152157
struct nfsd4_clid_slot {
153158
u32 sl_seqid;

fs/nfsd/xdr4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ struct nfsd4_op {
427427

428428
/* NFSv4.1 */
429429
struct nfsd4_exchange_id exchange_id;
430+
struct nfsd4_bind_conn_to_session bind_conn_to_session;
430431
struct nfsd4_create_session create_session;
431432
struct nfsd4_destroy_session destroy_session;
432433
struct nfsd4_sequence sequence;
@@ -523,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
523524
struct nfsd4_sequence *seq);
524525
extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
525526
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 *);
526528
extern __be32 nfsd4_create_session(struct svc_rqst *,
527529
struct nfsd4_compound_state *,
528530
struct nfsd4_create_session *);

include/linux/nfs4.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@
6565

6666
#define NFS4_CDFC4_FORE 0x1
6767
#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
6871

6972
#define NFS4_SET_TO_SERVER_TIME 0
7073
#define NFS4_SET_TO_CLIENT_TIME 1

0 commit comments

Comments
 (0)