提交 1d1bc8f2 编写于 作者: J J. Bruce Fields

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: NJ. Bruce Fields <bfields@redhat.com>
上级 4c649378
...@@ -1004,8 +1004,8 @@ static const char *nfsd4_op_name(unsigned opnum); ...@@ -1004,8 +1004,8 @@ static const char *nfsd4_op_name(unsigned opnum);
* Also note, enforced elsewhere: * Also note, enforced elsewhere:
* - SEQUENCE other than as first op results in * - SEQUENCE other than as first op results in
* NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().)
* - BIND_CONN_TO_SESSION must be the only op in its compound * - BIND_CONN_TO_SESSION must be the only op in its compound.
* (Will be enforced in nfsd4_bind_conn_to_session().) * (Enforced in nfsd4_bind_conn_to_session().)
* - DESTROY_SESSION must be the final operation in a compound, if * - DESTROY_SESSION must be the final operation in a compound, if
* sessionid's in SEQUENCE and DESTROY_SESSION are the same. * sessionid's in SEQUENCE and DESTROY_SESSION are the same.
* (Enforced in nfsd4_destroy_session().) * (Enforced in nfsd4_destroy_session().)
...@@ -1326,6 +1326,11 @@ static struct nfsd4_operation nfsd4_ops[] = { ...@@ -1326,6 +1326,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
.op_name = "OP_EXCHANGE_ID", .op_name = "OP_EXCHANGE_ID",
}, },
[OP_BIND_CONN_TO_SESSION] = {
.op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
.op_name = "OP_BIND_CONN_TO_SESSION",
},
[OP_CREATE_SESSION] = { [OP_CREATE_SESSION] = {
.op_func = (nfsd4op_func)nfsd4_create_session, .op_func = (nfsd4op_func)nfsd4_create_session,
.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
......
...@@ -679,15 +679,12 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn) ...@@ -679,15 +679,12 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn)
return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
} }
static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir)
{ {
struct nfsd4_conn *conn; struct nfsd4_conn *conn;
u32 flags = NFS4_CDFC4_FORE;
int ret; int ret;
if (ses->se_flags & SESSION4_BACK_CHAN) conn = alloc_conn(rqstp, dir);
flags |= NFS4_CDFC4_BACK;
conn = alloc_conn(rqstp, flags);
if (!conn) if (!conn)
return nfserr_jukebox; return nfserr_jukebox;
nfsd4_hash_conn(conn, ses); nfsd4_hash_conn(conn, ses);
...@@ -698,6 +695,17 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) ...@@ -698,6 +695,17 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
return nfs_ok; return nfs_ok;
} }
static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses)
{
u32 dir = NFS4_CDFC4_FORE;
if (ses->se_flags & SESSION4_BACK_CHAN)
dir |= NFS4_CDFC4_BACK;
return nfsd4_new_conn(rqstp, ses, dir);
}
/* must be called under client_lock */
static void nfsd4_del_conns(struct nfsd4_session *s) static void nfsd4_del_conns(struct nfsd4_session *s)
{ {
struct nfs4_client *clp = s->se_client; 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,7 +784,7 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
spin_unlock(&client_lock); spin_unlock(&client_lock);
status = nfsd4_new_conn(rqstp, new); status = nfsd4_new_conn_from_crses(rqstp, new);
/* whoops: benny points out, status is ignored! (err, or bogus) */ /* whoops: benny points out, status is ignored! (err, or bogus) */
if (status) { if (status) {
free_session(&new->se_ref); free_session(&new->se_ref);
...@@ -1597,6 +1605,45 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) ...@@ -1597,6 +1605,45 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
return argp->opcnt == resp->opcnt; return argp->opcnt == resp->opcnt;
} }
static __be32 nfsd4_map_bcts_dir(u32 *dir)
{
switch (*dir) {
case NFS4_CDFC4_FORE:
case NFS4_CDFC4_BACK:
return nfs_ok;
case NFS4_CDFC4_FORE_OR_BOTH:
case NFS4_CDFC4_BACK_OR_BOTH:
*dir = NFS4_CDFC4_BOTH;
return nfs_ok;
};
return nfserr_inval;
}
__be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate,
struct nfsd4_bind_conn_to_session *bcts)
{
__be32 status;
if (!nfsd4_last_compound_op(rqstp))
return nfserr_not_only_op;
spin_lock(&client_lock);
cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid);
/* Sorta weird: we only need the refcnt'ing because new_conn acquires
* client_lock iself: */
if (cstate->session) {
nfsd4_get_session(cstate->session);
atomic_inc(&cstate->session->se_client->cl_refcount);
}
spin_unlock(&client_lock);
if (!cstate->session)
return nfserr_badsession;
status = nfsd4_map_bcts_dir(&bcts->dir);
nfsd4_new_conn(rqstp, cstate->session, bcts->dir);
return nfs_ok;
}
static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
{ {
if (!session) if (!session)
......
...@@ -421,6 +421,21 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access ...@@ -421,6 +421,21 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
DECODE_TAIL; DECODE_TAIL;
} }
static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
{
DECODE_HEAD;
u32 dummy;
READ_BUF(NFS4_MAX_SESSIONID_LEN + 8);
COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
READ32(bcts->dir);
/* XXX: Perhaps Tom Tucker could help us figure out how we
* should be using ctsa_use_conn_in_rdma_mode: */
READ32(dummy);
DECODE_TAIL;
}
static __be32 static __be32
nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
{ {
...@@ -1359,7 +1374,7 @@ static nfsd4_dec nfsd41_dec_ops[] = { ...@@ -1359,7 +1374,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
/* new operations for NFSv4.1 */ /* new operations for NFSv4.1 */
[OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp, [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
[OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
[OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
[OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, [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,6 +2398,21 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
return nfserr; return nfserr;
} }
static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
{
__be32 *p;
if (!nfserr) {
RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
WRITE32(bcts->dir);
/* XXX: ? */
WRITE32(0);
ADJUST_ARGS();
}
return nfserr;
}
static __be32 static __be32
nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
{ {
...@@ -3174,7 +3204,7 @@ static nfsd4_enc nfsd4_enc_ops[] = { ...@@ -3174,7 +3204,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
/* NFSv4.1 operations */ /* NFSv4.1 operations */
[OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop,
[OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_noop, [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
[OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
[OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
[OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,
......
...@@ -148,6 +148,11 @@ struct nfsd4_create_session { ...@@ -148,6 +148,11 @@ struct nfsd4_create_session {
u32 gid; u32 gid;
}; };
struct nfsd4_bind_conn_to_session {
struct nfs4_sessionid sessionid;
u32 dir;
};
/* The single slot clientid cache structure */ /* The single slot clientid cache structure */
struct nfsd4_clid_slot { struct nfsd4_clid_slot {
u32 sl_seqid; u32 sl_seqid;
......
...@@ -427,6 +427,7 @@ struct nfsd4_op { ...@@ -427,6 +427,7 @@ struct nfsd4_op {
/* NFSv4.1 */ /* NFSv4.1 */
struct nfsd4_exchange_id exchange_id; struct nfsd4_exchange_id exchange_id;
struct nfsd4_bind_conn_to_session bind_conn_to_session;
struct nfsd4_create_session create_session; struct nfsd4_create_session create_session;
struct nfsd4_destroy_session destroy_session; struct nfsd4_destroy_session destroy_session;
struct nfsd4_sequence sequence; struct nfsd4_sequence sequence;
...@@ -523,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, ...@@ -523,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
struct nfsd4_sequence *seq); struct nfsd4_sequence *seq);
extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
struct nfsd4_compound_state *, struct nfsd4_exchange_id *); struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *);
extern __be32 nfsd4_create_session(struct svc_rqst *, extern __be32 nfsd4_create_session(struct svc_rqst *,
struct nfsd4_compound_state *, struct nfsd4_compound_state *,
struct nfsd4_create_session *); struct nfsd4_create_session *);
......
...@@ -65,6 +65,9 @@ ...@@ -65,6 +65,9 @@
#define NFS4_CDFC4_FORE 0x1 #define NFS4_CDFC4_FORE 0x1
#define NFS4_CDFC4_BACK 0x2 #define NFS4_CDFC4_BACK 0x2
#define NFS4_CDFC4_BOTH 0x3
#define NFS4_CDFC4_FORE_OR_BOTH 0x3
#define NFS4_CDFC4_BACK_OR_BOTH 0x7
#define NFS4_SET_TO_SERVER_TIME 0 #define NFS4_SET_TO_SERVER_TIME 0
#define NFS4_SET_TO_CLIENT_TIME 1 #define NFS4_SET_TO_CLIENT_TIME 1
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册