Skip to content

Commit 82bf103

Browse files
davejiangdjbw
authored andcommitted
libnvdimm: check and clear poison before writing to pmem
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 <dave.jiang@intel.com> Reviewed-by: Vishal Verma <vishal.l.verma@intel.com> [djbw: fixup 0-length write request to succeed] Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent dafb104 commit 82bf103

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

drivers/nvdimm/claim.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,24 +226,46 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns,
226226
resource_size_t offset, void *buf, size_t size, int rw)
227227
{
228228
struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
229+
unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
230+
sector_t sector = offset >> 9;
231+
int rc = 0;
232+
233+
if (unlikely(!size))
234+
return 0;
229235

230236
if (unlikely(offset + size > nsio->size)) {
231237
dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n");
232238
return -EFAULT;
233239
}
234240

235241
if (rw == READ) {
236-
unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
237-
238-
if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align)))
242+
if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align)))
239243
return -EIO;
240244
return memcpy_from_pmem(buf, nsio->addr + offset, size);
241245
} else {
246+
247+
if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) {
248+
if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)) {
249+
long cleared;
250+
251+
cleared = nvdimm_clear_poison(&ndns->dev,
252+
offset, size);
253+
if (cleared != size) {
254+
size = cleared;
255+
rc = -EIO;
256+
}
257+
258+
badblocks_clear(&nsio->bb, sector,
259+
cleared >> 9);
260+
} else
261+
rc = -EIO;
262+
}
263+
242264
memcpy_to_pmem(nsio->addr + offset, buf, size);
243265
nvdimm_flush(to_nd_region(ndns->dev.parent));
244266
}
245267

246-
return 0;
268+
return rc;
247269
}
248270

249271
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio)

0 commit comments

Comments
 (0)