OSDN Git Service

nfsd: plumb in a CB_NOTIFY_LOCK operation
authorJeff Layton <jlayton@redhat.com>
Fri, 16 Sep 2016 20:28:23 +0000 (16:28 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 26 Sep 2016 19:20:35 +0000 (15:20 -0400)
Add the encoding/decoding for CB_NOTIFY_LOCK operations.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4callback.c
fs/nfsd/state.h
fs/nfsd/xdr4cb.h

index dbef646..211dc2a 100644 (file)
@@ -623,6 +623,62 @@ static int nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp,
 }
 #endif /* CONFIG_NFSD_PNFS */
 
+static void encode_stateowner(struct xdr_stream *xdr, struct nfs4_stateowner *so)
+{
+       __be32  *p;
+
+       p = xdr_reserve_space(xdr, 8 + 4 + so->so_owner.len);
+       p = xdr_encode_opaque_fixed(p, &so->so_client->cl_clientid, 8);
+       xdr_encode_opaque(p, so->so_owner.data, so->so_owner.len);
+}
+
+static void nfs4_xdr_enc_cb_notify_lock(struct rpc_rqst *req,
+                                       struct xdr_stream *xdr,
+                                       const struct nfsd4_callback *cb)
+{
+       const struct nfsd4_blocked_lock *nbl =
+               container_of(cb, struct nfsd4_blocked_lock, nbl_cb);
+       struct nfs4_lockowner *lo = (struct nfs4_lockowner *)nbl->nbl_lock.fl_owner;
+       struct nfs4_cb_compound_hdr hdr = {
+               .ident = 0,
+               .minorversion = cb->cb_clp->cl_minorversion,
+       };
+
+       __be32 *p;
+
+       BUG_ON(hdr.minorversion == 0);
+
+       encode_cb_compound4args(xdr, &hdr);
+       encode_cb_sequence4args(xdr, cb, &hdr);
+
+       p = xdr_reserve_space(xdr, 4);
+       *p = cpu_to_be32(OP_CB_NOTIFY_LOCK);
+       encode_nfs_fh4(xdr, &nbl->nbl_fh);
+       encode_stateowner(xdr, &lo->lo_owner);
+       hdr.nops++;
+
+       encode_cb_nops(&hdr);
+}
+
+static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp,
+                                       struct xdr_stream *xdr,
+                                       struct nfsd4_callback *cb)
+{
+       struct nfs4_cb_compound_hdr hdr;
+       int status;
+
+       status = decode_cb_compound4res(xdr, &hdr);
+       if (unlikely(status))
+               return status;
+
+       if (cb) {
+               status = decode_cb_sequence4res(xdr, cb);
+               if (unlikely(status || cb->cb_seq_status))
+                       return status;
+       }
+       return decode_cb_op_status(xdr, OP_CB_NOTIFY_LOCK, &cb->cb_status);
+}
+
 /*
  * RPC procedure tables
  */
@@ -643,6 +699,7 @@ static struct rpc_procinfo nfs4_cb_procedures[] = {
 #ifdef CONFIG_NFSD_PNFS
        PROC(CB_LAYOUT, COMPOUND,       cb_layout,      cb_layout),
 #endif
+       PROC(CB_NOTIFY_LOCK,    COMPOUND,       cb_notify_lock, cb_notify_lock),
 };
 
 static struct rpc_version nfs_cb_version4 = {
index 0bdc79c..88d029d 100644 (file)
@@ -571,6 +571,7 @@ enum nfsd4_cb_op {
        NFSPROC4_CLNT_CB_RECALL,
        NFSPROC4_CLNT_CB_LAYOUT,
        NFSPROC4_CLNT_CB_SEQUENCE,
+       NFSPROC4_CLNT_CB_NOTIFY_LOCK,
 };
 
 /* Returns true iff a is later than b: */
@@ -579,6 +580,12 @@ static inline bool nfsd4_stateid_generation_after(stateid_t *a, stateid_t *b)
        return (s32)(a->si_generation - b->si_generation) > 0;
 }
 
+struct nfsd4_blocked_lock {
+       struct file_lock        nbl_lock;
+       struct knfsd_fh         nbl_fh;
+       struct nfsd4_callback   nbl_cb;
+};
+
 struct nfsd4_compound_state;
 struct nfsd_net;
 
index c47f6fd..49b719d 100644 (file)
 #define NFS4_dec_cb_layout_sz          (cb_compound_dec_hdr_sz  +      \
                                        cb_sequence_dec_sz +            \
                                        op_dec_sz)
+
+#define NFS4_enc_cb_notify_lock_sz     (cb_compound_enc_hdr_sz +        \
+                                       cb_sequence_enc_sz +             \
+                                       2 + 1 +                          \
+                                       XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
+                                       enc_nfs4_fh_sz)
+#define NFS4_dec_cb_notify_lock_sz     (cb_compound_dec_hdr_sz  +      \
+                                       cb_sequence_dec_sz +            \
+                                       op_dec_sz)