diff mbox

[linux-cifs-client] cifs: hard mount option behaviour implementation

Message ID 1275755825-6504-1-git-send-email-shirishpargaonkar@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Shirish Pargaonkar June 5, 2010, 4:37 p.m. UTC
None
diff mbox

Patch

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index fb1657e..7a475c5 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -63,12 +63,13 @@  extern char *cifs_compose_mount_options(const char *sb_mountdata,
 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
 			struct smb_hdr * /* input */ ,
 			struct smb_hdr * /* out */ ,
-			int * /* bytes returned */ , const int long_op);
+			int * /* bytes returned */ , const int long_op, bool);
 extern int SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
-			struct smb_hdr *in_buf, int flags);
+			struct smb_hdr *in_buf, int flags, bool hard_mount);
 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
 			struct kvec *, int /* nvec to send */,
-			int * /* type of buf returned */ , const int flags);
+			int * /* type of buf returned */ , const int flags,
+			bool);
 extern int SendReceiveBlockingLock(const unsigned int xid,
 			struct cifsTconInfo *ptcon,
 			struct smb_hdr *in_buf ,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c65c341..2634354 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -404,7 +404,7 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, false);
 	if (rc != 0)
 		goto neg_err_exit;
 
@@ -678,7 +678,7 @@  CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
 	if (rc)
 		return rc;
 
-	rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "Tree disconnect failed %d", rc);
 
@@ -725,7 +725,7 @@  CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
 	pSMB->hdr.Uid = ses->Suid;
 
 	pSMB->AndXCommand = 0xFF;
-	rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0, false);
 session_already_dead:
 	mutex_unlock(&ses->session_mutex);
 
@@ -799,7 +799,7 @@  PsxDelete:
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "Posix delete returned %d", rc);
 	cifs_buf_release(pSMB);
@@ -845,7 +845,7 @@  DelFileRetry:
 	pSMB->hdr.smb_buf_length += name_len + 1;
 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_deletes);
 	if (rc)
 		cFYI(1, "Error in RMFile = %d", rc);
@@ -889,7 +889,7 @@  RmDirRetry:
 	pSMB->hdr.smb_buf_length += name_len + 1;
 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_rmdirs);
 	if (rc)
 		cFYI(1, "Error in RMDir = %d", rc);
@@ -932,7 +932,7 @@  MkDirRetry:
 	pSMB->hdr.smb_buf_length += name_len + 1;
 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_mkdirs);
 	if (rc)
 		cFYI(1, "Error in Mkdir = %d", rc);
@@ -1010,7 +1010,7 @@  PsxCreat:
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Posix create returned %d", rc);
 		goto psx_create_err;
@@ -1177,7 +1177,8 @@  OldOpenRetry:
 	pSMB->ByteCount = cpu_to_le16(count);
 	/* long_op set to 1 to allow for oplock break timeouts */
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
+		(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP,
+		tcon->retry);
 	cifs_stats_inc(&tcon->num_opens);
 	if (rc) {
 		cFYI(1, "Error in Open = %d", rc);
@@ -1290,7 +1291,8 @@  openRetry:
 	pSMB->ByteCount = cpu_to_le16(count);
 	/* long_op set to 1 to allow for oplock break timeouts */
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
+		(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP,
+		tcon->retry);
 	cifs_stats_inc(&tcon->num_opens);
 	if (rc) {
 		cFYI(1, "Error in Open = %d", rc);
@@ -1372,7 +1374,7 @@  CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
 	iov[0].iov_base = (char *)pSMB;
 	iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
-			 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
+		 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR, tcon->retry);
 	cifs_stats_inc(&tcon->num_reads);
 	pSMBr = (READ_RSP *)iov[0].iov_base;
 	if (rc) {
@@ -1516,7 +1518,8 @@  CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
 	}
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
+		(struct smb_hdr *) pSMBr, &bytes_returned, long_op,
+		tcon->retry);
 	cifs_stats_inc(&tcon->num_writes);
 	if (rc) {
 		cFYI(1, "Send error in write = %d", rc);
@@ -1608,7 +1611,7 @@  CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 
 
 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
-			  long_op);
+			  long_op, tcon->retry);
 	cifs_stats_inc(&tcon->num_writes);
 	if (rc) {
 		cFYI(1, "Send error Write2 = %d", rc);
@@ -1699,7 +1702,7 @@  CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 		cifs_small_buf_release(pSMB);
 	} else {
 		rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
-				      timeout);
+				      timeout, tcon->retry);
 		/* SMB buffer freed by function above */
 	}
 	cifs_stats_inc(&tcon->num_locks);
