@@ -387,7 +387,7 @@ static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
387387#ifdef CONFIG_CIFS_DFS_UPCALL
388388struct super_cb_data {
389389 struct TCP_Server_Info * server ;
390- struct cifs_sb_info * cifs_sb ;
390+ struct super_block * sb ;
391391};
392392
393393/* These functions must be called with server->srv_mutex held */
@@ -398,25 +398,39 @@ static void super_cb(struct super_block *sb, void *arg)
398398 struct cifs_sb_info * cifs_sb ;
399399 struct cifs_tcon * tcon ;
400400
401- if (d -> cifs_sb )
401+ if (d -> sb )
402402 return ;
403403
404404 cifs_sb = CIFS_SB (sb );
405405 tcon = cifs_sb_master_tcon (cifs_sb );
406406 if (tcon -> ses -> server == d -> server )
407- d -> cifs_sb = cifs_sb ;
407+ d -> sb = sb ;
408408}
409409
410- static inline struct cifs_sb_info *
411- find_super_by_tcp (struct TCP_Server_Info * server )
410+ static struct super_block * get_tcp_super (struct TCP_Server_Info * server )
412411{
413412 struct super_cb_data d = {
414413 .server = server ,
415- .cifs_sb = NULL ,
414+ .sb = NULL ,
416415 };
417416
418417 iterate_supers_type (& cifs_fs_type , super_cb , & d );
419- return d .cifs_sb ? d .cifs_sb : ERR_PTR (- ENOENT );
418+
419+ if (unlikely (!d .sb ))
420+ return ERR_PTR (- ENOENT );
421+ /*
422+ * Grab an active reference in order to prevent automounts (DFS links)
423+ * of expiring and then freeing up our cifs superblock pointer while
424+ * we're doing failover.
425+ */
426+ cifs_sb_active (d .sb );
427+ return d .sb ;
428+ }
429+
430+ static inline void put_tcp_super (struct super_block * sb )
431+ {
432+ if (!IS_ERR_OR_NULL (sb ))
433+ cifs_sb_deactive (sb );
420434}
421435
422436static void reconn_inval_dfs_target (struct TCP_Server_Info * server ,
@@ -480,6 +494,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
480494 struct mid_q_entry * mid_entry ;
481495 struct list_head retry_list ;
482496#ifdef CONFIG_CIFS_DFS_UPCALL
497+ struct super_block * sb = NULL ;
483498 struct cifs_sb_info * cifs_sb = NULL ;
484499 struct dfs_cache_tgt_list tgt_list = {0 };
485500 struct dfs_cache_tgt_iterator * tgt_it = NULL ;
@@ -489,13 +504,15 @@ cifs_reconnect(struct TCP_Server_Info *server)
489504 server -> nr_targets = 1 ;
490505#ifdef CONFIG_CIFS_DFS_UPCALL
491506 spin_unlock (& GlobalMid_Lock );
492- cifs_sb = find_super_by_tcp (server );
493- if (IS_ERR (cifs_sb )) {
494- rc = PTR_ERR (cifs_sb );
507+ sb = get_tcp_super (server );
508+ if (IS_ERR (sb )) {
509+ rc = PTR_ERR (sb );
495510 cifs_dbg (FYI , "%s: will not do DFS failover: rc = %d\n" ,
496511 __func__ , rc );
497- cifs_sb = NULL ;
512+ sb = NULL ;
498513 } else {
514+ cifs_sb = CIFS_SB (sb );
515+
499516 rc = reconn_setup_dfs_targets (cifs_sb , & tgt_list , & tgt_it );
500517 if (rc && (rc != - EOPNOTSUPP )) {
501518 cifs_server_dbg (VFS , "%s: no target servers for DFS failover\n" ,
@@ -512,6 +529,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
512529 /* the demux thread will exit normally
513530 next time through the loop */
514531 spin_unlock (& GlobalMid_Lock );
532+ #ifdef CONFIG_CIFS_DFS_UPCALL
533+ dfs_cache_free_tgts (& tgt_list );
534+ put_tcp_super (sb );
535+ #endif
515536 return rc ;
516537 } else
517538 server -> tcpStatus = CifsNeedReconnect ;
@@ -638,7 +659,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
638659 __func__ , rc );
639660 }
640661 dfs_cache_free_tgts (& tgt_list );
662+
641663 }
664+
665+ put_tcp_super (sb );
642666#endif
643667 if (server -> tcpStatus == CifsNeedNegotiate )
644668 mod_delayed_work (cifsiod_wq , & server -> echo , 0 );
0 commit comments