From patchwork Sun Jul 24 14:59:45 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 1003032 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6OF09EB015623 for ; Sun, 24 Jul 2011 15:00:12 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752749Ab1GXPAL (ORCPT ); Sun, 24 Jul 2011 11:00:11 -0400 Received: from mail-fx0-f52.google.com ([209.85.161.52]:49515 "EHLO mail-fx0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752839Ab1GXPAK (ORCPT ); Sun, 24 Jul 2011 11:00:10 -0400 Received: by mail-fx0-f52.google.com with SMTP id 18so7679812fxd.11 for ; Sun, 24 Jul 2011 08:00:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; bh=IThzd/YqUntv0q7WgnSuiMo9BtWuxa/A4q7tXdwA+1M=; b=AnYyWux5Fu4PyrAzuJuvnw2C9Osv9ljqQkS+8Z+O3EP0Wqlwfn/Zp7ibi4qHVLpzqt MBJa2xhmhAjtsjl0uaAiypSZWzkc/yq7kqyrHhyflg3c5C8EpW7JYgtuzwOVZo2XZShp Cwtmenl/S8vr3FigW27BDoC2SCxxOlhMMJ09k= Received: by 10.204.23.201 with SMTP id s9mr1086102bkb.326.1311519610054; Sun, 24 Jul 2011 08:00:10 -0700 (PDT) Received: from localhost.localdomain ([85.26.232.196]) by mx.google.com with ESMTPS id p24sm299970bkw.41.2011.07.24.08.00.06 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 24 Jul 2011 08:00:09 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [v4 PATCH 2/5] CIFS: Simplify socket reading in demultiplex thread Date: Sun, 24 Jul 2011 18:59:45 +0400 Message-Id: <1311519588-2457-2-git-send-email-piastryyy@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1311519588-2457-1-git-send-email-piastryyy@gmail.com> References: <1311519588-2457-1-git-send-email-piastryyy@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sun, 24 Jul 2011 15:00:12 +0000 (UTC) Move reading to separate function and remove csocket variable. Also change semantic in a little: goto incomplete_rcv only when we get -EAGAIN (or a familiar error) while reading rfc1002 header. In this case we don't check for echo timeout when we don't get whole header at once, as it was before. Signed-off-by: Pavel Shilovsky --- fs/cifs/connect.c | 154 ++++++++++++++++++++++++---------------------------- 1 files changed, 71 insertions(+), 83 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 86bdc34..e8a1d64 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -359,6 +359,64 @@ allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size, } static int +read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg, + struct kvec *iov, unsigned int to_read, + unsigned int *ptotal_read, bool is_header_read) +{ + int length, rc = 0; + unsigned int total_read; + char *buf = iov->iov_base; + + for (total_read = 0; total_read < to_read; total_read += length) { + length = kernel_recvmsg(server->ssocket, smb_msg, iov, 1, + to_read - total_read, 0); + if (server->tcpStatus == CifsExiting) { + /* then will exit */ + rc = 2; + break; + } else if (server->tcpStatus == CifsNeedReconnect) { + cifs_reconnect(server); + /* Reconnect wakes up rspns q */ + /* Now we will reread sock */ + rc = 1; + break; + } else if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { + /* + * Minimum sleep to prevent looping, allowing socket + * to clear and app threads to set tcpStatus + * CifsNeedReconnect if server hung. + */ + usleep_range(1000, 2000); + length = 0; + if (!is_header_read) + continue; + /* Special handling for header read */ + if (total_read) { + iov->iov_base = (to_read - total_read) + + buf; + iov->iov_len = to_read - total_read; + smb_msg->msg_control = NULL; + smb_msg->msg_controllen = 0; + rc = 3; + } else + rc = 1; + break; + } else if (length <= 0) { + cERROR(1, "Received no data, expecting %d", + to_read - total_read); + cifs_reconnect(server); + rc = 1; + break; + } + } + + *ptotal_read = total_read; + return rc; +} + +static int cifs_demultiplex_thread(struct TCP_Server_Info *server) { int length; @@ -367,14 +425,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct smb_hdr *smb_buffer = NULL; struct msghdr smb_msg; struct kvec iov; - struct socket *csocket = server->ssocket; struct list_head *tmp, *tmp2; struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; char temp; bool isLargeBuf = false; bool isMultiRsp; - int reconnect; + int rc; current->flags |= PF_MEMALLOC; cFYI(1, "Demultiplex PID: %d", task_pid_nr(current)); @@ -411,51 +468,18 @@ incomplete_rcv: "Reconnecting...", server->hostname, (echo_retries * SMB_ECHO_INTERVAL / HZ)); cifs_reconnect(server); - csocket = server->ssocket; wake_up(&server->response_q); continue; } - length = - kernel_recvmsg(csocket, &smb_msg, - &iov, 1, pdu_length, 0 /* BB other flags? */); - - if (server->tcpStatus == CifsExiting) { + rc = read_from_socket(server, &smb_msg, &iov, pdu_length, + &total_read, true /* header read */); + if (rc == 3) + goto incomplete_rcv; + else if (rc == 2) break; - } else if (server->tcpStatus == CifsNeedReconnect) { - cFYI(1, "Reconnect after server stopped responding"); - cifs_reconnect(server); - cFYI(1, "call to reconnect done"); - csocket = server->ssocket; - continue; - } else if (length == -ERESTARTSYS || - length == -EAGAIN || - length == -EINTR) { - msleep(1); /* minimum sleep to prevent looping - allowing socket to clear and app threads to set - tcpStatus CifsNeedReconnect if server hung */ - if (pdu_length < 4) { - iov.iov_base = (4 - pdu_length) + buf; - iov.iov_len = pdu_length; - smb_msg.msg_control = NULL; - smb_msg.msg_controllen = 0; - goto incomplete_rcv; - } else - continue; - } else if (length <= 0) { - cFYI(1, "Reconnect after unexpected peek error %d", - length); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); + else if (rc == 1) continue; - } else if (length < pdu_length) { - cFYI(1, "requested %d bytes but only got %d bytes", - pdu_length, length); - pdu_length -= length; - msleep(1); - goto incomplete_rcv; - } /* The right amount was read from socket - 4 bytes */ /* so we can now interpret the length field */ @@ -492,14 +516,12 @@ incomplete_rcv: cifs_set_port((struct sockaddr *) &server->dstaddr, CIFS_PORT); cifs_reconnect(server); - csocket = server->ssocket; wake_up(&server->response_q); continue; } else if (temp != (char) 0) { cERROR(1, "Unknown RFC 1002 frame"); cifs_dump_mem(" Received Data: ", buf, length); cifs_reconnect(server); - csocket = server->ssocket; continue; } @@ -509,59 +531,25 @@ incomplete_rcv: cERROR(1, "Invalid size SMB length %d pdu_length %d", length, pdu_length+4); cifs_reconnect(server); - csocket = server->ssocket; wake_up(&server->response_q); continue; } /* else length ok */ - reconnect = 0; - if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { isLargeBuf = true; memcpy(bigbuf, smallbuf, 4); smb_buffer = (struct smb_hdr *)bigbuf; buf = bigbuf; } - length = 0; + iov.iov_base = 4 + buf; iov.iov_len = pdu_length; - for (total_read = 0; total_read < pdu_length; - total_read += length) { - length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, - pdu_length - total_read, 0); - if (server->tcpStatus == CifsExiting) { - /* then will exit */ - reconnect = 2; - break; - } else if (server->tcpStatus == CifsNeedReconnect) { - cifs_reconnect(server); - csocket = server->ssocket; - /* Reconnect wakes up rspns q */ - /* Now we will reread sock */ - reconnect = 1; - break; - } else if (length == -ERESTARTSYS || - length == -EAGAIN || - length == -EINTR) { - msleep(1); /* minimum sleep to prevent looping, - allowing socket to clear and app - threads to set tcpStatus - CifsNeedReconnect if server hung*/ - length = 0; - continue; - } else if (length <= 0) { - cERROR(1, "Received no data, expecting %d", - pdu_length - total_read); - cifs_reconnect(server); - csocket = server->ssocket; - reconnect = 1; - break; - } - } - if (reconnect == 2) + rc = read_from_socket(server, &smb_msg, &iov, pdu_length, + &total_read, false); + if (rc == 2) break; - else if (reconnect == 1) + else if (rc == 1) continue; total_read += 4; /* account for rfc1002 hdr */ @@ -704,7 +692,7 @@ multi_t2_fnd: msleep(125); if (server->ssocket) { - sock_release(csocket); + sock_release(server->ssocket); server->ssocket = NULL; } /* buffer usually freed in free_mid - need to free it here on exit */