mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
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
1 changed files with 124 additions and 190 deletions
|
@ -100,6 +100,128 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
|
||||||
to this tcon */
|
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
|
/* 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
|
SMB information in the SMB header. If the return code is zero, this
|
||||||
function must have filled in request_buf pointer */
|
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;
|
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 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue