We need to clear any poison when we are writing to pmem. The granularity will be sector size. If it's less then we can't do anything about it barring corruption.
Signed-off-by: Dave Jiang <[email protected]> --- drivers/nvdimm/claim.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c index d5dc80c..2078d25 100644 --- a/drivers/nvdimm/claim.c +++ b/drivers/nvdimm/claim.c @@ -226,6 +226,7 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, resource_size_t offset, void *buf, size_t size, int rw) { struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); + unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); if (unlikely(offset + size > nsio->size)) { dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); @@ -233,12 +234,27 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, } if (rw == READ) { - unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); - if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align))) return -EIO; return memcpy_from_pmem(buf, nsio->addr + offset, size); } else { + sector_t sector = offset / 512; + + if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) { + if (IS_ALIGNED(offset, 512) && + IS_ALIGNED(size, 512) && (size >= 512)) { + int rc; + + rc = nvdimm_clear_poison(&ndns->dev, offset, + size); + if (rc != size) + return -EIO; + + badblocks_clear(&nsio->bb, sector, rc / 512); + } else + return -EIO; + } + memcpy_to_pmem(nsio->addr + offset, buf, size); nvdimm_flush(to_nd_region(ndns->dev.parent)); } _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
