Detailed analysis of how tree connect state is handled in cifs.ko

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Did a detailed analysis of the 24 functions where we set or check the
tcon status (or need_reconnect).   Detailed analysis below.  There is
some overlap between TID_NEED_RECON and need_reconnect,
but generally the "TID_NEED_RECON" and "TID_NEED_FILES_INVALIDATE"
status are set more
generally by the equivalent boolean, but other status changes are
handled by the tid status enum.

Eight tree connect struct status values are defined for tcon->status
cifsglob.h:122: TID_NEW = 0,
cifsglob.h:123: TID_GOOD,
cifsglob.h:124: TID_EXITING,
cifsglob.h:125: TID_NEED_RECON,
cifsglob.h:126: TID_NEED_TCON,
cifsglob.h:127: TID_IN_TCON,
cifsglob.h:128: TID_NEED_FILES_INVALIDATE, /* currently unused */
cifsglob.h:129: TID_IN_FILES_INVALIDATE

and also a partially overlapping bool tcon->need_reconnect is defined,
and another one called tcon->need_reopen_files

The 23 functions which set or check these statuses are listed below:

1) cifs_umount_begin()
checks if other umount in progress, holds tcp_ses_lock
cifsfs.c:702: if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
cifsfs.c:709: tcon->status = TID_EXITING;

2) cifs_mark_open_files_invalid()
holds tcp_set_lock
returns if TID_NEED_RECON already set, or if session status not CifsGood
otherwise sets TID_IN_FILES_INVALIDATE, marks the files as invalidHandle
unlocks then locks again to check if TID_IN_FILES_INVALIDATE is still set
then sets TID_NEED_TCON.  May be missing call to invalidate inodes on the sb
cifssmb.c:82: tcon->status = TID_IN_FILES_INVALIDATE;
cifssmb.c:102: if (tcon->status == TID_IN_FILES_INVALIDATE)
cifssmb.c:103: tcon->status = TID_NEED_TCON;

3) cifs_reconnect_tcon()
if TID_EXITING then doesn't allow Write or Open or Tree Disconnect
to be sent (holding tcp_ses_lock), and later it checks tcon->need_reconnect
(and exits without sending the tcon if it is not set).
Before sending negotiate, it checks if chan_needs_reconnect is not set
but no tcon needs to be sent (tcon->need_reconnect not set). And finally
after session setup (if it needed to be sent), before sending the tcon
(and marking the open files invalid) it checks need_reconnect once more
to see if it is really needed
cifssmb.c:138: if (tcon->status == TID_EXITING) {
cifssmb.c:191: if (!cifs_chan_needs_reconnect(ses, server) &&
!tcon->need_reconnect) {
cifssmb.c:221: if (tcon->need_reconnect)
cifssmb.c:235: if (rc || !tcon->need_reconnect) {

4) smb_init_no_reconnect()
if tcon->need_reconnect set then it doesn't do the __smb_init and
just returns EHOSTDOWN
cifssmb.c:382:     tcon->need_reconnect) {

5) CIFSSMBTDis()
while holding the chan lock it sees if tcon->need_reconnect and
if so returns EIO instead of sending the tree disconnect
cifssmb.c:650: if ((tcon->need_reconnect) ||
CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {

6) cifs_mark_tcp_ses_conns_for_reconnect()
while holding tcp_ses_lock marks all ses structs as CifsNeedReconnect
and also marks all of the tcon structs they contain as TID_NEED_RECON
and need_reconnect
connect.c:247: tcon->need_reconnect = true;
connect.c:248: tcon->status = TID_NEED_RECON;
connect.c:251: ses->tcon_ipc->need_reconnect = true;


7) match_tcon()
Returns immediately (no match) if TID_EXITING set
connect.c:2210: if (tcon->status == TID_EXITING)

8) __tree_connect_dfs_target()
If ipc$ needs reconnect it connects that before doing the DFS share connect
connect.c:4402: if (ipc->need_reconnect) {

9) cifs_tree_connect()   [DFS enabled version]
While holding tcp_ses_lock sets tcon status as TID_IN_TCON
and if tree connect fails, sets tcon status again as TID_NEED_TCON
else if status is still TID_IN_TCON (presumably to see if reconnect
occurred after tcon in other thread) sets TID_GOOD and also
sets tcon->need_reconnect false
(holding the tcp_ses_lock)
connect.c:4494: tcon->status = TID_IN_TCON;
connect.c:4535: if (tcon->status == TID_IN_TCON)
connect.c:4536: tcon->status = TID_NEED_TCON;
connect.c:4540: if (tcon->status == TID_IN_TCON)
connect.c:4541: tcon->status = TID_GOOD;
connect.c:4543: tcon->need_reconnect = false;

