Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756493AbcJMP6m (ORCPT ); Thu, 13 Oct 2016 11:58:42 -0400 Received: from g9t1613g.houston.hpe.com ([15.241.32.99]:34104 "EHLO g9t1613g.houston.hpe.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754471AbcJMP6d (ORCPT ); Thu, 13 Oct 2016 11:58:33 -0400 From: Toshi Kani To: dan.j.williams@intel.com Cc: vishal.l.verma@intel.com, linux-nvdimm@ml01.01.org, linux-kernel@vger.kernel.org, Toshi Kani Subject: [PATCH] pmem: report error on clear poison failure Date: Thu, 13 Oct 2016 09:54:21 -0600 Message-Id: <1476374061-9080-1-git-send-email-toshi.kani@hpe.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1763 Lines: 50 ACPI Clear Uncorrectable Error DSM function may fail or may be unsupported on a platform. pmem_clear_poison() returns without clearing badblocks in such cases, which leads to a silent data corruption. Change pmem_do_bvec() and pmem_clear_poison() to return -EIO so that filesystem can log an error message. Signed-off-by: Toshi Kani Cc: Dan Williams Cc: Vishal Verma --- drivers/nvdimm/pmem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 42b3a82..2461843 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -47,7 +47,7 @@ static struct nd_region *to_region(struct pmem_device *pmem) return to_nd_region(to_dev(pmem)->parent); } -static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, +static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, unsigned int len) { struct device *dev = to_dev(pmem); @@ -62,8 +62,12 @@ static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, __func__, (unsigned long long) sector, cleared / 512, cleared / 512 > 1 ? "s" : ""); badblocks_clear(&pmem->bb, sector, cleared / 512); + } else { + return -EIO; } + invalidate_pmem(pmem->virt_addr + offset, len); + return 0; } static void write_pmem(void *pmem_addr, struct page *page, @@ -123,7 +127,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, flush_dcache_page(page); write_pmem(pmem_addr, page, off, len); if (unlikely(bad_pmem)) { - pmem_clear_poison(pmem, pmem_off, len); + rc = pmem_clear_poison(pmem, pmem_off, len); write_pmem(pmem_addr, page, off, len); } }