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 @@
#define TRUE 1
#endif
#ifndef XATTR_DOS_ATTRIB
#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
#endif
/*
* This information is kept on every Server we know about.
*
......@@ -182,6 +186,7 @@ struct cifsTconInfo {
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
int retry:1;
/* BB add field for back pointer to sb struct? */
};
......
......@@ -78,16 +78,23 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(tcon) {
if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage = load_nls_default();
if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
/* 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) {
unload_nls(nls_codepage);
return -EHOSTDOWN;
}
/* on "soft" mounts we wait once */
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
......@@ -163,7 +170,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
rc = -EIO;
return rc;
}
NegotiateRetry:
rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
(void **) &pSMB, (void **) &pSMBr);
if (rc)
......@@ -253,8 +259,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
}
if (pSMB)
buf_release(pSMB);
if (rc == -EAGAIN)
goto NegotiateRetry;
return rc;
}
......
......@@ -58,7 +58,8 @@ struct smb_vol {
gid_t linux_gid;
mode_t file_mode;
mode_t dir_mode;
int rw;
int rw:1;
int retry:1;
unsigned int rsize;
unsigned int wsize;
unsigned int sockopt;
......@@ -386,6 +387,7 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
/* 2767 perms indicate mandatory locking support */
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;
if (!options)
......@@ -530,6 +532,14 @@ parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
vol->rw = TRUE;
} else if (strnicmp(data, "ro", 2) == 0) {
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
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
int ntlmv2_flag = FALSE;
/* 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);
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->sequence_number = 0;
if (!rc) {
......@@ -1036,6 +1052,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
volume_info.username);
if (tcon) {
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 {
tcon = tconInfoAlloc();
if (tcon == NULL)
......@@ -1062,8 +1083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
tcon, cifs_sb->local_nls);
cFYI(1, ("CIFS Tcon rc = %d", rc));
}
if (!rc)
if (!rc) {
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