@@ -473,8 +473,7 @@ static int max_cb_time(void)
473
473
/* Reference counting, callback cleanup, etc., all look racy as heck.
474
474
* And why is cl_cb_set an atomic? */
475
475
476
- static int setup_callback_client (struct nfs4_client * clp ,
477
- struct nfs4_cb_conn * conn )
476
+ static int setup_callback_client (struct nfs4_client * clp , struct nfs4_cb_conn * conn , struct nfsd4_session * ses )
478
477
{
479
478
struct rpc_timeout timeparms = {
480
479
.to_initval = max_cb_time (),
@@ -501,6 +500,10 @@ static int setup_callback_client(struct nfs4_client *clp,
501
500
args .protocol = XPRT_TRANSPORT_TCP ;
502
501
clp -> cl_cb_ident = conn -> cb_ident ;
503
502
} else {
503
+ if (!conn -> cb_xprt )
504
+ return - EINVAL ;
505
+ clp -> cl_cb_conn .cb_xprt = conn -> cb_xprt ;
506
+ clp -> cl_cb_session = ses ;
504
507
args .bc_xprt = conn -> cb_xprt ;
505
508
args .prognumber = clp -> cl_cb_session -> se_cb_prog ;
506
509
args .protocol = XPRT_TRANSPORT_BC_TCP ;
@@ -756,10 +759,27 @@ static void nfsd4_release_cb(struct nfsd4_callback *cb)
756
759
cb -> cb_ops -> rpc_release (cb );
757
760
}
758
761
762
+ /* requires cl_lock: */
763
+ static struct nfsd4_conn * __nfsd4_find_backchannel (struct nfs4_client * clp )
764
+ {
765
+ struct nfsd4_session * s ;
766
+ struct nfsd4_conn * c ;
767
+
768
+ list_for_each_entry (s , & clp -> cl_sessions , se_perclnt ) {
769
+ list_for_each_entry (c , & s -> se_conns , cn_persession ) {
770
+ if (c -> cn_flags & NFS4_CDFC4_BACK )
771
+ return c ;
772
+ }
773
+ }
774
+ return NULL ;
775
+ }
776
+
759
777
static void nfsd4_process_cb_update (struct nfsd4_callback * cb )
760
778
{
761
779
struct nfs4_cb_conn conn ;
762
780
struct nfs4_client * clp = cb -> cb_clp ;
781
+ struct nfsd4_session * ses = NULL ;
782
+ struct nfsd4_conn * c ;
763
783
int err ;
764
784
765
785
/*
@@ -770,6 +790,10 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
770
790
rpc_shutdown_client (clp -> cl_cb_client );
771
791
clp -> cl_cb_client = NULL ;
772
792
}
793
+ if (clp -> cl_cb_conn .cb_xprt ) {
794
+ svc_xprt_put (clp -> cl_cb_conn .cb_xprt );
795
+ clp -> cl_cb_conn .cb_xprt = NULL ;
796
+ }
773
797
if (test_bit (NFSD4_CLIENT_KILL , & clp -> cl_cb_flags ))
774
798
return ;
775
799
spin_lock (& clp -> cl_lock );
@@ -780,9 +804,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
780
804
BUG_ON (!clp -> cl_cb_flags );
781
805
clear_bit (NFSD4_CLIENT_CB_UPDATE , & clp -> cl_cb_flags );
782
806
memcpy (& conn , & cb -> cb_clp -> cl_cb_conn , sizeof (struct nfs4_cb_conn ));
807
+ c = __nfsd4_find_backchannel (clp );
808
+ if (c ) {
809
+ svc_xprt_get (c -> cn_xprt );
810
+ conn .cb_xprt = c -> cn_xprt ;
811
+ ses = c -> cn_session ;
812
+ }
783
813
spin_unlock (& clp -> cl_lock );
784
814
785
- err = setup_callback_client (clp , & conn );
815
+ err = setup_callback_client (clp , & conn , ses );
786
816
if (err )
787
817
warn_no_callback_path (clp , err );
788
818
}
0 commit comments