From patchwork Mon Aug 1 09:19:44 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 1025142 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 p719KIpB031141 for ; Mon, 1 Aug 2011 09:20:41 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752847Ab1HAJUl (ORCPT ); Mon, 1 Aug 2011 05:20:41 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:35513 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751589Ab1HAJUk (ORCPT ); Mon, 1 Aug 2011 05:20:40 -0400 Received: by mail-fx0-f46.google.com with SMTP id 19so4371466fxh.19 for ; Mon, 01 Aug 2011 02:20:40 -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=AQQX7dpyJ6lSHwg0RUu+3qpnpLM7fV3al2JqSo8/L3U=; b=JwKCg60Q+7IGy5HVmdvBKhkfCSK5VWXvoDvD7XkJyNXdcjXfyJZQdA3ySNyUeXjkZy O3cu4S9c2GWLK4WplT2nMiJzhhqY1AbjoE+RCOgrHtPqb7PS/8MCR34p2dqqciTxu6sH w/MAv6Qb+MCWDPzy7aVYPANX4+7HKx9/kEmHw= Received: by 10.204.41.72 with SMTP id n8mr1210715bke.345.1312190440155; Mon, 01 Aug 2011 02:20:40 -0700 (PDT) Received: from localhost.localdomain ([85.26.232.135]) by mx.google.com with ESMTPS id a22sm1249911bke.53.2011.08.01.02.20.36 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 01 Aug 2011 02:20:39 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [v5 PATCH 5/5] CIFS: Cleanup demupltiplex thread exiting code Date: Mon, 1 Aug 2011 13:19:44 +0400 Message-Id: <1312190384-3376-6-git-send-email-piastryyy@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1312190384-3376-1-git-send-email-piastryyy@gmail.com> References: <1312190384-3376-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]); Mon, 01 Aug 2011 09:20:41 +0000 (UTC) Reviewed-and-Tested-by: Jeff Layton 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 12b2741..80c2e3a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -531,6 +531,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(void *p) { @@ -541,7 +636,6 @@ cifs_demultiplex_thread(void *p) 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; @@ -678,88 +772,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) {