@@ -1790,7 +1793,7 @@  CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 		iov[0].iov_base = (char *)pSMB;
 		iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
 		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
-				&resp_buf_type, timeout);
+				&resp_buf_type, timeout, false);
 		pSMB = NULL; /* request buf already freed by SendReceive2. Do
 				not try to free it twice below on exit */
 		pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
@@ -1866,7 +1869,8 @@  CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 	pSMB->FileID = (__u16) smb_file_id;
 	pSMB->LastWriteTime = 0xFFFFFFFF;
 	pSMB->ByteCount = 0;
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	cifs_stats_inc(&tcon->num_closes);
 	if (rc) {
 		if (rc != -EINTR) {
@@ -1895,7 +1899,8 @@  CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 
 	pSMB->FileID = (__u16) smb_file_id;
 	pSMB->ByteCount = 0;
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	cifs_stats_inc(&tcon->num_flushes);
 	if (rc)
 		cERROR(1, "Send error in Flush = %d", rc);
@@ -1958,7 +1963,7 @@  renameRetry:
 	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_renames);
 	if (rc)
 		cFYI(1, "Send error in rename = %d", rc);
@@ -2037,7 +2042,7 @@  int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, pTcon->retry);
 	cifs_stats_inc(&pTcon->num_t2renames);
 	if (rc)
 		cFYI(1, "Send error in Rename (by file handle) = %d", rc);
@@ -2105,7 +2110,7 @@  copyRetry:
 	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in copy = %d with %d files copied",
 			rc, le16_to_cpu(pSMBr->CopyCount));
@@ -2194,7 +2199,7 @@  createSymLinkRetry:
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_symlinks);
 	if (rc)
 		cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
@@ -2280,7 +2285,7 @@  createHardLinkRetry:
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_hardlinks);
 	if (rc)
 		cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
@@ -2352,7 +2357,7 @@  winCreateHardLinkRetry:
 	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_hardlinks);
 	if (rc)
 		cFYI(1, "Send error in hard link (NT rename) = %d", rc);
@@ -2423,7 +2428,7 @@  querySymLinkRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
 	} else {
@@ -2586,7 +2591,7 @@  CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
 	pSMB->ByteCount = 0;
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
 	} else {		/* decode response */
@@ -2849,7 +2854,7 @@  queryAclRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_acl_get);
 	if (rc) {
 		cFYI(1, "Send error in Query POSIX ACL = %d", rc);
@@ -2942,7 +2947,7 @@  setAclRetry:
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "Set POSIX ACL returned %d", rc);
 
