mirror of https://gitee.com/openkylin/linux.git
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: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
6ab409b53d
commit
9162ab2000
|
@ -100,6 +100,128 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
|
|||
to this tcon */
|
||||
}
|
||||
|
||||
/* reconnect the socket, tcon, and smb session if needed */
|
||||
static int
|
||||
cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
|
||||
{
|
||||
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 for those three - in the
|
||||
* 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 (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 (ses->status == CifsExiting)
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* Give demultiplex thread up to 10 seconds to reconnect, should be
|
||||
* greater than cifs socket timeout which is 7 seconds
|
||||
*/
|
||||
while (server->tcpStatus == CifsNeedReconnect) {
|
||||
wait_event_interruptible_timeout(server->response_q,
|
||||
(server->tcpStatus == CifsGood), 10 * HZ);
|
||||
|
||||
/* is TCP session is reestablished now ?*/
|
||||
if (server->tcpStatus != CifsNeedReconnect)
|
||||
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();
|
||||
|
||||
/*
|
||||
* need to prevent multiple threads trying to simultaneously
|
||||
* reconnect the same SMB session
|
||||
*/
|
||||
down(&ses->sesSem);
|
||||
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);
|
||||
rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
|
||||
up(&ses->sesSem);
|
||||
cFYI(1, ("reconnect tcon rc = %d", rc));
|
||||
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* FIXME: check if wsize needs updated due to negotiated smb buffer
|
||||
* size shrinking
|
||||
*/
|
||||
atomic_inc(&tconInfoReconnectCount);
|
||||
|
||||
/* tell server Unix caps we support */
|
||||
if (ses->capabilities & CAP_UNIX)
|
||||
reset_cifs_unix_caps(0, tcon, NULL, NULL);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* FIXME: what about file locks? don't we need to reclaim them ASAP?
|
||||
*/
|
||||
|
||||
out:
|
||||
/*
|
||||
* 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:
|
||||
rc = -EAGAIN;
|
||||
}
|
||||
|
||||
unload_nls(nls_codepage);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Allocate and return pointer to an SMB request buffer, and set basic
|
||||
SMB information in the SMB header. If the return code is zero, this
|
||||
function must have filled in request_buf pointer */
|
||||
|
@ -109,101 +231,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
|||
{
|
||||
int rc = 0;
|
||||
|
||||
/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
|
||||
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 back 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 /* we 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;
|
||||
}
|
||||
}
|
||||
rc = cifs_reconnect_tcon(tcon, smb_command);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -256,101 +284,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
|||
{
|
||||
int rc = 0;
|
||||
|
||||
/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
|
||||
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;
|
||||
}
|
||||
}
|
||||
rc = cifs_reconnect_tcon(tcon, smb_command);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
Loading…
Reference in New Issue