From patchwork Fri Nov 17 03:51:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Hua X-Patchwork-Id: 10062263 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 86B2760352 for ; Fri, 17 Nov 2017 03:51:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A38D2AC28 for ; Fri, 17 Nov 2017 03:51:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5EF222AC2B; Fri, 17 Nov 2017 03:51:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EF9482AC28 for ; Fri, 17 Nov 2017 03:51:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756512AbdKQDve (ORCPT ); Thu, 16 Nov 2017 22:51:34 -0500 Received: from mail-ua0-f193.google.com ([209.85.217.193]:42307 "EHLO mail-ua0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756363AbdKQDvd (ORCPT ); Thu, 16 Nov 2017 22:51:33 -0500 Received: by mail-ua0-f193.google.com with SMTP id p33so584293uag.9; Thu, 16 Nov 2017 19:51:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:sender:from:date:message-id:subject:to:cc; bh=f6TcFFsWIuQvPn8Shsv6gEZj3HWe1r67OpRlIbICBtc=; b=TP5/+55XeJeCqMH79powyKkV7a7XSzxpR6VJRGNqFYln/szlvCN4H+730d0nzhocyY qoADcfhxCMpOZQtAf/7Ie9FB98A0Z+AesdCUkq6N29u2C90yeY1p54j2bp8Y5ccKk3aU OlkmsMymzqrnXcqxxpZytPsRh+6jKb6aJqBYxvYnaddyHkyjb9xDMvDVgXfmQ8brcGrp RDr36n8cIhu218fo6+BTXv2Fc/2P3RP/XwnpMAKJKUgXRmpryHjrTztXr1xfJ1cnmpsM MsBbFV67KYfhre4IbH/86UsWsrfQjCcAFOsL5qYBunL+F8yYGEh6AGVQ3C5siwu7ylmb fMbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:from:date:message-id:subject :to:cc; bh=f6TcFFsWIuQvPn8Shsv6gEZj3HWe1r67OpRlIbICBtc=; b=YeFTpxIFAlx+toN9v0YaQDDxatPA5ZkJFCLB18JyriQwz0eCFpkxi6Yb4OK2h1qGwa Z7lTPLmzlfw3GW9ABf4WtcwUqPJ4Ei33t6S53RqewAdlG9SKlqKQqKxIPi/A0sVOZf9D YnAaWkTJEiLjNCLEJ9aLeYzaRxXraWPdaR4IlNa27R6V2y0mzOWETlw7PIVQ+IoDFhpx RSVinkpthmmAHzWvyzOjEBJhO7Al9iOfEWSUaa4weKGou2QIJDl6syIJFofYRkQsksnX H7q22GbI6ni3HRnykhKKOslk7TUvYNx+4s6aTSv8A6rhkKaNLKItA/PCLBBSvMO5hkts l1WA== X-Gm-Message-State: AJaThX4An8zN0WdTJWjG6EAwPAGU9Lgm972pOLBLXJCs3AQ8DeeYpGC9 hsOhz36hU+7LaM3Hi43uIm4eAQ26jFcuTDduLbA= X-Google-Smtp-Source: AGs4zMaIp5c+6Ug9vkzdaJ7ETxBKV3kB7BHAINOaZATy4qOACISf/kVUDH8ljgXCZo4919R4ju74Fu+eMyovKI9BQ8c= X-Received: by 10.176.81.12 with SMTP id e12mr3396902uaa.120.1510890692431; Thu, 16 Nov 2017 19:51:32 -0800 (PST) MIME-Version: 1.0 Received: by 10.103.35.194 with HTTP; Thu, 16 Nov 2017 19:51:12 -0800 (PST) From: Rui Hua Date: Fri, 17 Nov 2017 11:51:12 +0800 X-Google-Sender-Auth: W97X6ixBhgTM1nuoKFAta0Hcpt8 Message-ID: Subject: [PATCH] bcache: recover data from backing device when read request hit clean To: Coly Li , Michael Lyle , Kent Overstreet Cc: linux-bcache@vger.kernel.org, linux-block@vger.kernel.org Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When we send a read request and hit the clean data in cache device, there is a situation called cache read race in bcache(see the commit in the tail of cache_look_up(), the following explaination just copy from there): The bucket we're reading from might be reused while our bio is in flight, and we could then end up reading the wrong data. We guard against this by checking (in bch_cache_read_endio()) if the pointer is stale again; if so, we treat it as an error (s->iop.error = -EINTR) and reread from the backing device (but we don't pass that error up anywhere) It should be noted that cache read race happened under normal circumstances, not the circumstance when SSD failed, it was counted and shown in /sys/fs/bcache/XXX/internal/cache_read_races. Without this patch, when we use writeback mode, we will never reread from the backing device when cache read race happend, until the whole cache device is clean, because the condition (s->recoverable && (dc && !atomic_read(&dc->has_dirty))) is false in cached_dev_read_error(). In this situation, the s->iop.error(= -EINTR) will be passed up, at last, user will receive -EINTR when it's bio end, this is not suitable, and wield to up-application. In this patch, we use s->read_dirty_data to judge whether the read request hit dirty data in cache device, it is safe to reread data from the backing device when the read request hit clean data. This can not only handle cache read race, but also recover data when failed read request from cache device. Signed-off-by: Hua Rui Reviewed-by: Coly Li Reviewed-by: Michael Lyle --- drivers/md/bcache/request.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 3a7aed7..f02fefb 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -708,16 +708,15 @@ static void cached_dev_read_error(struct closure *cl) { struct search *s = container_of(cl, struct search, cl); struct bio *bio = &s->bio.bio; - struct cached_dev *dc = container_of(s->d, struct cached_dev, disk); /* - * If cache device is dirty (dc->has_dirty is non-zero), then - * recovery a failed read request from cached device may get a - * stale data back. So read failure recovery is only permitted - * when cache device is clean. + * If read request hit dirty data (s->read_dirty_data is true), + * then recovery a failed read request from cached device may + * get a stale data back. So read failure recovery is only + * permitted when read request hit clean data in cache device, + * or when cache read race happend. */ - if (s->recoverable && - (dc && !atomic_read(&dc->has_dirty))) { + if (s->recoverable && !s->read_dirty_data) { /* Retry from the backing device: */ trace_bcache_read_retry(s->orig_bio);