Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp7353787imm; Thu, 28 Jun 2018 02:14:52 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJSzfjORWc/ifXz4CHAbAqEtkq5SRbx5J7cHijEEL/YdBUlB+4Guu+Iz0YBFKQ+1PP0MvyY X-Received: by 2002:a17:902:a715:: with SMTP id w21-v6mr9671047plq.111.1530177292699; Thu, 28 Jun 2018 02:14:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530177292; cv=none; d=google.com; s=arc-20160816; b=z7++NKUkzvLiPj6/Ws7TXFHoThtY8Ocd7M4hPKkRpjJJ07Bq23Vt0aJMq5M2B/kP3v iIlwbCvhtrA3Mx9RPsB7KtUIKPjCY9b/OXoBRbQFjjahshm9piSBV1OgKfR9gb0tJt5m JuqHdL9rEJ72hh33JqhM7tDPHm775gK4GT46kq02xgw3jKHXfl5bTEdJNj7AUghGFHry Xy83lhkFJDiIZoscvdX8hs7g5BjEISb/ibb1u3TX/UddcEFAp0Pa29TVIGzXCl/yDw3s ktOn76snG5QinfbACEKdxzcKOYHL5B44HyMMMqGxxsWhEfbv1y1F5chTjHNfkChDZx8K E5kA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=pgkMAEjFrbsEi0EmWdk7pAq+9QPZGH5uYXy4rkPzf0A=; b=Sl57Glr+ej79Qh+X8pTIabypQvnoqV8haCdn6H91my3pz48DSM2MhwtJ4L1/QmP7G+ IUKH0ztEoE+GPt5oK1Y1bKJKyoAXxDoT7fnwTo5hd24j3n+3Zam4erufTe8Lf+4tZUFY 5J5+q9kPM/I3c5fQGuC6LE7aSTEqZhaDGeYCpcQ1qcX4yQ2mxaZsKqJ9zxSNSAq8WZz8 fHdsTjXdhcTUgednPjATSIP3Rqv6BowEc9QsnbgfTpuACTi9/5OpanB2MkMqY/Y2r5mG zfdyOAY9uw5gdQRJ23CUMdsl70o7n84ocoFYn175cyh5xO8zY3YRejQj93ePnwoOJOxc 9b0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@javigon-com.20150623.gappssmtp.com header.s=20150623 header.b=pcIGEqlG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m1-v6si5686103pgb.373.2018.06.28.02.14.35; Thu, 28 Jun 2018 02:14:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@javigon-com.20150623.gappssmtp.com header.s=20150623 header.b=pcIGEqlG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964782AbeF1JMm (ORCPT + 99 others); Thu, 28 Jun 2018 05:12:42 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:39581 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934955AbeF1JMj (ORCPT ); Thu, 28 Jun 2018 05:12:39 -0400 Received: by mail-pl0-f68.google.com with SMTP id s24-v6so2460353plq.6 for ; Thu, 28 Jun 2018 02:12:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=javigon-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pgkMAEjFrbsEi0EmWdk7pAq+9QPZGH5uYXy4rkPzf0A=; b=pcIGEqlGqCLUGLduC4YWfpRRENYZX4BDkk/HWT7a6rBws3HN5l563AZGgftRsLkIZl +aqzugdeAP+I9Pb+SAHGa5H6RJoBwNa10nSG8OscZMYzcGrKvx4WOb2qgAUwh8VoaJAn +P7t/XbQkZWVkqa0N6UHXQhgP8Wl0JQAshjRhN0l/28FIr8Ydc5iraxYyO8Vui6RrbhZ 1hS3iyRJfiTOCeyyjfYuEMN1mSpqcmoyj99KHN3jHkZ9FotsQtTbBu4BnHZ6AR/TwW7f lICon41gh7IjKGzipMozamKOQvY0cp6YdoMYq+bHv/s3kZRWWAlaaKy1mXpW48OPtrCT xiZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pgkMAEjFrbsEi0EmWdk7pAq+9QPZGH5uYXy4rkPzf0A=; b=Mboh6jjOQJl7LZW814Ql1A3IRYoWeA8Yu58e46BlWR+NU4glJYgxw1k0rgSzPA6BIE HTckw7AsORXyjPoacRYYnaMzaWRILlfl8l/ZdsRS4DrLK34XSon4QVpDtT1ZIn0jaqsd J4unG/GoNtNBXOQkp85G3TXgMdh7mC04KHCgESSSlstxNEAQxMkHjSyK36yQGvOK5ljr ef5+rwBRf96MxKkupb0fKopDXjRFA9hv5TkbcyMraoUr7CypHdYiIwc7uYeSKZ9iuvlh vjdmu9zHwbJyaMa5hHSa7GxdGFG0HtbsqeiO8aw7rHB/57IPh0CqM5PJxQNPOaTVt0j2 A0LA== X-Gm-Message-State: APt69E1DvR3dmq09xIc2ahZxOyGVC7qN9PeghLrBXhSLKJinASYimW8d +DjzmBx1XszVFOunHEIh8w2vOg== X-Received: by 2002:a17:902:8210:: with SMTP id x16-v6mr9620336pln.307.1530177158494; Thu, 28 Jun 2018 02:12:38 -0700 (PDT) Received: from ch-wrk-javier.cnexlabs.com (6164211-cl69.boa.fiberby.dk. [193.106.164.211]) by smtp.gmail.com with ESMTPSA id x6-v6sm2223454pfx.185.2018.06.28.02.12.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 28 Jun 2018 02:12:37 -0700 (PDT) From: "=?UTF-8?q?Javier=20Gonz=C3=A1lez?=" X-Google-Original-From: =?UTF-8?q?Javier=20Gonz=C3=A1lez?= To: mb@lightnvm.io Cc: hans.holmberg@cnexlabs.com, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Javier=20Gonz=C3=A1lez?= Subject: [PATCH] lightnvm: pblk: recover chunk state on 1.2 devices Date: Thu, 28 Jun 2018 11:12:01 +0200 Message-Id: <1530177121-24908-2-git-send-email-javier@cnexlabs.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1530177121-24908-1-git-send-email-javier@cnexlabs.com> References: <1530177121-24908-1-git-send-email-javier@cnexlabs.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Open-Channel 1.2 spec does not define a mechanism for the host to recover the block (chunk) state. As a consequence, a newly format device will need to reconstruct the state. Currently, pblk assumes that blocks are not erased, which might cause double-erases in case that the device does not protect itself against them (which is not specified in the spec either). This patch, reconstructs the state based on read errors. If the first sector of a block returns and empty page (NVM_RSP_ERR_EMPTYPAGE), then the block s marked free, i.e., erased and ready to be used (NVM_CHK_ST_FREE). Otherwise, the block is marked as closed (NVM_CHK_ST_CLOSED). Note that even if a block is open and not fully written, it has to be erased in order to be used again. One caveat of this approach is that blocks that have been erased at a moment in time, will always be considered as erased. However, some media might become unstable if blocks are not erased before usage. Since pblk would follow this principle after the state of all blocks fall under pblk's domain, we can consider this as an initialization problem. The trade-off would be to fall back to the old behavior and risk premature media wearing. Signed-off-by: Javier González --- drivers/lightnvm/pblk-init.c | 138 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 14 deletions(-) diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c index 3b8aa4a64cac..ce25f1473d8e 100644 --- a/drivers/lightnvm/pblk-init.c +++ b/drivers/lightnvm/pblk-init.c @@ -697,47 +697,138 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks) atomic_set(&pblk->rl.free_user_blocks, nr_free_blks); } +static void pblk_state_complete(struct kref *ref) +{ + struct pblk_pad_rq *pad_rq = container_of(ref, struct pblk_pad_rq, ref); + + complete(&pad_rq->wait); +} + +static void pblk_end_io_state(struct nvm_rq *rqd) +{ + struct pblk_pad_rq *pad_rq = rqd->private; + struct pblk *pblk = pad_rq->pblk; + struct nvm_tgt_dev *dev = pblk->dev; + struct nvm_geo *geo = &dev->geo; + struct pblk_line *line; + struct nvm_chk_meta *chunk; + int pos; + + line = &pblk->lines[pblk_ppa_to_line(rqd->ppa_addr)]; + pos = pblk_ppa_to_pos(geo, rqd->ppa_addr); + + chunk = &line->chks[pos]; + + if (rqd->error == NVM_RSP_ERR_EMPTYPAGE) + chunk->state = NVM_CHK_ST_FREE; + else + chunk->state = NVM_CHK_ST_CLOSED; + + bio_put(rqd->bio); + pblk_free_rqd(pblk, rqd, PBLK_READ); + kref_put(&pad_rq->ref, pblk_state_complete); +} + +static int pblk_check_chunk_state(struct pblk *pblk, struct nvm_chk_meta *chunk, + struct ppa_addr ppa, struct pblk_pad_rq *pad_rq) +{ + struct nvm_rq *rqd; + struct bio *bio; + int ret; + + bio = bio_alloc(GFP_KERNEL, 1); + + if (pblk_bio_add_pages(pblk, bio, GFP_KERNEL, 1)) + goto fail_free_bio; + + rqd = pblk_alloc_rqd(pblk, PBLK_READ); + + rqd->bio = bio; + rqd->opcode = NVM_OP_PREAD; + rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL); + rqd->nr_ppas = 1; + rqd->ppa_addr = ppa; + rqd->end_io = pblk_end_io_state; + rqd->private = pad_rq; + + kref_get(&pad_rq->ref); + + ret = pblk_submit_io(pblk, rqd); + if (ret) { + pr_err("pblk: I/O submissin failed: %d\n", ret); + goto fail_free_rqd; + } + + return NVM_IO_OK; + +fail_free_rqd: + pblk_free_rqd(pblk, rqd, PBLK_READ); + pblk_bio_free_pages(pblk, bio, 0, bio->bi_vcnt); +fail_free_bio: + bio_put(bio); + + return NVM_IO_ERR; +} + static int pblk_setup_line_meta_12(struct pblk *pblk, struct pblk_line *line, void *chunk_meta) { struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; struct pblk_line_meta *lm = &pblk->lm; + struct pblk_pad_rq *pad_rq; int i, chk_per_lun, nr_bad_chks = 0; + pad_rq = kmalloc(sizeof(struct pblk_pad_rq), GFP_KERNEL); + if (!pad_rq) + return -1; + + pad_rq->pblk = pblk; + init_completion(&pad_rq->wait); + kref_init(&pad_rq->ref); + chk_per_lun = geo->num_chk * geo->pln_mode; for (i = 0; i < lm->blk_per_line; i++) { struct pblk_lun *rlun = &pblk->luns[i]; struct nvm_chk_meta *chunk; - int pos = pblk_ppa_to_pos(geo, rlun->bppa); + struct ppa_addr ppa = rlun->bppa; + int pos = pblk_ppa_to_pos(geo, ppa); u8 *lun_bb_meta = chunk_meta + pos * chk_per_lun; chunk = &line->chks[pos]; - /* - * In 1.2 spec. chunk state is not persisted by the device. Thus - * some of the values are reset each time pblk is instantiated, - * so we have to assume that the block is closed. - */ - if (lun_bb_meta[line->id] == NVM_BLK_T_FREE) - chunk->state = NVM_CHK_ST_CLOSED; - else - chunk->state = NVM_CHK_ST_OFFLINE; - chunk->type = NVM_CHK_TP_W_SEQ; chunk->wi = 0; chunk->slba = -1; chunk->cnlb = geo->clba; chunk->wp = 0; - if (!(chunk->state & NVM_CHK_ST_OFFLINE)) + if (lun_bb_meta[line->id] != NVM_BLK_T_FREE) { + chunk->state = NVM_CHK_ST_OFFLINE; + set_bit(pos, line->blk_bitmap); + nr_bad_chks++; + continue; + } - set_bit(pos, line->blk_bitmap); - nr_bad_chks++; + /* + * In 1.2 spec. chunk state is not persisted by the device. + * Recover the state based on media response. + */ + ppa.g.blk = line->id; + pblk_check_chunk_state(pblk, chunk, ppa, pad_rq); } + kref_put(&pad_rq->ref, pblk_state_complete); + + if (!wait_for_completion_io_timeout(&pad_rq->wait, + msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) { + pr_err("pblk: state recovery timed out\n"); + return -1; + } + + kfree(pad_rq); return nr_bad_chks; } @@ -1036,6 +1127,23 @@ static int pblk_line_meta_init(struct pblk *pblk) return 0; } +static void check_meta(struct pblk *pblk, struct pblk_line *line) +{ + struct nvm_tgt_dev *dev = pblk->dev; + struct nvm_geo *geo = &dev->geo; + struct pblk_line_meta *lm = &pblk->lm; + int i; + + for (i = 0; i < lm->blk_per_line; i++) { + struct pblk_lun *rlun = &pblk->luns[i]; + struct nvm_chk_meta *chunk; + struct ppa_addr ppa = rlun->bppa; + int pos = pblk_ppa_to_pos(geo, ppa); + + chunk = &line->chks[pos]; + } +} + static int pblk_lines_init(struct pblk *pblk) { struct pblk_line_mgmt *l_mg = &pblk->l_mg; @@ -1077,6 +1185,8 @@ static int pblk_lines_init(struct pblk *pblk) goto fail_free_lines; nr_free_chks += pblk_setup_line_meta(pblk, line, chunk_meta, i); + + check_meta(pblk, line); } if (!nr_free_chks) { -- 2.7.4