@@ -3001,7 +3006,7 @@  GetExtAttrRetry:
 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "error %d in GetExtAttr", rc);
 	} else {
@@ -3070,7 +3075,7 @@  CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
 	iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
 
 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
-			 CIFS_STD_OP);
+			 CIFS_STD_OP, tcon->retry);
 	cifs_stats_inc(&tcon->num_acl_get);
 	if (rc) {
 		cFYI(1, "Send error in QuerySecDesc = %d", rc);
@@ -3182,7 +3187,7 @@  setCifsAclRetry:
 		pSMB->hdr.smb_buf_length += byte_count;
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 
 	cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
 	if (rc)
@@ -3234,7 +3239,7 @@  QInfRetry:
 	pSMB->ByteCount = cpu_to_le16(name_len);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QueryInfo = %d", rc);
 	} else if (pFinfo) {
@@ -3308,7 +3313,7 @@  QFileInfoRetry:
 	pSMB->hdr.smb_buf_length += byte_count;
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QPathInfo = %d", rc);
 	} else {		/* decode response */
@@ -3396,7 +3401,7 @@  QPathInfoRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QPathInfo = %d", rc);
 	} else {		/* decode response */
@@ -3476,7 +3481,7 @@  UnixQFileInfoRetry:
 	pSMB->hdr.smb_buf_length += byte_count;
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QPathInfo = %d", rc);
 	} else {		/* decode response */
@@ -3562,7 +3567,7 @@  UnixQPathInfoRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QPathInfo = %d", rc);
 	} else {		/* decode response */
@@ -3676,7 +3681,7 @@  findFirstRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_ffirst);
 
 	if (rc) {/* BB add logic to retry regular search if Unix search
@@ -3805,7 +3810,7 @@  int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	cifs_stats_inc(&tcon->num_fnext);
 	if (rc) {
 		if (rc == -EBADF) {
@@ -3894,7 +3899,8 @@  CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
 
 	pSMB->FileID = searchHandle;
 	pSMB->ByteCount = 0;
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	if (rc)
 		cERROR(1, "Send error in FindClose = %d", rc);
 
@@ -3967,7 +3973,7 @@  GetInodeNumberRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "error %d in QueryInternalInfo", rc);
 	} else {
@@ -4191,7 +4197,7 @@  getDFSRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, false);
 	if (rc) {
 		cFYI(1, "Send error in GetDFSRefer = %d", rc);
 		goto GetDFSRefExit;
@@ -4265,7 +4271,7 @@  oldQFSInfoRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QFSInfo = %d", rc);
 	} else {                /* decode response */
@@ -4344,7 +4350,7 @@  QFSInfoRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QFSInfo = %d", rc);
 	} else {		/* decode response */
@@ -4424,7 +4430,7 @@  QFSAttributeRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
 	} else {		/* decode response */
@@ -4495,7 +4501,7 @@  QFSDeviceRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
 	} else {		/* decode response */
@@ -4564,7 +4570,7 @@  QFSUnixRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cERROR(1, "Send error in QFSUnixInfo = %d", rc);
 	} else {		/* decode response */
@@ -4647,7 +4653,7 @@  SETFSUnixRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
 	} else {		/* decode response */
@@ -4709,7 +4715,7 @@  QFSPosixRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QFSUnixInfo = %d", rc);
 	} else {		/* decode response */
@@ -4835,7 +4841,7 @@  SetEOFRetry:
 	parm_data->FileSize = cpu_to_le64(size);
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "SetPathInfo (file size) returned %d", rc);
 
@@ -4915,7 +4921,8 @@  CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
 	pSMB->Reserved4 = 0;
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
 	}
@@ -4984,7 +4991,8 @@  CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	if (rc)
 		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
 
@@ -5043,7 +5051,8 @@  CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	*data_offset = delete_file ? 1 : 0;
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	if (rc)
 		cFYI(1, "Send error in SetFileDisposition = %d", rc);
 
@@ -5117,7 +5126,7 @@  SetTimesRetry:
 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "SetPathInfo (times) returned %d", rc);
 
@@ -5275,7 +5284,8 @@  CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
 
 	cifs_fill_unix_set_info(data_offset, args);
 
-	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+	rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0,
+				tcon->retry);
 	if (rc)
 		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
 
@@ -5352,7 +5362,7 @@  setPermsRetry:
 
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "SetPathInfo (perms) returned %d", rc);
 
@@ -5404,8 +5414,8 @@  int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
 	pSMB->ByteCount = 0;
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *)pSMBr, &bytes_returned,
-			 CIFS_ASYNC_OP);
+		(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_ASYNC_OP,
+		tcon->retry);
 	if (rc) {
 		cFYI(1, "Error in Notify = %d", rc);
 	} else {
@@ -5508,7 +5518,7 @@  QAllEAsRetry:
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc) {
 		cFYI(1, "Send error in QueryAllEAs = %d", rc);
 		goto QAllEAsOut;
@@ -5720,7 +5730,7 @@  SetEARetry:
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+		 (struct smb_hdr *) pSMBr, &bytes_returned, 0, tcon->retry);
 	if (rc)
 		cFYI(1, "SetPathInfo (EA) returned %d", rc);
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2208f06..7ddc602 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1809,6 +1809,9 @@  cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
 		}
 	}
 
+	if (volume_info->retry)
+		tcon->retry = volume_info->retry;
+
 	if (strchr(volume_info->UNC + 3, '\\') == NULL
 	    && strchr(volume_info->UNC + 3, '/') == NULL) {
 		cERROR(1, "Missing share name");
@@ -2807,7 +2810,7 @@  CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
-			 CIFS_STD_OP);
+			 CIFS_STD_OP, false);
 
 	/* above now done in SendReceive */
 	if ((rc == 0) && (tcon != NULL)) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7707389..ff0dfb7 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -866,7 +866,7 @@  ssetup_ntlmssp_authenticate:
 	BCC_LE(smb_buf) = cpu_to_le16(count);
 
 	rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type,
