From patchwork Sat Jan 29 12:02:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 516441 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0TC2YbO022587 for ; Sat, 29 Jan 2011 12:02:35 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752063Ab1A2MCe (ORCPT ); Sat, 29 Jan 2011 07:02:34 -0500 Received: from mail-yi0-f46.google.com ([209.85.218.46]:45188 "EHLO mail-yi0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751567Ab1A2MCd (ORCPT ); Sat, 29 Jan 2011 07:02:33 -0500 Received: by yib18 with SMTP id 18so1392514yib.19 for ; Sat, 29 Jan 2011 04:02:33 -0800 (PST) Received: by 10.100.189.9 with SMTP id m9mr2485545anf.170.1296302553081; Sat, 29 Jan 2011 04:02:33 -0800 (PST) Received: from salusa.poochiereds.net (cpe-071-070-153-003.nc.res.rr.com [71.70.153.3]) by mx.google.com with ESMTPS id b11sm9394926ana.38.2011.01.29.04.02.31 (version=SSLv3 cipher=RC4-MD5); Sat, 29 Jan 2011 04:02:32 -0800 (PST) From: Jeff Layton To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org Subject: [PATCH 1/2] cifs: force a reconnect if there are too many MIDs in flight Date: Sat, 29 Jan 2011 07:02:28 -0500 Message-Id: <1296302548-18913-1-git-send-email-jlayton@redhat.com> X-Mailer: git-send-email 1.7.3.4 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]); Sat, 29 Jan 2011 12:03:21 +0000 (UTC) diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 77dc732..2a930a7 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -236,10 +236,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server) { __u16 mid = 0; __u16 last_mid; - int collision; - - if (server == NULL) - return mid; + bool collision; spin_lock(&GlobalMid_Lock); last_mid = server->CurrentMid; /* we do not want to loop forever */ @@ -252,24 +249,38 @@ __u16 GetNextMid(struct TCP_Server_Info *server) (and it would also have to have been a request that did not time out) */ while (server->CurrentMid != last_mid) { - struct list_head *tmp; struct mid_q_entry *mid_entry; + unsigned int num_mids; - collision = 0; + collision = false; if (server->CurrentMid == 0) server->CurrentMid++; - list_for_each(tmp, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - - if ((mid_entry->mid == server->CurrentMid) && - (mid_entry->midState == MID_REQUEST_SUBMITTED)) { + num_mids = 0; + list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { + ++num_mids; + if (mid_entry->mid == server->CurrentMid && + mid_entry->midState == MID_REQUEST_SUBMITTED) { /* This mid is in use, try a different one */ - collision = 1; + collision = true; break; } } - if (collision == 0) { + + /* + * if we have more than 32k mids in the list, then something + * is very wrong. Possibly a local user is trying to DoS the + * box by issuing long-running calls and SIGKILL'ing them. If + * we get to 2^16 mids then we're in big trouble as this + * function could loop forever. + * + * Go ahead and assign out the mid in this situation, but force + * an eventual reconnect to clean out the pending_mid_q. + */ + if (num_mids > 32768) + server->tcpStatus = CifsNeedReconnect; + + if (!collision) { mid = server->CurrentMid; break; }