@@ -139,14 +139,73 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
139139 return ;
140140}
141141
142+ static int wait_for_server_reconnect (struct TCP_Server_Info * server ,
143+ __le16 smb2_command , bool retry )
144+ {
145+ int timeout = 10 ;
146+ int rc ;
147+
148+ spin_lock (& server -> srv_lock );
149+ if (server -> tcpStatus != CifsNeedReconnect ) {
150+ spin_unlock (& server -> srv_lock );
151+ return 0 ;
152+ }
153+ timeout *= server -> nr_targets ;
154+ spin_unlock (& server -> srv_lock );
155+
156+ /*
157+ * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
158+ * here since they are implicitly done when session drops.
159+ */
160+ switch (smb2_command ) {
161+ /*
162+ * BB Should we keep oplock break and add flush to exceptions?
163+ */
164+ case SMB2_TREE_DISCONNECT :
165+ case SMB2_CANCEL :
166+ case SMB2_CLOSE :
167+ case SMB2_OPLOCK_BREAK :
168+ return - EAGAIN ;
169+ }
170+
171+ /*
172+ * Give demultiplex thread up to 10 seconds to each target available for
173+ * reconnect -- should be greater than cifs socket timeout which is 7
174+ * seconds.
175+ *
176+ * On "soft" mounts we wait once. Hard mounts keep retrying until
177+ * process is killed or server comes back on-line.
178+ */
179+ do {
180+ rc = wait_event_interruptible_timeout (server -> response_q ,
181+ (server -> tcpStatus != CifsNeedReconnect ),
182+ timeout * HZ );
183+ if (rc < 0 ) {
184+ cifs_dbg (FYI , "%s: aborting reconnect due to received signal\n" ,
185+ __func__ );
186+ return - ERESTARTSYS ;
187+ }
188+
189+ /* are we still trying to reconnect? */
190+ spin_lock (& server -> srv_lock );
191+ if (server -> tcpStatus != CifsNeedReconnect ) {
192+ spin_unlock (& server -> srv_lock );
193+ return 0 ;
194+ }
195+ spin_unlock (& server -> srv_lock );
196+ } while (retry );
197+
198+ cifs_dbg (FYI , "%s: gave up waiting on reconnect\n" , __func__ );
199+ return - EHOSTDOWN ;
200+ }
201+
142202static int
143203smb2_reconnect (__le16 smb2_command , struct cifs_tcon * tcon ,
144204 struct TCP_Server_Info * server )
145205{
146206 int rc = 0 ;
147207 struct nls_table * nls_codepage ;
148208 struct cifs_ses * ses ;
149- int retries ;
150209
151210 /*
152211 * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
@@ -184,61 +243,11 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
184243 (!tcon -> ses -> server ) || !server )
185244 return - EIO ;
186245
187- ses = tcon -> ses ;
188- retries = server -> nr_targets ;
189-
190- /*
191- * Give demultiplex thread up to 10 seconds to each target available for
192- * reconnect -- should be greater than cifs socket timeout which is 7
193- * seconds.
194- */
195- while (server -> tcpStatus == CifsNeedReconnect ) {
196- /*
197- * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
198- * here since they are implicitly done when session drops.
199- */
200- switch (smb2_command ) {
201- /*
202- * BB Should we keep oplock break and add flush to exceptions?
203- */
204- case SMB2_TREE_DISCONNECT :
205- case SMB2_CANCEL :
206- case SMB2_CLOSE :
207- case SMB2_OPLOCK_BREAK :
208- return - EAGAIN ;
209- }
210-
211- rc = wait_event_interruptible_timeout (server -> response_q ,
212- (server -> tcpStatus != CifsNeedReconnect ),
213- 10 * HZ );
214- if (rc < 0 ) {
215- cifs_dbg (FYI , "%s: aborting reconnect due to a received signal by the process\n" ,
216- __func__ );
217- return - ERESTARTSYS ;
218- }
219-
220- /* are we still trying to reconnect? */
221- spin_lock (& server -> srv_lock );
222- if (server -> tcpStatus != CifsNeedReconnect ) {
223- spin_unlock (& server -> srv_lock );
224- break ;
225- }
226- spin_unlock (& server -> srv_lock );
227-
228- if (retries && -- retries )
229- continue ;
246+ rc = wait_for_server_reconnect (server , smb2_command , tcon -> retry );
247+ if (rc )
248+ return rc ;
230249
231- /*
232- * on "soft" mounts we wait once. Hard mounts keep
233- * retrying until process is killed or server comes
234- * back on-line
235- */
236- if (!tcon -> retry ) {
237- cifs_dbg (FYI , "gave up waiting on reconnect in smb_init\n" );
238- return - EHOSTDOWN ;
239- }
240- retries = server -> nr_targets ;
241- }
250+ ses = tcon -> ses ;
242251
243252 spin_lock (& ses -> chan_lock );
244253 if (!cifs_chan_needs_reconnect (ses , server ) && !tcon -> need_reconnect ) {
0 commit comments