Commit bb550c6e authored by Steve French's avatar Steve French Committed by Steve French

fixes for socket retry and error handling of misc. error paths

parent 38aad1bc
Version 1.12
------------
Fixes for large file copy, signal handling, socket retry, buffer
allocation and low memory situations.
Version 1.11 Version 1.11
------------ ------------
Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize) also Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
now allowing support for specifying client netbiosname. NT4 support added. also now allowing support for specifying client netbiosname. NT4 support added.
Version 1.10 Version 1.10
------------ ------------
......
...@@ -1509,7 +1509,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -1509,7 +1509,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
TRANSACTION2_QPI_REQ *pSMB = NULL; TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL; TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0; int rc = 0;
int bytes_returned; int bytes_returned = 0;
int name_len; int name_len;
cFYI(1, ("In QPathInfo (Unix) the path %s", searchName)); cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
...@@ -1565,9 +1565,13 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -1565,9 +1565,13 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
} else { /* decode response */ } else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
/* BB also check if enough total bytes returned */ /* BB also check if enough total bytes returned */
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO) + sizeof(FILE_UNIX_BASIC_INFO)) ||
(pSMBr->DataOffset > 512) ||
(pSMBr->DataOffset < sizeof(struct smb_hdr))) {
cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
(int)pSMBr->DataOffset,bytes_returned));
rc = -EIO; /* bad smb */ rc = -EIO; /* bad smb */
else { } else {
memcpy((char *) pFindData, memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol + (char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset, pSMBr->DataOffset,
......
...@@ -201,9 +201,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -201,9 +201,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
memset(smb_buffer, 0, sizeof (struct smb_hdr)); memset(smb_buffer, 0, sizeof (struct smb_hdr));
if (smb_buffer == NULL) { if (smb_buffer == NULL) {
cERROR(1, cERROR(1,("Can not get memory for SMB response"));
("Can not get mem for SMB response buffer ")); set_current_state(TASK_INTERRUPTIBLE);
return -ENOMEM; schedule_timeout(HZ * 3); /* give system time to free memory */
continue;
} }
iov.iov_base = smb_buffer; iov.iov_base = smb_buffer;
iov.iov_len = sizeof (struct smb_hdr) - 1; iov.iov_len = sizeof (struct smb_hdr) - 1;
......
...@@ -1362,6 +1362,11 @@ static void reset_resume_key(struct file * dir_file, ...@@ -1362,6 +1362,11 @@ static void reset_resume_key(struct file * dir_file,
cifsFile->search_resume_name = cifsFile->search_resume_name =
kmalloc(cifsFile->resume_name_length, GFP_KERNEL); kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
if(cifsFile->search_resume_name == NULL) {
cERROR(1,("failed new resume key allocate, length %d",
cifsFile->resume_name_length));
return;
}
if(Unicode) if(Unicode)
cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name, cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
filename, len, nls_tab); filename, len, nls_tab);
......
...@@ -149,19 +149,25 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -149,19 +149,25 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
temp_fs = get_fs(); /* we must turn off socket api parm checking */ temp_fs = get_fs(); /* we must turn off socket api parm checking */
set_fs(get_ds()); set_fs(get_ds());
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4); while(iov.iov_len > 0) {
while((rc == -ENOSPC) || (rc == -EAGAIN)) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/2);
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4); rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/2);
continue;
}
if (rc < 0)
break;
iov.iov_base += rc;
iov.iov_len -= rc;
} }
set_fs(temp_fs); set_fs(temp_fs);
if (rc < 0) { if (rc < 0) {
cERROR(1, cERROR(1,("Error %d sending data on socket to server.", rc));
("Error %d sending data on socket to server.", rc)); } else {
} else
rc = 0; rc = 0;
}
return rc; return rc;
} }
...@@ -239,7 +245,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -239,7 +245,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
but we still give response a change to complete */ but we still give response a change to complete */
if(midQ->midState & MID_REQUEST_SUBMITTED) { if(midQ->midState & MID_REQUEST_SUBMITTED) {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
timeout = schedule_timeout(2 * HZ); timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
} }
} else { /* using normal timeout */ } else { /* using normal timeout */
/* timeout = wait_event_interruptible_timeout(ses->server->response_q, /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
...@@ -250,44 +256,38 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -250,44 +256,38 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
/* Can not allow user interrupts- wreaks havoc with performance */ /* Can not allow user interrupts- wreaks havoc with performance */
if(midQ->midState & MID_REQUEST_SUBMITTED) { if(midQ->midState & MID_REQUEST_SUBMITTED) {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
timeout = schedule_timeout(timeout); timeout = sleep_on_timeout(&ses->server->response_q,timeout);
} }
} }
if (signal_pending(current)) {
if (midQ->resp_buf == NULL) spin_lock(&GlobalMid_Lock);
rc = -EINTR; /* BB are we supposed to return -ERESTARTSYS ? */ if (midQ->resp_buf) {
DeleteMidQEntry(midQ); spin_unlock(&GlobalMid_Lock);
return rc; /* why bother returning an error if it succeeded */ receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
} else { /* BB spinlock protect this against races with demux thread */ } else {
spin_lock(&GlobalMid_Lock); cERROR(1,("No response buffer"));
if (midQ->resp_buf) { if(midQ->midState == MID_REQUEST_SUBMITTED) {
spin_unlock(&GlobalMid_Lock); if(ses->server->tcpStatus == CifsExiting)
receive_len = rc = -EHOSTDOWN;
be32_to_cpu(midQ->resp_buf->smb_buf_length); else {
} else { ses->server->tcpStatus = CifsNeedReconnect;
cFYI(1,("No response buffer")); midQ->midState = MID_RETRY_NEEDED;
if(midQ->midState == MID_REQUEST_SUBMITTED) {
if(ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN;
else {
ses->server->tcpStatus = CifsNeedReconnect;
midQ->midState = MID_RETRY_NEEDED;
}
} }
}
if (rc != -EHOSTDOWN) { if (rc != -EHOSTDOWN) {
if(midQ->midState == MID_RETRY_NEEDED) { if(midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN; rc = -EAGAIN;
cFYI(1,("marking request for retry")); cFYI(1,("marking request for retry"));
} else { } else {
rc = -EIO; rc = -EIO;
}
} }
spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ);
return rc;
} }
spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ);
return rc;
} }
if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1, cERROR(1,
......
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