39
39
#include "state.h"
40
40
#include "netns.h"
41
41
#include "xdr4cb.h"
42
+ #include "xdr4.h"
42
43
43
44
#define NFSDDBG_FACILITY NFSDDBG_PROC
44
45
@@ -105,6 +106,7 @@ enum nfs_cb_opnum4 {
105
106
OP_CB_WANTS_CANCELLED = 12 ,
106
107
OP_CB_NOTIFY_LOCK = 13 ,
107
108
OP_CB_NOTIFY_DEVICEID = 14 ,
109
+ OP_CB_OFFLOAD = 15 ,
108
110
OP_CB_ILLEGAL = 10044
109
111
};
110
112
@@ -682,6 +684,101 @@ static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp,
682
684
return decode_cb_op_status (xdr , OP_CB_NOTIFY_LOCK , & cb -> cb_status );
683
685
}
684
686
687
+ /*
688
+ * struct write_response4 {
689
+ * stateid4 wr_callback_id<1>;
690
+ * length4 wr_count;
691
+ * stable_how4 wr_committed;
692
+ * verifier4 wr_writeverf;
693
+ * };
694
+ * union offload_info4 switch (nfsstat4 coa_status) {
695
+ * case NFS4_OK:
696
+ * write_response4 coa_resok4;
697
+ * default:
698
+ * length4 coa_bytes_copied;
699
+ * };
700
+ * struct CB_OFFLOAD4args {
701
+ * nfs_fh4 coa_fh;
702
+ * stateid4 coa_stateid;
703
+ * offload_info4 coa_offload_info;
704
+ * };
705
+ */
706
+ static void encode_offload_info4 (struct xdr_stream * xdr ,
707
+ __be32 nfserr ,
708
+ const struct nfsd4_copy * cp )
709
+ {
710
+ __be32 * p ;
711
+
712
+ p = xdr_reserve_space (xdr , 4 );
713
+ * p ++ = nfserr ;
714
+ if (!nfserr ) {
715
+ p = xdr_reserve_space (xdr , 4 + 8 + 4 + NFS4_VERIFIER_SIZE );
716
+ p = xdr_encode_empty_array (p );
717
+ p = xdr_encode_hyper (p , cp -> cp_res .wr_bytes_written );
718
+ * p ++ = cpu_to_be32 (cp -> cp_res .wr_stable_how );
719
+ p = xdr_encode_opaque_fixed (p , cp -> cp_res .wr_verifier .data ,
720
+ NFS4_VERIFIER_SIZE );
721
+ } else {
722
+ p = xdr_reserve_space (xdr , 8 );
723
+ /* We always return success if bytes were written */
724
+ p = xdr_encode_hyper (p , 0 );
725
+ }
726
+ }
727
+
728
+ static void encode_cb_offload4args (struct xdr_stream * xdr ,
729
+ __be32 nfserr ,
730
+ const struct knfsd_fh * fh ,
731
+ const struct nfsd4_copy * cp ,
732
+ struct nfs4_cb_compound_hdr * hdr )
733
+ {
734
+ __be32 * p ;
735
+
736
+ p = xdr_reserve_space (xdr , 4 );
737
+ * p ++ = cpu_to_be32 (OP_CB_OFFLOAD );
738
+ encode_nfs_fh4 (xdr , fh );
739
+ encode_stateid4 (xdr , & cp -> cp_res .cb_stateid );
740
+ encode_offload_info4 (xdr , nfserr , cp );
741
+
742
+ hdr -> nops ++ ;
743
+ }
744
+
745
+ static void nfs4_xdr_enc_cb_offload (struct rpc_rqst * req ,
746
+ struct xdr_stream * xdr ,
747
+ const void * data )
748
+ {
749
+ const struct nfsd4_callback * cb = data ;
750
+ const struct nfsd4_copy * cp =
751
+ container_of (cb , struct nfsd4_copy , cp_cb );
752
+ struct nfs4_cb_compound_hdr hdr = {
753
+ .ident = 0 ,
754
+ .minorversion = cb -> cb_clp -> cl_minorversion ,
755
+ };
756
+
757
+ encode_cb_compound4args (xdr , & hdr );
758
+ encode_cb_sequence4args (xdr , cb , & hdr );
759
+ encode_cb_offload4args (xdr , cp -> nfserr , & cp -> fh , cp , & hdr );
760
+ encode_cb_nops (& hdr );
761
+ }
762
+
763
+ static int nfs4_xdr_dec_cb_offload (struct rpc_rqst * rqstp ,
764
+ struct xdr_stream * xdr ,
765
+ void * data )
766
+ {
767
+ struct nfsd4_callback * cb = data ;
768
+ struct nfs4_cb_compound_hdr hdr ;
769
+ int status ;
770
+
771
+ status = decode_cb_compound4res (xdr , & hdr );
772
+ if (unlikely (status ))
773
+ return status ;
774
+
775
+ if (cb ) {
776
+ status = decode_cb_sequence4res (xdr , cb );
777
+ if (unlikely (status || cb -> cb_seq_status ))
778
+ return status ;
779
+ }
780
+ return decode_cb_op_status (xdr , OP_CB_OFFLOAD , & cb -> cb_status );
781
+ }
685
782
/*
686
783
* RPC procedure tables
687
784
*/
@@ -703,6 +800,7 @@ static const struct rpc_procinfo nfs4_cb_procedures[] = {
703
800
PROC (CB_LAYOUT , COMPOUND , cb_layout , cb_layout ),
704
801
#endif
705
802
PROC (CB_NOTIFY_LOCK , COMPOUND , cb_notify_lock , cb_notify_lock ),
803
+ PROC (CB_OFFLOAD , COMPOUND , cb_offload , cb_offload ),
706
804
};
707
805
708
806
static unsigned int nfs4_cb_counts [ARRAY_SIZE (nfs4_cb_procedures )];
0 commit comments