nfsd4: implement backchannel_ctl operation
authorJ. Bruce Fields <bfields@redhat.com>
Thu, 1 Nov 2012 22:09:48 +0000 (18:09 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Thu, 8 Nov 2012 00:39:58 +0000 (19:39 -0500)
This operation is mandatory for servers to implement.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Documentation/filesystems/nfs/nfs41-server.txt
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/state.h
fs/nfsd/xdr4.h

index 092fad92a3f0e9bcc164b40595c19055e398d9ba..f5ddff2da3020dfaa5e953577332edbd79c9a131 100644 (file)
@@ -39,11 +39,6 @@ interoperability problems with future clients.  Known issues:
          from a linux client are possible, but we aren't really
          conformant with the spec (for example, we don't use kerberos
          on the backchannel correctly).
-       - Incomplete backchannel support: incomplete backchannel gss
-         support and no support for BACKCHANNEL_CTL mean that
-         callbacks (hence delegations and layouts) may not be
-         available and clients confused by the incomplete
-         implementation may fail.
        - We do not support SSV, which provides security for shared
          client-server state (thus preventing unauthorized tampering
          with locks and opens, for example).  It is mandatory for
@@ -89,7 +84,7 @@ Operations
    |                      | MNI        | or OPT)      |                |
    +----------------------+------------+--------------+----------------+
    | ACCESS               | REQ        |              | Section 18.1   |
-NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
+ | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
 I  | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
    | CLOSE                | REQ        |              | Section 18.2   |
    | COMMIT               | REQ        |              | Section 18.3   |
index 6c9a4b291dba2c7e44498a32dc46ab6973e922c9..f955176f1b6fd4fb9148f07d605de370e1d2b516 100644 (file)
@@ -1666,6 +1666,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_name = "OP_EXCHANGE_ID",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize,
        },
+       [OP_BACKCHANNEL_CTL] = {
+               .op_func = (nfsd4op_func)nfsd4_backchannel_ctl,
+               .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
+               .op_name = "OP_BACKCHANNEL_CTL",
+               .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
+       },
        [OP_BIND_CONN_TO_SESSION] = {
                .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
                .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
index dbbbd2fe52364b405b26609e327cd3290f6e99e8..4023e77687eeefae249abfef1fbb6393c1fd6801 100644 (file)
@@ -1865,6 +1865,20 @@ static __be32 nfsd4_map_bcts_dir(u32 *dir)
        return nfserr_inval;
 }
 
+__be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_backchannel_ctl *bc)
+{
+       struct nfsd4_session *session = cstate->session;
+
+       spin_lock(&client_lock);
+       session->se_cb_prog = bc->bc_cb_program;
+       session->se_cb_sec = bc->bc_cb_sec;
+       spin_unlock(&client_lock);
+
+       nfsd4_probe_callback(session->se_client);
+
+       return nfs_ok;
+}
+
 __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
                     struct nfsd4_compound_state *cstate,
                     struct nfsd4_bind_conn_to_session *bcts)
index 511f980b605cbc03c2ebc2428795f887a7afedb7..d7e7c110246ef281db12f039fb60314111a43c8f 100644 (file)
@@ -483,6 +483,17 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_
        DECODE_TAIL;
 }
 
+static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
+{
+       DECODE_HEAD;
+
+       READ_BUF(4);
+       READ32(bc->bc_cb_program);
+       nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
+
+       DECODE_TAIL;
+}
+
 static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
 {
        DECODE_HEAD;
@@ -1536,7 +1547,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
        [OP_RELEASE_LOCKOWNER]  = (nfsd4_dec)nfsd4_decode_notsupp,
 
        /* new operations for NFSv4.1 */
-       [OP_BACKCHANNEL_CTL]    = (nfsd4_dec)nfsd4_decode_notsupp,
+       [OP_BACKCHANNEL_CTL]    = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
        [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
        [OP_EXCHANGE_ID]        = (nfsd4_dec)nfsd4_decode_exchange_id,
        [OP_CREATE_SESSION]     = (nfsd4_dec)nfsd4_decode_create_session,
index bff856c34a324303451c3c123e30768ffcdd0781..758bc9c2646b03b3b4e1a68f5661c723e74c40d8 100644 (file)
@@ -166,6 +166,11 @@ struct nfsd4_create_session {
        struct nfsd4_cb_sec             cb_sec;
 };
 
+struct nfsd4_backchannel_ctl {
+       u32     bc_cb_program;
+       struct nfsd4_cb_sec             bc_cb_sec;
+};
+
 struct nfsd4_bind_conn_to_session {
        struct nfs4_sessionid           sessionid;
        u32                             dir;
index acd127d4ee821660e71fe1e38ef1c804962f6508..71c5c47f2750e9a1bb87bdd39809dc3d6a23fc19 100644 (file)
@@ -462,6 +462,7 @@ struct nfsd4_op {
 
                /* NFSv4.1 */
                struct nfsd4_exchange_id        exchange_id;
+               struct nfsd4_backchannel_ctl    backchannel_ctl;
                struct nfsd4_bind_conn_to_session bind_conn_to_session;
                struct nfsd4_create_session     create_session;
                struct nfsd4_destroy_session    destroy_session;
@@ -566,6 +567,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
                struct nfsd4_sequence *seq);
 extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
                struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
+extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *);
 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 *,
                struct nfsd4_compound_state *,