From patchwork Wed Jul 6 10:27:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 949362 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p66AS0dM000882 for ; Wed, 6 Jul 2011 10:28:01 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751894Ab1GFK2B (ORCPT ); Wed, 6 Jul 2011 06:28:01 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:39540 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751621Ab1GFK2A (ORCPT ); Wed, 6 Jul 2011 06:28:00 -0400 Received: by mail-bw0-f46.google.com with SMTP id 5so5446214bwd.19 for ; Wed, 06 Jul 2011 03:27:59 -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=NIx0a4cpJCQI3ZUPT/ZT07zApPv6wouJHITXh+vAVNM=; b=vDrujzqTsFE6MpgRQ0ecm5rb2my/qOJs40UQnw32M5cbtouZwK1Itp9m9kW1hmuHa1 7abJCbE9d5smvrSXrLAona/Q7icZEiUzJKcD2anQillVmE62LAtM+TUb1DnPXCgOG3N3 Q18rVP4lNuTXHnIFqAi6BZwq5KPS27MMQSpyQ= Received: by 10.204.82.72 with SMTP id a8mr1634675bkl.84.1309948079664; Wed, 06 Jul 2011 03:27:59 -0700 (PDT) Received: from localhost.localdomain ([95.84.31.191]) by mx.google.com with ESMTPS id f16sm1613995bke.16.2011.07.06.03.27.57 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 06 Jul 2011 03:27:58 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [v3 5/5] CIFS: Cleanup demupltiplex thread exiting code Date: Wed, 6 Jul 2011 14:27:39 +0400 Message-Id: <1309948059-29704-6-git-send-email-piastryyy@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1309948059-29704-1-git-send-email-piastryyy@gmail.com> References: <1309948059-29704-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 (demeter2.kernel.org [140.211.167.43]); Wed, 06 Jul 2011 10:28:01 +0000 (UTC) Signed-off-by: Pavel Shilovsky --- fs/cifs/connect.c | 173 +++++++++++++++++++++++++++++----------------------- 1 files changed, 96 insertions(+), 77 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a393002..d2a0f51 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -529,6 +529,101 @@ multi_t2_fnd: return ret; } +static void clean_demultiplex_info(struct TCP_Server_Info *server) +{ + int length; + + /* take it off the list, if it's not already */ + spin_lock(&cifs_tcp_ses_lock); + list_del_init(&server->tcp_ses_list); + spin_unlock(&cifs_tcp_ses_lock); + + spin_lock(&GlobalMid_Lock); + server->tcpStatus = CifsExiting; + spin_unlock(&GlobalMid_Lock); + wake_up_all(&server->response_q); + + /* + * Check if we have blocked requests that need to free. Note that + * cifs_max_pending is normally 50, but can be set at module install + * time to as little as two. + */ + spin_lock(&GlobalMid_Lock); + if (atomic_read(&server->inFlight) >= cifs_max_pending) + atomic_set(&server->inFlight, cifs_max_pending - 1); + /* + * We do not want to set the max_pending too low or we could end up + * with the counter going negative. + */ + spin_unlock(&GlobalMid_Lock); + /* + * Although there should not be any requests blocked on this queue it + * can not hurt to be paranoid and try to wake up requests that may + * haven been blocked when more than 50 at time were on the wire to the + * same server - they now will see the session is in exit state and get + * out of SendReceive. + */ + wake_up_all(&server->request_q); + /* give those requests time to exit */ + msleep(125); + + if (server->ssocket) { + sock_release(server->ssocket); + server->ssocket = NULL; + } + + if (!list_empty(&server->pending_mid_q)) { + struct list_head dispose_list; + struct mid_q_entry *mid_entry; + struct list_head *tmp, *tmp2; + + INIT_LIST_HEAD(&dispose_list); + spin_lock(&GlobalMid_Lock); + list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { + mid_entry = list_entry(tmp, struct mid_q_entry, qhead); + cFYI(1, "Clearing mid 0x%x", mid_entry->mid); + mid_entry->midState = MID_SHUTDOWN; + list_move(&mid_entry->qhead, &dispose_list); + } + spin_unlock(&GlobalMid_Lock); + + /* now walk dispose list and issue callbacks */ + list_for_each_safe(tmp, tmp2, &dispose_list) { + mid_entry = list_entry(tmp, struct mid_q_entry, qhead); + cFYI(1, "Callback mid 0x%x", mid_entry->mid); + list_del_init(&mid_entry->qhead); + mid_entry->callback(mid_entry); + } + /* 1/8th of sec is more than enough time for them to exit */ + msleep(125); + } + + if (!list_empty(&server->pending_mid_q)) { + /* + * mpx threads have not exited yet give them at least the smb + * send timeout time for long ops. + * + * Due to delays on oplock break requests, we need to wait at + * least 45 seconds before giving up on a request getting a + * response and going ahead and killing cifsd. + */ + cFYI(1, "Wait for exit from demultiplex thread"); + msleep(46000); + /* + * If threads still have not exited they are probably never + * coming home not much else we can do but free the memory. + */ + } + + kfree(server->hostname); + kfree(server); + + length = atomic_dec_return(&tcpSesAllocCount); + if (length > 0) + mempool_resize(cifs_req_poolp, length + cifs_min_rcv, + GFP_KERNEL); +} + static int cifs_demultiplex_thread(struct TCP_Server_Info *server) { @@ -538,7 +633,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct smb_hdr *smb_buffer = NULL; struct msghdr smb_msg; struct kvec iov; - struct list_head *tmp, *tmp2; struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; bool isLargeBuf = false; @@ -675,88 +769,13 @@ incomplete_rcv: } } /* end while !EXITING */ - /* take it off the list, if it's not already */ - spin_lock(&cifs_tcp_ses_lock); - list_del_init(&server->tcp_ses_list); - spin_unlock(&cifs_tcp_ses_lock); - - spin_lock(&GlobalMid_Lock); - server->tcpStatus = CifsExiting; - spin_unlock(&GlobalMid_Lock); - wake_up_all(&server->response_q); - - /* check if we have blocked requests that need to free */ - /* Note that cifs_max_pending is normally 50, but - can be set at module install time to as little as two */ - spin_lock(&GlobalMid_Lock); - if (atomic_read(&server->inFlight) >= cifs_max_pending) - atomic_set(&server->inFlight, cifs_max_pending - 1); - /* We do not want to set the max_pending too low or we - could end up with the counter going negative */ - spin_unlock(&GlobalMid_Lock); - /* Although there should not be any requests blocked on - this queue it can not hurt to be paranoid and try to wake up requests - that may haven been blocked when more than 50 at time were on the wire - to the same server - they now will see the session is in exit state - and get out of SendReceive. */ - wake_up_all(&server->request_q); - /* give those requests time to exit */ - msleep(125); - - if (server->ssocket) { - sock_release(server->ssocket); - server->ssocket = NULL; - } /* buffer usually freed in free_mid - need to free it here on exit */ cifs_buf_release(bigbuf); if (smallbuf) /* no sense logging a debug message if NULL */ cifs_small_buf_release(smallbuf); - if (!list_empty(&server->pending_mid_q)) { - struct list_head dispose_list; - - INIT_LIST_HEAD(&dispose_list); - spin_lock(&GlobalMid_Lock); - list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cFYI(1, "Clearing mid 0x%x", mid_entry->mid); - mid_entry->midState = MID_SHUTDOWN; - list_move(&mid_entry->qhead, &dispose_list); - } - spin_unlock(&GlobalMid_Lock); - - /* now walk dispose list and issue callbacks */ - list_for_each_safe(tmp, tmp2, &dispose_list) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cFYI(1, "Callback mid 0x%x", mid_entry->mid); - list_del_init(&mid_entry->qhead); - mid_entry->callback(mid_entry); - } - /* 1/8th of sec is more than enough time for them to exit */ - msleep(125); - } - - if (!list_empty(&server->pending_mid_q)) { - /* mpx threads have not exited yet give them - at least the smb send timeout time for long ops */ - /* due to delays on oplock break requests, we need - to wait at least 45 seconds before giving up - on a request getting a response and going ahead - and killing cifsd */ - cFYI(1, "Wait for exit from demultiplex thread"); - msleep(46000); - /* if threads still have not exited they are probably never - coming home not much else we can do but free the memory */ - } - - kfree(server->hostname); task_to_wake = xchg(&server->tsk, NULL); - kfree(server); - - length = atomic_dec_return(&tcpSesAllocCount); - if (length > 0) - mempool_resize(cifs_req_poolp, length + cifs_min_rcv, - GFP_KERNEL); + clean_demultiplex_info(server); /* if server->tsk was NULL then wait for a signal before exiting */ if (!task_to_wake) {