From patchwork Mon Jan 3 18:30:51 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Fields X-Patchwork-Id: 448741 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 p03IUvSc026001 for ; Mon, 3 Jan 2011 18:31:04 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752912Ab1ACSbB (ORCPT ); Mon, 3 Jan 2011 13:31:01 -0500 Received: from fieldses.org ([174.143.236.118]:56799 "EHLO fieldses.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752764Ab1ACSbA (ORCPT ); Mon, 3 Jan 2011 13:31:00 -0500 Received: from bfields by fieldses.org with local (Exim 4.72) (envelope-from ) id 1PZpBL-0004gw-GA; Mon, 03 Jan 2011 13:30:59 -0500 From: "J. Bruce Fields" To: linux-nfs@vger.kernel.org Cc: "J. Bruce Fields" , Neil Brown Subject: [PATCH 2/5] nfsd4: avoid double reply caused by deferral race Date: Mon, 3 Jan 2011 13:30:51 -0500 Message-Id: <1294079454-17891-3-git-send-email-bfields@redhat.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1294079454-17891-1-git-send-email-bfields@redhat.com> References: <1294079454-17891-1-git-send-email-bfields@redhat.com> Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Mon, 03 Jan 2011 18:31:06 +0000 (UTC) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index e433e75..0d6002f 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -37,7 +37,7 @@ #define RPCDBG_FACILITY RPCDBG_CACHE -static void cache_defer_req(struct cache_req *req, struct cache_head *item); +static bool cache_defer_req(struct cache_req *req, struct cache_head *item); static void cache_revisit_request(struct cache_head *item); static void cache_init(struct cache_head *h) @@ -268,9 +268,11 @@ int cache_check(struct cache_detail *detail, } if (rv == -EAGAIN) { - cache_defer_req(rqstp, h); - if (!test_bit(CACHE_PENDING, &h->flags)) { - /* Request is not deferred */ + if (!cache_defer_req(rqstp, h)) { + /* + * Request was not deferred; handle it as best + * we can ourselves: + */ rv = cache_is_valid(detail, h); if (rv == -EAGAIN) rv = -ETIMEDOUT; @@ -618,18 +620,19 @@ static void cache_limit_defers(void) discard->revisit(discard, 1); } -static void cache_defer_req(struct cache_req *req, struct cache_head *item) +/* Return true if and only if a deferred request is queued. */ +static bool cache_defer_req(struct cache_req *req, struct cache_head *item) { struct cache_deferred_req *dreq; if (req->thread_wait) { cache_wait_req(req, item); if (!test_bit(CACHE_PENDING, &item->flags)) - return; + return false; } dreq = req->defer(req); if (dreq == NULL) - return; + return false; setup_deferral(dreq, item, 1); if (!test_bit(CACHE_PENDING, &item->flags)) /* Bit could have been cleared before we managed to @@ -638,6 +641,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item) cache_revisit_request(item); cache_limit_defers(); + return true; } static void cache_revisit_request(struct cache_head *item)