From patchwork Tue Oct 18 14:09:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Majchrzak X-Patchwork-Id: 9382175 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 D8C8A600CA for ; Tue, 18 Oct 2016 14:10:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C83212962B for ; Tue, 18 Oct 2016 14:10:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA82E2962D; Tue, 18 Oct 2016 14:10:05 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 9FC4F2962B for ; Tue, 18 Oct 2016 14:10:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753095AbcJROKD (ORCPT ); Tue, 18 Oct 2016 10:10:03 -0400 Received: from mga04.intel.com ([192.55.52.120]:33337 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752710AbcJROKD (ORCPT ); Tue, 18 Oct 2016 10:10:03 -0400 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga104.fm.intel.com with ESMTP; 18 Oct 2016 07:09:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,362,1473145200"; d="scan'208";a="774087713" Received: from gklab-102-100.igk.intel.com (HELO proton.igk.intel.com) ([10.102.102.100]) by FMSMGA003.fm.intel.com with ESMTP; 18 Oct 2016 07:09:57 -0700 From: Tomasz Majchrzak To: linux-raid@vger.kernel.org Cc: shli@kernel.org, aleksey.obitotskiy@intel.com, pawel.baldysiak@intel.com, artur.paszkiewicz@intel.com, maksymilian.kunt@intel.com, mariusz.dabrowski@intel.com, axboe@kernel.dk, dan.j.williams@intel.com, linux-block@vger.kernel.org, Tomasz Majchrzak Subject: [PATCH 2/3 v2] md: add bad block support for external metadata Date: Tue, 18 Oct 2016 16:09:45 +0200 Message-Id: <1476799785-6339-1-git-send-email-tomasz.majchrzak@intel.com> X-Mailer: git-send-email 1.8.3.1 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 Add new rdev flag which external metadata handler can use to switch on/off bad block support. If new bad block is encountered, notify it via rdev 'unacknowledged_bad_blocks' sysfs file. If bad block has been cleared, notify update to rdev 'bad_blocks' sysfs file. When bad blocks support is being removed, just clear rdev flag. It is not necessary to reset badblocks->shift field. If there are bad blocks cleared or added at the same time, it is ok for those changes to be applied to the structure. The array is in blocked state and the drive which cannot handle bad blocks any more will be removed from the array before it is unlocked. Simplify state_show function by adding a separator at the end of each string and overwrite last separator with new line. Signed-off-by: Tomasz Majchrzak Reviewed-by: Artur Paszkiewicz --- drivers/md/md.c | 78 ++++++++++++++++++++++++++++----------------------------- drivers/md/md.h | 3 +++ 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index eac84d8..cc05236 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2523,51 +2523,38 @@ struct rdev_sysfs_entry { static ssize_t state_show(struct md_rdev *rdev, char *page) { - char *sep = ""; + char *sep = ","; size_t len = 0; unsigned long flags = ACCESS_ONCE(rdev->flags); if (test_bit(Faulty, &flags) || - rdev->badblocks.unacked_exist) { - len+= sprintf(page+len, "%sfaulty",sep); - sep = ","; - } - if (test_bit(In_sync, &flags)) { - len += sprintf(page+len, "%sin_sync",sep); - sep = ","; - } - if (test_bit(Journal, &flags)) { - len += sprintf(page+len, "%sjournal",sep); - sep = ","; - } - if (test_bit(WriteMostly, &flags)) { - len += sprintf(page+len, "%swrite_mostly",sep); - sep = ","; - } + rdev->badblocks.unacked_exist) + len += sprintf(page+len, "faulty%s", sep); + if (test_bit(In_sync, &flags)) + len += sprintf(page+len, "in_sync%s", sep); + if (test_bit(Journal, &flags)) + len += sprintf(page+len, "journal%s", sep); + if (test_bit(WriteMostly, &flags)) + len += sprintf(page+len, "write_mostly%s", sep); if (test_bit(Blocked, &flags) || (rdev->badblocks.unacked_exist - && !test_bit(Faulty, &flags))) { - len += sprintf(page+len, "%sblocked", sep); - sep = ","; - } + && !test_bit(Faulty, &flags))) + len += sprintf(page+len, "blocked%s", sep); if (!test_bit(Faulty, &flags) && !test_bit(Journal, &flags) && - !test_bit(In_sync, &flags)) { - len += sprintf(page+len, "%sspare", sep); - sep = ","; - } - if (test_bit(WriteErrorSeen, &flags)) { - len += sprintf(page+len, "%swrite_error", sep); - sep = ","; - } - if (test_bit(WantReplacement, &flags)) { - len += sprintf(page+len, "%swant_replacement", sep); - sep = ","; - } - if (test_bit(Replacement, &flags)) { - len += sprintf(page+len, "%sreplacement", sep); - sep = ","; - } + !test_bit(In_sync, &flags)) + len += sprintf(page+len, "spare%s", sep); + if (test_bit(WriteErrorSeen, &flags)) + len += sprintf(page+len, "write_error%s", sep); + if (test_bit(WantReplacement, &flags)) + len += sprintf(page+len, "want_replacement%s", sep); + if (test_bit(Replacement, &flags)) + len += sprintf(page+len, "replacement%s", sep); + if (test_bit(ExternalBbl, &flags)) + len += sprintf(page+len, "external_bbl%s", sep); + + if (len) + len -= strlen(sep); return len+sprintf(page+len, "\n"); } @@ -2708,6 +2695,13 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) } } else err = -EBUSY; + } else if (cmd_match(buf, "external_bbl") && (rdev->mddev->external)) { + set_bit(ExternalBbl, &rdev->flags); + rdev->badblocks.shift = 0; + err = 0; + } else if (cmd_match(buf, "-external_bbl") && (rdev->mddev->external)) { + clear_bit(ExternalBbl, &rdev->flags); + err = 0; } if (!err) sysfs_notify_dirent_safe(rdev->sysfs_state); @@ -8614,6 +8608,9 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors, rv = badblocks_set(&rdev->badblocks, s, sectors, 0); if (rv == 0) { /* Make sure they get written out promptly */ + if (test_bit(ExternalBbl, &rdev->flags)) + sysfs_notify(&rdev->kobj, NULL, + "unacknowledged_bad_blocks"); sysfs_notify_dirent_safe(rdev->sysfs_state); set_mask_bits(&mddev->flags, 0, BIT(MD_CHANGE_CLEAN) | BIT(MD_CHANGE_PENDING)); @@ -8627,12 +8624,15 @@ EXPORT_SYMBOL_GPL(rdev_set_badblocks); int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors, int is_new) { + int rv; if (is_new) s += rdev->new_data_offset; else s += rdev->data_offset; - return badblocks_clear(&rdev->badblocks, - s, sectors); + rv = badblocks_clear(&rdev->badblocks, s, sectors); + if ((rv == 0) && test_bit(ExternalBbl, &rdev->flags)) + sysfs_notify(&rdev->kobj, NULL, "bad_blocks"); + return rv; } EXPORT_SYMBOL_GPL(rdev_clear_badblocks); diff --git a/drivers/md/md.h b/drivers/md/md.h index 2b20417..21bd94f 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -168,6 +168,9 @@ enum flag_bits { * so it is safe to remove without * another synchronize_rcu() call. */ + ExternalBbl, /* External metadata provides bad + * block management for a disk + */ }; static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,