@@ -605,6 +605,7 @@ inc_rfc1001_len(void *buf, int count)
605605struct TCP_Server_Info {
606606 struct list_head tcp_ses_list ;
607607 struct list_head smb_ses_list ;
608+ spinlock_t srv_lock ; /* protect anything here that is not protected */
608609 __u64 conn_id ; /* connection identifier (useful for debugging) */
609610 int srv_count ; /* reference counter */
610611 /* 15 character server name + 0x20 16th byte indicating type = srv */
@@ -622,6 +623,7 @@ struct TCP_Server_Info {
622623#endif
623624 wait_queue_head_t response_q ;
624625 wait_queue_head_t request_q ; /* if more than maxmpx to srvr must block*/
626+ spinlock_t mid_lock ; /* protect mid queue and it's entries */
625627 struct list_head pending_mid_q ;
626628 bool noblocksnd ; /* use blocking sendmsg */
627629 bool noautotune ; /* do not autotune send buf sizes */
@@ -1008,6 +1010,7 @@ struct cifs_ses {
10081010 struct list_head rlist ; /* reconnect list */
10091011 struct list_head tcon_list ;
10101012 struct cifs_tcon * tcon_ipc ;
1013+ spinlock_t ses_lock ; /* protect anything here that is not protected */
10111014 struct mutex session_mutex ;
10121015 struct TCP_Server_Info * server ; /* pointer to server info */
10131016 int ses_count ; /* reference counter */
@@ -1169,6 +1172,7 @@ struct cifs_tcon {
11691172 struct list_head tcon_list ;
11701173 int tc_count ;
11711174 struct list_head rlist ; /* reconnect list */
1175+ spinlock_t tc_lock ; /* protect anything here that is not protected */
11721176 atomic_t num_local_opens ; /* num of all opens including disconnected */
11731177 atomic_t num_remote_opens ; /* num of all network opens on server */
11741178 struct list_head openFileList ;
@@ -1899,33 +1903,78 @@ require use of the stronger protocol */
18991903 */
19001904
19011905/****************************************************************************
1902- * Locking notes. All updates to global variables and lists should be
1903- * protected by spinlocks or semaphores.
1906+ * Here are all the locks (spinlock, mutex, semaphore) in cifs.ko, arranged according
1907+ * to the locking order. i.e. if two locks are to be held together, the lock that
1908+ * appears higher in this list needs to be taken before the other.
19041909 *
1905- * Spinlocks
1906- * ---------
1907- * GlobalMid_Lock protects:
1908- * list operations on pending_mid_q and oplockQ
1909- * updates to XID counters, multiplex id and SMB sequence numbers
1910- * list operations on global DnotifyReqList
1911- * updates to ses->status and TCP_Server_Info->tcpStatus
1912- * updates to server->CurrentMid
1913- * tcp_ses_lock protects:
1914- * list operations on tcp and SMB session lists
1915- * tcon->open_file_lock protects the list of open files hanging off the tcon
1916- * inode->open_file_lock protects the openFileList hanging off the inode
1917- * cfile->file_info_lock protects counters and fields in cifs file struct
1918- * f_owner.lock protects certain per file struct operations
1919- * mapping->page_lock protects certain per page operations
1910+ * If you hold a lock that is lower in this list, and you need to take a higher lock
1911+ * (or if you think that one of the functions that you're calling may need to), first
1912+ * drop the lock you hold, pick up the higher lock, then the lower one. This will
1913+ * ensure that locks are picked up only in one direction in the below table
1914+ * (top to bottom).
19201915 *
1921- * Note that the cifs_tcon.open_file_lock should be taken before
1922- * not after the cifsInodeInfo.open_file_lock
1916+ * Also, if you expect a function to be called with a lock held, explicitly document
1917+ * this in the comments on top of your function definition.
19231918 *
1924- * Semaphores
1925- * ----------
1926- * cifsInodeInfo->lock_sem protects:
1927- * the list of locks held by the inode
1919+ * And also, try to keep the critical sections (lock hold time) to be as minimal as
1920+ * possible. Blocking / calling other functions with a lock held always increase
1921+ * the risk of a possible deadlock.
19281922 *
1923+ * Following this rule will avoid unnecessary deadlocks, which can get really hard to
1924+ * debug. Also, any new lock that you introduce, please add to this list in the correct
1925+ * order.
1926+ *
1927+ * Please populate this list whenever you introduce new locks in your changes. Or in
1928+ * case I've missed some existing locks. Please ensure that it's added in the list
1929+ * based on the locking order expected.
1930+ *
1931+ * =====================================================================================
1932+ * Lock Protects Initialization fn
1933+ * =====================================================================================
1934+ * vol_list_lock
1935+ * vol_info->ctx_lock vol_info->ctx
1936+ * cifs_sb_info->tlink_tree_lock cifs_sb_info->tlink_tree cifs_setup_cifs_sb
1937+ * TCP_Server_Info-> TCP_Server_Info cifs_get_tcp_session
1938+ * reconnect_mutex
1939+ * TCP_Server_Info->srv_mutex TCP_Server_Info cifs_get_tcp_session
1940+ * cifs_ses->session_mutex cifs_ses sesInfoAlloc
1941+ * cifs_tcon
1942+ * cifs_tcon->open_file_lock cifs_tcon->openFileList tconInfoAlloc
1943+ * cifs_tcon->pending_opens
1944+ * cifs_tcon->stat_lock cifs_tcon->bytes_read tconInfoAlloc
1945+ * cifs_tcon->bytes_written
1946+ * cifs_tcp_ses_lock cifs_tcp_ses_list sesInfoAlloc
1947+ * GlobalMid_Lock GlobalMaxActiveXid init_cifs
1948+ * GlobalCurrentXid
1949+ * GlobalTotalActiveXid
1950+ * TCP_Server_Info->srv_lock (anything in struct not protected by another lock and can change)
1951+ * TCP_Server_Info->mid_lock TCP_Server_Info->pending_mid_q cifs_get_tcp_session
1952+ * ->CurrentMid
1953+ * (any changes in mid_q_entry fields)
1954+ * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_session
1955+ * ->credits
1956+ * ->echo_credits
1957+ * ->oplock_credits
1958+ * ->reconnect_instance
1959+ * cifs_ses->ses_lock (anything that is not protected by another lock and can change)
1960+ * cifs_ses->iface_lock cifs_ses->iface_list sesInfoAlloc
1961+ * ->iface_count
1962+ * ->iface_last_update
1963+ * cifs_ses->chan_lock cifs_ses->chans
1964+ * ->chans_need_reconnect
1965+ * ->chans_in_reconnect
1966+ * cifs_tcon->tc_lock (anything that is not protected by another lock and can change)
1967+ * cifsInodeInfo->open_file_lock cifsInodeInfo->openFileList cifs_alloc_inode
1968+ * cifsInodeInfo->writers_lock cifsInodeInfo->writers cifsInodeInfo_alloc
1969+ * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once
1970+ * ->can_cache_brlcks
1971+ * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc
1972+ * cached_fid->fid_mutex cifs_tcon->crfid tconInfoAlloc
1973+ * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
1974+ * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
1975+ * ->invalidHandle initiate_cifs_search
1976+ * ->oplock_break_cancelled
1977+ * cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc
19291978 ****************************************************************************/
19301979
19311980#ifdef DECLARE_GLOBALS_HERE
@@ -1946,9 +1995,7 @@ extern struct list_head cifs_tcp_ses_list;
19461995/*
19471996 * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
19481997 * tcp session, and the list of tcon's per smb session. It also protects
1949- * the reference counters for the server, smb session, and tcon. It also
1950- * protects some fields in the TCP_Server_Info struct such as dstaddr. Finally,
1951- * changes to the tcon->tidStatus should be done while holding this lock.
1998+ * the reference counters for the server, smb session, and tcon.
19521999 * generally the locks should be taken in order tcp_ses_lock before
19532000 * tcon->open_file_lock and that before file->file_info_lock since the
19542001 * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
0 commit comments