For every request we send, whether it is SMB1 or SMB2+, we attempt to reconnect tcon (cifs_reconnect_tcon or smb2_reconnect) before carrying out the request. So, while server->tcpStatus != CifsNeedReconnect, we wait for the reconnection to succeed on wait_event_interruptible_timeout(). If it returns, that means that either the condition was evaluated to true, or timeout elapsed, or it was interrupted by a signal. Since we're not handling the case where the process woke up due to a received signal (-ERESTARTSYS), the next call to wait_event_interruptible_timeout() will _always_ fail and we end up looping forever inside either cifs_reconnect_tcon() or smb2_reconnect(). Here's an example of how to trigger that: $ mount.cifs //foo/share /mnt/test -o username=foo,password=foo,vers=1.0,hard (break connection to server before executing bellow cmd) $ stat -f /mnt/test & sleep 140 [1] 2511 $ ps -aux -q 2511 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2511 0.0 0.0 12892 1008 pts/0 S 12:24 0:00 stat -f /mnt/test $ kill -9 2511 (wait for a while; process is stuck in the kernel) $ ps -aux -q 2511 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2511 83.2 0.0 12892 1008 pts/0 R 12:24 30:01 stat -f /mnt/test By using 'hard' mount point means that cifs.ko will keep retrying indefinitely, however we must allow the process to be killed otherwise it would hang the system.
Unified · Split
| @@ -157,8 +157,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) · 156 unmodified lines | ||
| 157 | 157 | * greater than cifs socket timeout which is 7 seconds |
| 158 | 158 | */ |
| 159 | 159 | while (server->tcpStatus == CifsNeedReconnect) { |
| 160 | − wait_event_interruptible_timeout(server->response_q, | |
| 161 | − (server->tcpStatus != CifsNeedReconnect), 10 * HZ); | |
| 160 | + rc = wait_event_interruptible_timeout(server->response_q, | |
| 161 | + (server->tcpStatus != CifsNeedReconnect), | |
| 162 | + 10 * HZ); | |
| 163 | + if (rc < 0) { | |
| 164 | + cifs_dbg(FYI, "%s: aborting reconnect due to a received" | |
| 165 | + " signal by the process\n", __func__); | |
| 166 | + return -ERESTARTSYS; | |
| 167 | + } | |
| 162 | 168 | |
| 163 | 169 | /* are we still trying to reconnect? */ |
| 164 | 170 | if (server->tcpStatus != CifsNeedReconnect) |
| @@ -155,7 +155,7 @@ out: · 154 unmodified lines | ||
| 155 | 155 | static int |
| 156 | 156 | smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) |
| 157 | 157 | { |
| 158 | − int rc = 0; | |
| 158 | + int rc; | |
| 159 | 159 | struct nls_table *nls_codepage; |
| 160 | 160 | struct cifs_ses *ses; |
| 161 | 161 | struct TCP_Server_Info *server; |
| @@ -166,10 +166,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 4 unmodified lines | ||
| 166 | 166 | * for those three - in the calling routine. |
| 167 | 167 | */ |
| 168 | 168 | if (tcon == NULL) |
| 169 | − return rc; | |
| 169 | + return 0; | |
| 170 | 170 | |
| 171 | 171 | if (smb2_command == SMB2_TREE_CONNECT) |
| 172 | − return rc; | |
| 172 | + return 0; | |
| 173 | 173 | |
| 174 | 174 | if (tcon->tidStatus == CifsExiting) { |
| 175 | 175 | /* |
| @@ -212,8 +212,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 36 unmodified lines | ||
| 212 | 212 | return -EAGAIN; |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | − wait_event_interruptible_timeout(server->response_q, | |
| 216 | − (server->tcpStatus != CifsNeedReconnect), 10 * HZ); | |
| 215 | + rc = wait_event_interruptible_timeout(server->response_q, | |
| 216 | + (server->tcpStatus != CifsNeedReconnect), | |
| 217 | + 10 * HZ); | |
| 218 | + if (rc < 0) { | |
| 219 | + cifs_dbg(FYI, "%s: aborting reconnect due to a received" | |
| 220 | + " signal by the process\n", __func__); | |
| 221 | + return -ERESTARTSYS; | |
| 222 | + } | |
| 217 | 223 | |
| 218 | 224 | /* are we still trying to reconnect? */ |
| 219 | 225 | if (server->tcpStatus != CifsNeedReconnect) |
| @@ -231,7 +237,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) · 11 unmodified lines | ||
| 231 | 237 | } |
| 232 | 238 | |
| 233 | 239 | if (!tcon->ses->need_reconnect && !tcon->need_reconnect) |
| 234 | − return rc; | |
| 240 | + return 0; | |
| 235 | 241 | |
| 236 | 242 | nls_codepage = load_nls_default(); |
| 237 | 243 | |