aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/nvdimm/pfn_devs.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index f7718ec685fa..cea8350fbc7e 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -344,6 +344,8 @@ struct device *nd_pfn_create(struct nd_region *nd_region)
344int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) 344int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
345{ 345{
346 u64 checksum, offset; 346 u64 checksum, offset;
347 unsigned long align;
348 enum nd_pfn_mode mode;
347 struct nd_namespace_io *nsio; 349 struct nd_namespace_io *nsio;
348 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; 350 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
349 struct nd_namespace_common *ndns = nd_pfn->ndns; 351 struct nd_namespace_common *ndns = nd_pfn->ndns;
@@ -386,22 +388,50 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
386 return -ENXIO; 388 return -ENXIO;
387 } 389 }
388 390
391 align = le32_to_cpu(pfn_sb->align);
392 offset = le64_to_cpu(pfn_sb->dataoff);
393 if (align == 0)
394 align = 1UL << ilog2(offset);
395 mode = le32_to_cpu(pfn_sb->mode);
396
389 if (!nd_pfn->uuid) { 397 if (!nd_pfn->uuid) {
390 /* from probe we allocate */ 398 /*
399 * When probing a namepace via nd_pfn_probe() the uuid
400 * is NULL (see: nd_pfn_devinit()) we init settings from
401 * pfn_sb
402 */
391 nd_pfn->uuid = kmemdup(pfn_sb->uuid, 16, GFP_KERNEL); 403 nd_pfn->uuid = kmemdup(pfn_sb->uuid, 16, GFP_KERNEL);
392 if (!nd_pfn->uuid) 404 if (!nd_pfn->uuid)
393 return -ENOMEM; 405 return -ENOMEM;
406 nd_pfn->align = align;
407 nd_pfn->mode = mode;
394 } else { 408 } else {
395 /* from init we validate */ 409 /*
410 * When probing a pfn / dax instance we validate the
411 * live settings against the pfn_sb
412 */
396 if (memcmp(nd_pfn->uuid, pfn_sb->uuid, 16) != 0) 413 if (memcmp(nd_pfn->uuid, pfn_sb->uuid, 16) != 0)
397 return -ENODEV; 414 return -ENODEV;
415
416 /*
417 * If the uuid validates, but other settings mismatch
418 * return EINVAL because userspace has managed to change
419 * the configuration without specifying new
420 * identification.
421 */
422 if (nd_pfn->align != align || nd_pfn->mode != mode) {
423 dev_err(&nd_pfn->dev,
424 "init failed, settings mismatch\n");
425 dev_dbg(&nd_pfn->dev, "align: %lx:%lx mode: %d:%d\n",
426 nd_pfn->align, align, nd_pfn->mode,
427 mode);
428 return -EINVAL;
429 }
398 } 430 }
399 431
400 if (nd_pfn->align == 0) 432 if (align > nvdimm_namespace_capacity(ndns)) {
401 nd_pfn->align = le32_to_cpu(pfn_sb->align);
402 if (nd_pfn->align > nvdimm_namespace_capacity(ndns)) {
403 dev_err(&nd_pfn->dev, "alignment: %lx exceeds capacity %llx\n", 433 dev_err(&nd_pfn->dev, "alignment: %lx exceeds capacity %llx\n",
404 nd_pfn->align, nvdimm_namespace_capacity(ndns)); 434 align, nvdimm_namespace_capacity(ndns));
405 return -EINVAL; 435 return -EINVAL;
406 } 436 }
407 437
@@ -411,7 +441,6 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
411 * namespace has changed since the pfn superblock was 441 * namespace has changed since the pfn superblock was
412 * established. 442 * established.
413 */ 443 */
414 offset = le64_to_cpu(pfn_sb->dataoff);
415 nsio = to_nd_namespace_io(&ndns->dev); 444 nsio = to_nd_namespace_io(&ndns->dev);
416 if (offset >= resource_size(&nsio->res)) { 445 if (offset >= resource_size(&nsio->res)) {
417 dev_err(&nd_pfn->dev, "pfn array size exceeds capacity of %s\n", 446 dev_err(&nd_pfn->dev, "pfn array size exceeds capacity of %s\n",
@@ -419,10 +448,11 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
419 return -EBUSY; 448 return -EBUSY;
420 } 449 }
421 450
422 if ((nd_pfn->align && !IS_ALIGNED(offset, nd_pfn->align)) 451 if ((align && !IS_ALIGNED(offset, align))
423 || !IS_ALIGNED(offset, PAGE_SIZE)) { 452 || !IS_ALIGNED(offset, PAGE_SIZE)) {
424 dev_err(&nd_pfn->dev, "bad offset: %#llx dax disabled\n", 453 dev_err(&nd_pfn->dev,
425 offset); 454 "bad offset: %#llx dax disabled align: %#lx\n",
455 offset, align);
426 return -ENXIO; 456 return -ENXIO;
427 } 457 }
428 458
@@ -502,7 +532,6 @@ static struct vmem_altmap *__nvdimm_setup_pfn(struct nd_pfn *nd_pfn,
502 res->start += start_pad; 532 res->start += start_pad;
503 res->end -= end_trunc; 533 res->end -= end_trunc;
504 534
505 nd_pfn->mode = le32_to_cpu(nd_pfn->pfn_sb->mode);
506 if (nd_pfn->mode == PFN_MODE_RAM) { 535 if (nd_pfn->mode == PFN_MODE_RAM) {
507 if (offset < SZ_8K) 536 if (offset < SZ_8K)
508 return ERR_PTR(-EINVAL); 537 return ERR_PTR(-EINVAL);