@@ -243,11 +243,27 @@ struct proto smc_proto6 = {
243243};
244244EXPORT_SYMBOL_GPL (smc_proto6 );
245245
246+ static void smc_fback_restore_callbacks (struct smc_sock * smc )
247+ {
248+ struct sock * clcsk = smc -> clcsock -> sk ;
249+
250+ write_lock_bh (& clcsk -> sk_callback_lock );
251+ clcsk -> sk_user_data = NULL ;
252+
253+ smc_clcsock_restore_cb (& clcsk -> sk_state_change , & smc -> clcsk_state_change );
254+ smc_clcsock_restore_cb (& clcsk -> sk_data_ready , & smc -> clcsk_data_ready );
255+ smc_clcsock_restore_cb (& clcsk -> sk_write_space , & smc -> clcsk_write_space );
256+ smc_clcsock_restore_cb (& clcsk -> sk_error_report , & smc -> clcsk_error_report );
257+
258+ write_unlock_bh (& clcsk -> sk_callback_lock );
259+ }
260+
246261static void smc_restore_fallback_changes (struct smc_sock * smc )
247262{
248263 if (smc -> clcsock -> file ) { /* non-accepted sockets have no file yet */
249264 smc -> clcsock -> file -> private_data = smc -> sk .sk_socket ;
250265 smc -> clcsock -> file = NULL ;
266+ smc_fback_restore_callbacks (smc );
251267 }
252268}
253269
@@ -745,48 +761,57 @@ static void smc_fback_forward_wakeup(struct smc_sock *smc, struct sock *clcsk,
745761
746762static void smc_fback_state_change (struct sock * clcsk )
747763{
748- struct smc_sock * smc =
749- smc_clcsock_user_data (clcsk );
764+ struct smc_sock * smc ;
750765
751- if (!smc )
752- return ;
753- smc_fback_forward_wakeup (smc , clcsk , smc -> clcsk_state_change );
766+ read_lock_bh (& clcsk -> sk_callback_lock );
767+ smc = smc_clcsock_user_data (clcsk );
768+ if (smc )
769+ smc_fback_forward_wakeup (smc , clcsk ,
770+ smc -> clcsk_state_change );
771+ read_unlock_bh (& clcsk -> sk_callback_lock );
754772}
755773
756774static void smc_fback_data_ready (struct sock * clcsk )
757775{
758- struct smc_sock * smc =
759- smc_clcsock_user_data (clcsk );
776+ struct smc_sock * smc ;
760777
761- if (!smc )
762- return ;
763- smc_fback_forward_wakeup (smc , clcsk , smc -> clcsk_data_ready );
778+ read_lock_bh (& clcsk -> sk_callback_lock );
779+ smc = smc_clcsock_user_data (clcsk );
780+ if (smc )
781+ smc_fback_forward_wakeup (smc , clcsk ,
782+ smc -> clcsk_data_ready );
783+ read_unlock_bh (& clcsk -> sk_callback_lock );
764784}
765785
766786static void smc_fback_write_space (struct sock * clcsk )
767787{
768- struct smc_sock * smc =
769- smc_clcsock_user_data (clcsk );
788+ struct smc_sock * smc ;
770789
771- if (!smc )
772- return ;
773- smc_fback_forward_wakeup (smc , clcsk , smc -> clcsk_write_space );
790+ read_lock_bh (& clcsk -> sk_callback_lock );
791+ smc = smc_clcsock_user_data (clcsk );
792+ if (smc )
793+ smc_fback_forward_wakeup (smc , clcsk ,
794+ smc -> clcsk_write_space );
795+ read_unlock_bh (& clcsk -> sk_callback_lock );
774796}
775797
776798static void smc_fback_error_report (struct sock * clcsk )
777799{
778- struct smc_sock * smc =
779- smc_clcsock_user_data (clcsk );
800+ struct smc_sock * smc ;
780801
781- if (!smc )
782- return ;
783- smc_fback_forward_wakeup (smc , clcsk , smc -> clcsk_error_report );
802+ read_lock_bh (& clcsk -> sk_callback_lock );
803+ smc = smc_clcsock_user_data (clcsk );
804+ if (smc )
805+ smc_fback_forward_wakeup (smc , clcsk ,
806+ smc -> clcsk_error_report );
807+ read_unlock_bh (& clcsk -> sk_callback_lock );
784808}
785809
786810static void smc_fback_replace_callbacks (struct smc_sock * smc )
787811{
788812 struct sock * clcsk = smc -> clcsock -> sk ;
789813
814+ write_lock_bh (& clcsk -> sk_callback_lock );
790815 clcsk -> sk_user_data = (void * )((uintptr_t )smc | SK_USER_DATA_NOCOPY );
791816
792817 smc_clcsock_replace_cb (& clcsk -> sk_state_change , smc_fback_state_change ,
@@ -797,6 +822,8 @@ static void smc_fback_replace_callbacks(struct smc_sock *smc)
797822 & smc -> clcsk_write_space );
798823 smc_clcsock_replace_cb (& clcsk -> sk_error_report , smc_fback_error_report ,
799824 & smc -> clcsk_error_report );
825+
826+ write_unlock_bh (& clcsk -> sk_callback_lock );
800827}
801828
802829static int smc_switch_to_fallback (struct smc_sock * smc , int reason_code )
@@ -2370,17 +2397,20 @@ static void smc_tcp_listen_work(struct work_struct *work)
23702397
23712398static void smc_clcsock_data_ready (struct sock * listen_clcsock )
23722399{
2373- struct smc_sock * lsmc =
2374- smc_clcsock_user_data (listen_clcsock );
2400+ struct smc_sock * lsmc ;
23752401
2402+ read_lock_bh (& listen_clcsock -> sk_callback_lock );
2403+ lsmc = smc_clcsock_user_data (listen_clcsock );
23762404 if (!lsmc )
2377- return ;
2405+ goto out ;
23782406 lsmc -> clcsk_data_ready (listen_clcsock );
23792407 if (lsmc -> sk .sk_state == SMC_LISTEN ) {
23802408 sock_hold (& lsmc -> sk ); /* sock_put in smc_tcp_listen_work() */
23812409 if (!queue_work (smc_tcp_ls_wq , & lsmc -> tcp_listen_work ))
23822410 sock_put (& lsmc -> sk );
23832411 }
2412+ out :
2413+ read_unlock_bh (& listen_clcsock -> sk_callback_lock );
23842414}
23852415
23862416static int smc_listen (struct socket * sock , int backlog )
@@ -2412,10 +2442,12 @@ static int smc_listen(struct socket *sock, int backlog)
24122442 /* save original sk_data_ready function and establish
24132443 * smc-specific sk_data_ready function
24142444 */
2445+ write_lock_bh (& smc -> clcsock -> sk -> sk_callback_lock );
24152446 smc -> clcsock -> sk -> sk_user_data =
24162447 (void * )((uintptr_t )smc | SK_USER_DATA_NOCOPY );
24172448 smc_clcsock_replace_cb (& smc -> clcsock -> sk -> sk_data_ready ,
24182449 smc_clcsock_data_ready , & smc -> clcsk_data_ready );
2450+ write_unlock_bh (& smc -> clcsock -> sk -> sk_callback_lock );
24192451
24202452 /* save original ops */
24212453 smc -> ori_af_ops = inet_csk (smc -> clcsock -> sk )-> icsk_af_ops ;
@@ -2430,9 +2462,11 @@ static int smc_listen(struct socket *sock, int backlog)
24302462
24312463 rc = kernel_listen (smc -> clcsock , backlog );
24322464 if (rc ) {
2465+ write_lock_bh (& smc -> clcsock -> sk -> sk_callback_lock );
24332466 smc_clcsock_restore_cb (& smc -> clcsock -> sk -> sk_data_ready ,
24342467 & smc -> clcsk_data_ready );
24352468 smc -> clcsock -> sk -> sk_user_data = NULL ;
2469+ write_unlock_bh (& smc -> clcsock -> sk -> sk_callback_lock );
24362470 goto out ;
24372471 }
24382472 sk -> sk_max_ack_backlog = backlog ;
0 commit comments