Commit 720ecfed authored by Steve French's avatar Steve French Committed by Steve French

Missing soft vs. hard retry mount option

parent cb8baa9c
...@@ -55,6 +55,10 @@ ...@@ -55,6 +55,10 @@
#define TRUE 1 #define TRUE 1
#endif #endif
#ifndef XATTR_DOS_ATTRIB
#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
#endif
/* /*
* This information is kept on every Server we know about. * This information is kept on every Server we know about.
* *
...@@ -182,6 +186,7 @@ struct cifsTconInfo { ...@@ -182,6 +186,7 @@ struct cifsTconInfo {
FILE_SYSTEM_DEVICE_INFO fsDevInfo; FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
FILE_SYSTEM_UNIX_INFO fsUnixInfo; FILE_SYSTEM_UNIX_INFO fsUnixInfo;
int retry:1;
/* BB add field for back pointer to sb struct? */ /* BB add field for back pointer to sb struct? */
}; };
......
...@@ -78,16 +78,23 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -78,16 +78,23 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(tcon) { if(tcon) {
if((tcon->ses) && (tcon->ses->server)){ if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage = load_nls_default(); struct nls_table *nls_codepage = load_nls_default();
if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
/* Give Demultiplex thread up to 10 seconds to /* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket reconnect, should be greater than cifs socket
timeout which is 7 seconds */ timeout which is 7 seconds */
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q, wait_event_interruptible_timeout(tcon->ses->server->response_q,
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
unload_nls(nls_codepage); /* on "soft" mounts we wait once */
return -EHOSTDOWN; if((tcon->retry == FALSE) ||
} (tcon->ses->status == CifsExiting)) {
unload_nls(nls_codepage);
return -EHOSTDOWN;
} /* else "hard" mount - keep retrying until
process is killed or server comes back up */
} else /* TCP session is reestablished now */
break;
} }
/* need to prevent multiple threads trying to /* need to prevent multiple threads trying to
...@@ -163,7 +170,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -163,7 +170,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
rc = -EIO; rc = -EIO;
return rc; return rc;
} }
NegotiateRetry:
rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ , rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
(void **) &pSMB, (void **) &pSMBr); (void **) &pSMB, (void **) &pSMBr);
if (rc) if (rc)
...@@ -253,8 +259,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -253,8 +259,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
} }
if (pSMB) if (pSMB)
buf_release(pSMB); buf_release(pSMB);
if (rc == -EAGAIN)
goto NegotiateRetry;
return rc; return rc;
} }
......
...@@ -58,7 +58,8 @@ struct smb_vol { ...@@ -58,7 +58,8 @@ struct smb_vol {
gid_t linux_gid; gid_t linux_gid;
mode_t file_mode; mode_t file_mode;
mode_t dir_mode; mode_t dir_mode;
int rw; int rw:1;
int retry:1;
unsigned int rsize; unsigned int rsize;
unsigned int wsize; unsigned int wsize;
unsigned int sockopt; unsigned int sockopt;
...@@ -386,6 +387,7 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol) ...@@ -386,6 +387,7 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
/* 2767 perms indicate mandatory locking support */ /* 2767 perms indicate mandatory locking support */
vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = TRUE; vol->rw = TRUE;
if (!options) if (!options)
...@@ -530,6 +532,14 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol) ...@@ -530,6 +532,14 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
vol->rw = TRUE; vol->rw = TRUE;
} else if (strnicmp(data, "ro", 2) == 0) { } else if (strnicmp(data, "ro", 2) == 0) {
vol->rw = FALSE; vol->rw = FALSE;
} else if (strnicmp(data, "hard", 4) == 0) {
vol->retry = 1;
} else if (strnicmp(data, "soft", 4) == 0) {
vol->retry = 0;
} else if (strnicmp(data, "nohard", 6) == 0) {
vol->retry = 0;
} else if (strnicmp(data, "nosoft", 6) == 0) {
vol->retry = 1;
} else } else
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data); printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
} }
...@@ -695,8 +705,14 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab ...@@ -695,8 +705,14 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
int ntlmv2_flag = FALSE; int ntlmv2_flag = FALSE;
/* what if server changes its buffer size after dropping the session? */ /* what if server changes its buffer size after dropping the session? */
if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
rc = CIFSSMBNegotiate(xid, pSesInfo); rc = CIFSSMBNegotiate(xid, pSesInfo);
if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
rc = CIFSSMBNegotiate(xid, pSesInfo);
if(rc == -EAGAIN)
rc = -EHOSTDOWN;
}
}
pSesInfo->capabilities = pSesInfo->server->capabilities; pSesInfo->capabilities = pSesInfo->server->capabilities;
pSesInfo->sequence_number = 0; pSesInfo->sequence_number = 0;
if (!rc) { if (!rc) {
...@@ -1036,6 +1052,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1036,6 +1052,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
volume_info.username); volume_info.username);
if (tcon) { if (tcon) {
cFYI(1, ("Found match on UNC path ")); cFYI(1, ("Found match on UNC path "));
/* we can have only one retry value for a connection
to a share so for resources mounted more than once
to the same server share the last value passed in
for the retry flag is used */
tcon->retry = volume_info.retry;
} else { } else {
tcon = tconInfoAlloc(); tcon = tconInfoAlloc();
if (tcon == NULL) if (tcon == NULL)
...@@ -1062,8 +1083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1062,8 +1083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
tcon, cifs_sb->local_nls); tcon, cifs_sb->local_nls);
cFYI(1, ("CIFS Tcon rc = %d", rc)); cFYI(1, ("CIFS Tcon rc = %d", rc));
} }
if (!rc) if (!rc) {
atomic_inc(&pSesInfo->inUse); atomic_inc(&pSesInfo->inUse);
tcon->retry = volume_info.retry;
}
} }
} }
} }
......
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