10) cifs_tree_connect()  [non-DFS version]
similar logic to above other version of cifs_tree_connect
connect.c:4562: tcon->status = TID_IN_TCON;
connect.c:4568: if (tcon->status == TID_IN_TCON)
connect.c:4569: tcon->status = TID_NEED_TCON;
connect.c:4573: if (tcon->status == TID_IN_TCON)
connect.c:4574: tcon->status = TID_GOOD;
connect.c:4576: tcon->need_reconnect = false;

11) tconInfoAlloc()
sets TID_NEW when tcon buffer created, no lock needed since not in list yet
misc.c:119: ret_buf->status = TID_NEW;

12) smb2_compound_op()
if error EREMCHG returned from sending compound op then set need_reconnect
(EREMCHG is mapped from STATUS_NETWORK_NAME_DELETED)
smb2inode.c:384: tcon->need_reconnect = true;

13) open_cached_dir()
if error EREMCHG returned from sending compound op then set need_reconnect
smb2ops.c:890: tcon->need_reconnect = true;

14) smb2_is_network_name_deleted()
if STATUS_NETWORK_NAME_DELETED then set need_reconnect to true
(can be called from demultiplex_thread on error e.g.)
smb2ops.c:2541: tcon->need_reconnect = true;

15) smb2_query_info_compound()
similar to the above 3 examples
smb2ops.c:2746: tcon->need_reconnect = true;

16) smb2_reconnect()
checks if TID_EXITING, if so doesn't allow WRITE, CREATE, or TDIS
if tcon->need_reconnect not needed will return 0 (early)
if chan_needs_reconnect_not_set and tcon->need_reconnect can
skip session session setup, and finally just before marking files
invalid (and setting need_reopen_files to true) and sending the
tree_connect if tcon->need_reconnect not set then can exit
without having to send the tcon
smb2pdu.c:166: if (tcon->status == TID_EXITING) {
smb2pdu.c:243: if (!cifs_chan_needs_reconnect(ses, server) &&
!tcon->need_reconnect) {
smb2pdu.c:250: cifs_dbg(FYI, "tcon reconnect: %d", tcon->need_reconnect);
smb2pdu.c:276: if (tcon->need_reconnect)
smb2pdu.c:300: if (!tcon->need_reconnect) {
smb2pdu.c:306:          tcon->need_reopen_files = true;

17) SMB2_tcon()
if sending tree connect failed mark tcon->need_reconnect as true
smb2pdu.c:1891: tcon->need_reconnect = true;

18) SMB2_tdis()
If need_reconnect set, no need to send tree disconnect request
smb2pdu.c:1961: if ((tcon->need_reconnect) ||

19) SMB2_open()
if error EREMCHG (STATUS_NETWORK_NAME_DELETED) returned from open
then set need_reconnect to true
smb2pdu.c:3003: tcon->need_reconnect = true;

20) smb2_reconnect_server()
tcons with need_reconnect or need_reopen_files set are added to
tmp_list with the tcon->rlist (the tree connection's reconnect list).
Then allocates a dummy tcon used for reconnect, and sets it to TID_GOOD,
and its need_reconnect to false then frees it (doesn't hold
tcp_ses_lock but probably not needed)
smb2pdu.c:3799: if (tcon->need_reconnect || tcon->need_reopen_files) {
smb2pdu.c:3809: if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
smb2pdu.c:3863: tcon->status = TID_GOOD;
smb2pdu.c:3865: tcon->need_reconnect = false;

21) cifs_debug_tcon() and cifs_stats_proc_show()
Prints DISCONNECTED if need_reconnect is set to aid debugging
cifs_debug.c:120: if (tcon->need_reconnect)
cifs_debug.c:624: if (tcon->need_reconnect)

22) refresh_mounts()
goes through all sockets, servers and tcons, and if tcon doesn't
need_reconnect then adds it to tail of cache update list (tcon->ulist)
dfs_cache.c:1518: if (!tcon->ipc && !tcon->need_reconnect) {

23) _cifsFileInfo_put()
if tcon->need_reconnect set then don't need to close the file
file.c:489: if (!tcon->need_reconnect && !cifs_file->invalidHandle) {

24) cifs_reopen_persistent_handles()
if need_reopen_files set then returns immediately, else sets
need_reopen_files to false
(unless error returned reopening a file)
file.c:936:     if (!tcon->use_persistent || !tcon->need_reopen_files)
file.c:939:     tcon->need_reopen_files = false;
file.c:958:                     tcon->need_reopen_files = true;

-- 
Thanks,

Steve



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux