]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
libnvdimm, pmem: nvdimm_read_bytes() badblocks support
authorDan Williams <dan.j.williams@intel.com>
Tue, 5 Jan 2016 07:31:24 +0000 (23:31 -0800)
committerDan Duval <dan.duval@oracle.com>
Wed, 7 Dec 2016 17:25:51 +0000 (12:25 -0500)
Orabug: 22913653

Support badblock checking in all the pmem read paths that do not go
through the block layer.  This protects info block reads (btt or pfn) as
well as data reads to a pmem namespace via a btt instance.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
(cherry picked from commit 710d69cc99507803ed91b4ec7368fbd66d59f014)
Signed-off-by: Dan Duval <dan.duval@oracle.com>
drivers/nvdimm/pmem.c

index fd0262c2868e0acbd1dc29b0a05e41bbf84f4155..25e74701017fffe64233c89f7bdeb21de5a324a1 100644 (file)
@@ -226,6 +226,7 @@ static int pmem_attach_disk(struct device *dev,
        disk->driverfs_dev = dev;
        set_capacity(disk, (pmem->size - pmem->data_offset) / 512);
        pmem->pmem_disk = disk;
+       devm_exit_badblocks(dev, &pmem->bb);
        if (devm_init_badblocks(dev, &pmem->bb))
                return -ENOMEM;
        nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset);
@@ -246,9 +247,13 @@ static int pmem_rw_bytes(struct nd_namespace_common *ndns,
                return -EFAULT;
        }
 
-       if (rw == READ)
+       if (rw == READ) {
+               unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
+
+               if (unlikely(is_bad_pmem(&pmem->bb, offset / 512, sz_align)))
+                       return -EIO;
                memcpy_from_pmem(buf, pmem->virt_addr + offset, size);
-       else {
+       else {
                memcpy_to_pmem(pmem->virt_addr + offset, buf, size);
                wmb_pmem();
        }
@@ -411,6 +416,9 @@ static int nd_pmem_probe(struct device *dev)
        pmem->ndns = ndns;
        dev_set_drvdata(dev, pmem);
        ndns->rw_bytes = pmem_rw_bytes;
+       if (devm_init_badblocks(dev, &pmem->bb))
+               return -ENOMEM;
+       nvdimm_namespace_add_poison(ndns, &pmem->bb, 0);
 
        if (is_nd_btt(dev))
                return nvdimm_namespace_attach_btt(ndns);