@@ -387,7 +387,7 @@ static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
387
387
#ifdef CONFIG_CIFS_DFS_UPCALL
388
388
struct super_cb_data {
389
389
struct TCP_Server_Info * server ;
390
- struct cifs_sb_info * cifs_sb ;
390
+ struct super_block * sb ;
391
391
};
392
392
393
393
/* These functions must be called with server->srv_mutex held */
@@ -398,25 +398,39 @@ static void super_cb(struct super_block *sb, void *arg)
398
398
struct cifs_sb_info * cifs_sb ;
399
399
struct cifs_tcon * tcon ;
400
400
401
- if (d -> cifs_sb )
401
+ if (d -> sb )
402
402
return ;
403
403
404
404
cifs_sb = CIFS_SB (sb );
405
405
tcon = cifs_sb_master_tcon (cifs_sb );
406
406
if (tcon -> ses -> server == d -> server )
407
- d -> cifs_sb = cifs_sb ;
407
+ d -> sb = sb ;
408
408
}
409
409
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 )
412
411
{
413
412
struct super_cb_data d = {
414
413
.server = server ,
415
- .cifs_sb = NULL ,
414
+ .sb = NULL ,
416
415
};
417
416
418
417
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 );
420
434
}
421
435
422
436
static void reconn_inval_dfs_target (struct TCP_Server_Info * server ,
@@ -480,6 +494,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
480
494
struct mid_q_entry * mid_entry ;
481
495
struct list_head retry_list ;
482
496
#ifdef CONFIG_CIFS_DFS_UPCALL
497
+ struct super_block * sb = NULL ;
483
498
struct cifs_sb_info * cifs_sb = NULL ;
484
499
struct dfs_cache_tgt_list tgt_list = {0 };
485
500
struct dfs_cache_tgt_iterator * tgt_it = NULL ;
@@ -489,13 +504,15 @@ cifs_reconnect(struct TCP_Server_Info *server)
489
504
server -> nr_targets = 1 ;
490
505
#ifdef CONFIG_CIFS_DFS_UPCALL
491
506
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 );
495
510
cifs_dbg (FYI , "%s: will not do DFS failover: rc = %d\n" ,
496
511
__func__ , rc );
497
- cifs_sb = NULL ;
512
+ sb = NULL ;
498
513
} else {
514
+ cifs_sb = CIFS_SB (sb );
515
+
499
516
rc = reconn_setup_dfs_targets (cifs_sb , & tgt_list , & tgt_it );
500
517
if (rc && (rc != - EOPNOTSUPP )) {
501
518
cifs_server_dbg (VFS , "%s: no target servers for DFS failover\n" ,
@@ -512,6 +529,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
512
529
/* the demux thread will exit normally
513
530
next time through the loop */
514
531
spin_unlock (& GlobalMid_Lock );
532
+ #ifdef CONFIG_CIFS_DFS_UPCALL
533
+ dfs_cache_free_tgts (& tgt_list );
534
+ put_tcp_super (sb );
535
+ #endif
515
536
return rc ;
516
537
} else
517
538
server -> tcpStatus = CifsNeedReconnect ;
@@ -638,7 +659,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
638
659
__func__ , rc );
639
660
}
640
661
dfs_cache_free_tgts (& tgt_list );
662
+
641
663
}
664
+
665
+ put_tcp_super (sb );
642
666
#endif
643
667
if (server -> tcpStatus == CifsNeedNegotiate )
644
668
mod_delayed_work (cifsiod_wq , & server -> echo , 0 );
0 commit comments