Commit 9162ab20 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: consolidate reconnect logic in smb_init routines

There's a large cut and paste chunk of code in smb_init and
small_smb_init to handle reconnects. Break it out into a separate
function, clean it up and have both routines call it.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 6ab409b5
...@@ -100,110 +100,138 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon) ...@@ -100,110 +100,138 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
to this tcon */ to this tcon */
} }
/* Allocate and return pointer to an SMB request buffer, and set basic /* reconnect the socket, tcon, and smb session if needed */
SMB information in the SMB header. If the return code is zero, this
function must have filled in request_buf pointer */
static int static int
small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
void **request_buf)
{ {
int rc = 0; int rc = 0;
struct cifsSesInfo *ses;
struct TCP_Server_Info *server;
struct nls_table *nls_codepage;
/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so /*
check for tcp and smb session status done differently * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
for those three - in the calling routine */ * tcp and smb session status done differently for those three - in the
if (tcon) { * calling routine
*/
if (!tcon)
return 0;
ses = tcon->ses;
server = ses->server;
/*
* only tree disconnect, open, and write, (and ulogoff which does not
* have tcon) are allowed as we start force umount
*/
if (tcon->tidStatus == CifsExiting) { if (tcon->tidStatus == CifsExiting) {
/* only tree disconnect, open, and write, if (smb_command != SMB_COM_WRITE_ANDX &&
(and ulogoff which does not have tcon) smb_command != SMB_COM_OPEN_ANDX &&
are allowed as we start force umount */ smb_command != SMB_COM_TREE_DISCONNECT) {
if ((smb_command != SMB_COM_WRITE_ANDX) &&
(smb_command != SMB_COM_OPEN_ANDX) &&
(smb_command != SMB_COM_TREE_DISCONNECT)) {
cFYI(1, ("can not send cmd %d while umounting", cFYI(1, ("can not send cmd %d while umounting",
smb_command)); smb_command));
return -ENODEV; return -ENODEV;
} }
} }
if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
(tcon->ses->server)) { if (ses->status == CifsExiting)
struct nls_table *nls_codepage; return -EIO;
/* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket /*
timeout which is 7 seconds */ * Give demultiplex thread up to 10 seconds to reconnect, should be
while (tcon->ses->server->tcpStatus == * greater than cifs socket timeout which is 7 seconds
CifsNeedReconnect) { */
wait_event_interruptible_timeout(tcon->ses->server->response_q, while (server->tcpStatus == CifsNeedReconnect) {
(tcon->ses->server->tcpStatus == wait_event_interruptible_timeout(server->response_q,
CifsGood), 10 * HZ); (server->tcpStatus == CifsGood), 10 * HZ);
if (tcon->ses->server->tcpStatus ==
CifsNeedReconnect) { /* is TCP session is reestablished now ?*/
/* on "soft" mounts we wait once */ if (server->tcpStatus != CifsNeedReconnect)
if (!tcon->retry ||
(tcon->ses->status == CifsExiting)) {
cFYI(1, ("gave up waiting on "
"reconnect in smb_init"));
return -EHOSTDOWN;
} /* else "hard" mount - keep retrying
until process is killed or server
comes back on-line */
} else /* TCP session is reestablished now */
break; break;
/*
* on "soft" mounts we wait once. Hard mounts keep
* retrying until process is killed or server comes
* back on-line
*/
if (!tcon->retry || ses->status == CifsExiting) {
cFYI(1, ("gave up waiting on reconnect in smb_init"));
return -EHOSTDOWN;
}
} }
if (!ses->need_reconnect && !tcon->need_reconnect)
return 0;
nls_codepage = load_nls_default(); nls_codepage = load_nls_default();
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */ /*
down(&tcon->ses->sesSem); * need to prevent multiple threads trying to simultaneously
if (tcon->ses->need_reconnect) * reconnect the same SMB session
rc = cifs_setup_session(0, tcon->ses, */
nls_codepage); down(&ses->sesSem);
if (!rc && (tcon->need_reconnect)) { if (ses->need_reconnect)
rc = cifs_setup_session(0, ses, nls_codepage);
/* do we need to reconnect tcon? */
if (rc || !tcon->need_reconnect) {
up(&ses->sesSem);
goto out;
}
mark_open_files_invalid(tcon); mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
tcon, nls_codepage); up(&ses->sesSem);
up(&tcon->ses->sesSem); cFYI(1, ("reconnect tcon rc = %d", rc));
/* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size if (rc)
shrinking */ goto out;
if (rc == 0) {
/*
* FIXME: check if wsize needs updated due to negotiated smb buffer
* size shrinking
*/
atomic_inc(&tconInfoReconnectCount); atomic_inc(&tconInfoReconnectCount);
/* tell server Unix caps we support */ /* tell server Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX) if (ses->capabilities & CAP_UNIX)
reset_cifs_unix_caps( reset_cifs_unix_caps(0, tcon, NULL, NULL);
0 /* no xid */,
tcon,
NULL /* we do not know sb */,
NULL /* no vol info */);
}
cFYI(1, ("reconnect tcon rc = %d", rc)); /*
/* Removed call to reopen open files here. * Removed call to reopen open files here. It is safer (and faster) to
It is safer (and faster) to reopen files * reopen files one at a time as needed in read and write.
one at a time as needed in read and write */ *
* FIXME: what about file locks? don't we need to reclaim them ASAP?
*/
/* Check if handle based operation so we out:
know whether we can continue or not without /*
returning to caller to reset file handle */ * Check if handle based operation so we know whether we can continue
* or not without returning to caller to reset file handle
*/
switch (smb_command) { switch (smb_command) {
case SMB_COM_READ_ANDX: case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX: case SMB_COM_WRITE_ANDX:
case SMB_COM_CLOSE: case SMB_COM_CLOSE:
case SMB_COM_FIND_CLOSE2: case SMB_COM_FIND_CLOSE2:
case SMB_COM_LOCKING_ANDX: { case SMB_COM_LOCKING_ANDX:
unload_nls(nls_codepage); rc = -EAGAIN;
return -EAGAIN;
}
}
} else {
up(&tcon->ses->sesSem);
} }
unload_nls(nls_codepage); unload_nls(nls_codepage);
return rc;
}
} else { /* Allocate and return pointer to an SMB request buffer, and set basic
return -EIO; SMB information in the SMB header. If the return code is zero, this
} function must have filled in request_buf pointer */
} static int
small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf)
{
int rc = 0;
rc = cifs_reconnect_tcon(tcon, smb_command);
if (rc) if (rc)
return rc; return rc;
...@@ -256,101 +284,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -256,101 +284,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
{ {
int rc = 0; int rc = 0;
/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so rc = cifs_reconnect_tcon(tcon, smb_command);
check for tcp and smb session status done differently
for those three - in the calling routine */
if (tcon) {
if (tcon->tidStatus == CifsExiting) {
/* only tree disconnect, open, and write,
(and ulogoff which does not have tcon)
are allowed as we start force umount */
if ((smb_command != SMB_COM_WRITE_ANDX) &&
(smb_command != SMB_COM_OPEN_ANDX) &&
(smb_command != SMB_COM_TREE_DISCONNECT)) {
cFYI(1, ("can not send cmd %d while umounting",
smb_command));
return -ENODEV;
}
}
if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
(tcon->ses->server)) {
struct nls_table *nls_codepage;
/* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket
timeout which is 7 seconds */
while (tcon->ses->server->tcpStatus ==
CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q,
(tcon->ses->server->tcpStatus ==
CifsGood), 10 * HZ);
if (tcon->ses->server->tcpStatus ==
CifsNeedReconnect) {
/* on "soft" mounts we wait once */
if (!tcon->retry ||
(tcon->ses->status == CifsExiting)) {
cFYI(1, ("gave up waiting on "
"reconnect in smb_init"));
return -EHOSTDOWN;
} /* else "hard" mount - keep retrying
until process is killed or server
comes on-line */
} else /* TCP session is reestablished now */
break;
}
nls_codepage = load_nls_default();
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
if (tcon->ses->need_reconnect)
rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
if (!rc && (tcon->need_reconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
up(&tcon->ses->sesSem);
/* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size
shrinking */
if (rc == 0) {
atomic_inc(&tconInfoReconnectCount);
/* tell server Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX)
reset_cifs_unix_caps(
0 /* no xid */,
tcon,
NULL /* do not know sb */,
NULL /* no vol info */);
}
cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here.
It is safer (and faster) to reopen files
one at a time as needed in read and write */
/* Check if handle based operation so we
know whether we can continue or not without
returning to caller to reset file handle */
switch (smb_command) {
case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX:
case SMB_COM_CLOSE:
case SMB_COM_FIND_CLOSE2:
case SMB_COM_LOCKING_ANDX: {
unload_nls(nls_codepage);
return -EAGAIN;
}
}
} else {
up(&tcon->ses->sesSem);
}
unload_nls(nls_codepage);
} else {
return -EIO;
}
}
if (rc) if (rc)
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment