summaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-01-05 02:31:24 -0500
committerDan Williams <dan.j.williams@intel.com>2016-01-10 01:42:31 -0500
commit710d69cc99507803ed91b4ec7368fbd66d59f014 (patch)
treeaa05f6cd6fd1cc716a2c2b34e2a9856306aae993 /drivers/nvdimm
parent57f7f317abdd07954cb116280c88d18378afb33e (diff)
libnvdimm, pmem: nvdimm_read_bytes() badblocks support
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>
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r--drivers/nvdimm/pmem.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 6a1832b3983c..a88762d0d086 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -229,6 +229,7 @@ static int pmem_attach_disk(struct device *dev,
229 disk->driverfs_dev = dev; 229 disk->driverfs_dev = dev;
230 set_capacity(disk, (pmem->size - pmem->data_offset) / 512); 230 set_capacity(disk, (pmem->size - pmem->data_offset) / 512);
231 pmem->pmem_disk = disk; 231 pmem->pmem_disk = disk;
232 devm_exit_badblocks(dev, &pmem->bb);
232 if (devm_init_badblocks(dev, &pmem->bb)) 233 if (devm_init_badblocks(dev, &pmem->bb))
233 return -ENOMEM; 234 return -ENOMEM;
234 nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset); 235 nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset);
@@ -250,9 +251,13 @@ static int pmem_rw_bytes(struct nd_namespace_common *ndns,
250 return -EFAULT; 251 return -EFAULT;
251 } 252 }
252 253
253 if (rw == READ) 254 if (rw == READ) {
255 unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
256
257 if (unlikely(is_bad_pmem(&pmem->bb, offset / 512, sz_align)))
258 return -EIO;
254 memcpy_from_pmem(buf, pmem->virt_addr + offset, size); 259 memcpy_from_pmem(buf, pmem->virt_addr + offset, size);
255 else { 260 } else {
256 memcpy_to_pmem(pmem->virt_addr + offset, buf, size); 261 memcpy_to_pmem(pmem->virt_addr + offset, buf, size);
257 wmb_pmem(); 262 wmb_pmem();
258 } 263 }
@@ -427,6 +432,9 @@ static int nd_pmem_probe(struct device *dev)
427 pmem->ndns = ndns; 432 pmem->ndns = ndns;
428 dev_set_drvdata(dev, pmem); 433 dev_set_drvdata(dev, pmem);
429 ndns->rw_bytes = pmem_rw_bytes; 434 ndns->rw_bytes = pmem_rw_bytes;
435 if (devm_init_badblocks(dev, &pmem->bb))
436 return -ENOMEM;
437 nvdimm_namespace_add_poison(ndns, &pmem->bb, 0);
430 438
431 if (is_nd_btt(dev)) 439 if (is_nd_btt(dev))
432 return nvdimm_namespace_attach_btt(ndns); 440 return nvdimm_namespace_attach_btt(ndns);