-			  CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
+		  CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR, false);
 	/* SMB request buf freed in SendReceive2 */
 
 	cFYI(1, "ssetup rc from sendrecv2 is %d", rc);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 82f78c4..0c7a07e 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -311,6 +311,44 @@  static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
 	return 0;
 }
 
+static int
+wait_for_response_hard(struct cifsSesInfo *ses, struct mid_q_entry *midQ)
+{
+	int rc;
+	bool cmdresp = true;
+	unsigned long timeout = 60 * HZ;
+	unsigned long curr_timeout;
+
+wait_again:
+	curr_timeout = timeout + jiffies;
+	rc = wait_event_interruptible_timeout(ses->server->response_q,
+			(midQ->midState != MID_REQUEST_SUBMITTED), timeout);
+
+	if (rc < 0) {
+		cFYI(1, "command 0x%x interrupted", midQ->command);
+		return -1;
+	}
+	if (!time_before(jiffies, curr_timeout)) {
+		cmdresp = false;
+		cFYI(1, "server not responding...");
+		goto wait_again;
+	}
+	spin_lock(&GlobalMid_Lock);
+	if (midQ->midState != MID_REQUEST_SUBMITTED) {
+		if (midQ->midState == MID_RESPONSE_RECEIVED) {
+			if (!cmdresp)
+				cFYI(1, "server is ok...");
+			rc = 0;
+		} else {
+			cFYI(1, "command 0x%x aborted", midQ->command);
+			rc = -1;
+		}
+	}
+	spin_unlock(&GlobalMid_Lock);
+	return rc;
+}
+
+
 static int wait_for_response(struct cifsSesInfo *ses,
 			struct mid_q_entry *midQ,
 			unsigned long timeout,
@@ -367,7 +405,7 @@  static int wait_for_response(struct cifsSesInfo *ses,
  */
 int
 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
-		struct smb_hdr *in_buf, int flags)
+		struct smb_hdr *in_buf, int flags, bool hard_mount)
 {
 	int rc;
 	struct kvec iov[1];
@@ -376,7 +414,7 @@  SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
 	iov[0].iov_base = (char *)in_buf;
 	iov[0].iov_len = in_buf->smb_buf_length + 4;
 	flags |= CIFS_NO_RESP;
-	rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
+	rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, hard_mount);
 	cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
 
 	return rc;
@@ -385,7 +423,7 @@  SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
 int
 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 	     struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
-	     const int flags)
+	     const int flags, bool hard_mount)
 {
 	int rc = 0;
 	int long_op;
@@ -483,7 +521,12 @@  SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 	}
 
 	/* No user interrupts in wait - wreaks havoc with performance */
-	wait_for_response(ses, midQ, timeout, 10 * HZ);
+	if (hard_mount) {
+		rc = wait_for_response_hard(ses, midQ);
+		if (rc)
+			goto out;
+	} else
+		wait_for_response(ses, midQ, timeout, 10 * HZ);
 
 	spin_lock(&GlobalMid_Lock);
 
@@ -581,7 +624,7 @@  out:
 int
 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
-	    int *pbytes_returned, const int long_op)
+	    int *pbytes_returned, const int long_op, bool hard_mount)
 {
 	int rc = 0;
 	unsigned int receive_len;
@@ -675,7 +718,12 @@  SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 	}
 
 	/* No user interrupts in wait - wreaks havoc with performance */
-	wait_for_response(ses, midQ, timeout, 10 * HZ);
+	if (hard_mount) {
+		rc = wait_for_response_hard(ses, midQ);
+		if (rc)
+			goto out;
+	} else
+		wait_for_response(ses, midQ, timeout, 10 * HZ);
 
 	spin_lock(&GlobalMid_Lock);
 	if (midQ->resp_buf == NULL) {
@@ -807,7 +855,7 @@  send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
 	pSMB->hdr.Mid = GetNextMid(ses->server);
 
 	return SendReceive(xid, ses, in_buf, out_buf,
-			&bytes_returned, CIFS_STD_OP);
+			&bytes_returned, CIFS_STD_OP, tcon->retry);
 }
 
 int