@@ -391,7 +391,7 @@ static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
391
391
#ifdef CONFIG_CIFS_DFS_UPCALL
392
392
struct super_cb_data {
393
393
struct TCP_Server_Info * server ;
394
- struct cifs_sb_info * cifs_sb ;
394
+ struct super_block * sb ;
395
395
};
396
396
397
397
/* These functions must be called with server->srv_mutex held */
@@ -402,25 +402,39 @@ static void super_cb(struct super_block *sb, void *arg)
402
402
struct cifs_sb_info * cifs_sb ;
403
403
struct cifs_tcon * tcon ;
404
404
405
- if (d -> cifs_sb )
405
+ if (d -> sb )
406
406
return ;
407
407
408
408
cifs_sb = CIFS_SB (sb );
409
409
tcon = cifs_sb_master_tcon (cifs_sb );
410
410
if (tcon -> ses -> server == d -> server )
411
- d -> cifs_sb = cifs_sb ;
411
+ d -> sb = sb ;
412
412
}
413
413
414
- static inline struct cifs_sb_info *
415
- find_super_by_tcp (struct TCP_Server_Info * server )
414
+ static struct super_block * get_tcp_super (struct TCP_Server_Info * server )
416
415
{
417
416
struct super_cb_data d = {
418
417
.server = server ,
419
- .cifs_sb = NULL ,
418
+ .sb = NULL ,
420
419
};
421
420
422
421
iterate_supers_type (& cifs_fs_type , super_cb , & d );
423
- return d .cifs_sb ? d .cifs_sb : ERR_PTR (- ENOENT );
422
+
423
+ if (unlikely (!d .sb ))
424
+ return ERR_PTR (- ENOENT );
425
+ /*
426
+ * Grab an active reference in order to prevent automounts (DFS links)
427
+ * of expiring and then freeing up our cifs superblock pointer while
428
+ * we're doing failover.
429
+ */
430
+ cifs_sb_active (d .sb );
431
+ return d .sb ;
432
+ }
433
+
434
+ static inline void put_tcp_super (struct super_block * sb )
435
+ {
436
+ if (!IS_ERR_OR_NULL (sb ))
437
+ cifs_sb_deactive (sb );
424
438
}
425
439
426
440
static void reconn_inval_dfs_target (struct TCP_Server_Info * server ,
@@ -484,6 +498,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
484
498
struct mid_q_entry * mid_entry ;
485
499
struct list_head retry_list ;
486
500
#ifdef CONFIG_CIFS_DFS_UPCALL
501
+ struct super_block * sb = NULL ;
487
502
struct cifs_sb_info * cifs_sb = NULL ;
488
503
struct dfs_cache_tgt_list tgt_list = {0 };
489
504
struct dfs_cache_tgt_iterator * tgt_it = NULL ;
@@ -493,13 +508,15 @@ cifs_reconnect(struct TCP_Server_Info *server)
493
508
server -> nr_targets = 1 ;
494
509
#ifdef CONFIG_CIFS_DFS_UPCALL
495
510
spin_unlock (& GlobalMid_Lock );
496
- cifs_sb = find_super_by_tcp (server );
497
- if (IS_ERR (cifs_sb )) {
498
- rc = PTR_ERR (cifs_sb );
511
+ sb = get_tcp_super (server );
512
+ if (IS_ERR (sb )) {
513
+ rc = PTR_ERR (sb );
499
514
cifs_dbg (FYI , "%s: will not do DFS failover: rc = %d\n" ,
500
515
__func__ , rc );
501
- cifs_sb = NULL ;
516
+ sb = NULL ;
502
517
} else {
518
+ cifs_sb = CIFS_SB (sb );
519
+
503
520
rc = reconn_setup_dfs_targets (cifs_sb , & tgt_list , & tgt_it );
504
521
if (rc && (rc != - EOPNOTSUPP )) {
505
522
cifs_server_dbg (VFS , "%s: no target servers for DFS failover\n" ,
@@ -516,6 +533,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
516
533
/* the demux thread will exit normally
517
534
next time through the loop */
518
535
spin_unlock (& GlobalMid_Lock );
536
+ #ifdef CONFIG_CIFS_DFS_UPCALL
537
+ dfs_cache_free_tgts (& tgt_list );
538
+ put_tcp_super (sb );
539
+ #endif
519
540
return rc ;
520
541
} else
521
542
server -> tcpStatus = CifsNeedReconnect ;
@@ -642,7 +663,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
642
663
__func__ , rc );
643
664
}
644
665
dfs_cache_free_tgts (& tgt_list );
666
+
645
667
}
668
+
669
+ put_tcp_super (sb );
646
670
#endif
647
671
if (server -> tcpStatus == CifsNeedNegotiate )
648
672
mod_delayed_work (cifsiod_wq , & server -> echo , 0 );
0 commit comments