aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-01 18:15:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-01 18:15:03 -0400
commitf3683ccd12ac625cee12650ca8595c7b9cb16d77 (patch)
treef4e0d694e4a4da60b90b5b79950196684dd67923
parent6e5c4f13a53d8b126f5636cb29b1c80d10d6838e (diff)
parent1bcbf42d2732b3fdaa8559b0dfc91567769e23c8 (diff)
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm fixes from Dan Williams: "1/ Two regression fixes since v4.6: one for the byte order of a sysfs attribute (bz121161) and another for QEMU 2.6's NVDIMM _DSM (ACPI Device Specific Method) implementation that gets tripped up by new auto-probing behavior in the NFIT driver. 2/ A fix tagged for -stable that stops the kernel from clobbering/ignoring changes to the configuration of a 'pfn' instance ("struct page" driver). For example changing the alignment from 2M to 1G may silently revert to 2M if that value is currently stored on media. 3/ A fix from Eric for an xfstests failure in dax. It is not currently tagged for -stable since it requires an 8-exabyte file system to trigger, and there appear to be no user visible side effects" * 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: nfit: fix format interface code byte order dax: fix offset overflow in dax_io acpi, nfit: fix acpi_check_dsm() vs zero functions implemented libnvdimm, pfn, dax: fix initialization vs autodetect for mode + alignment
-rw-r--r--drivers/acpi/nfit.c12
-rw-r--r--drivers/acpi/nfit.h10
-rw-r--r--drivers/acpi/utils.c6
-rw-r--r--drivers/nvdimm/pfn_devs.c51
-rw-r--r--fs/dax.c7
5 files changed, 60 insertions, 26 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 2215fc847fa9..ac6ddcc080d4 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -928,7 +928,7 @@ static ssize_t format_show(struct device *dev,
928{ 928{
929 struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); 929 struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
930 930
931 return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->code)); 931 return sprintf(buf, "0x%04x\n", le16_to_cpu(dcr->code));
932} 932}
933static DEVICE_ATTR_RO(format); 933static DEVICE_ATTR_RO(format);
934 934
@@ -961,8 +961,8 @@ static ssize_t format1_show(struct device *dev,
961 continue; 961 continue;
962 if (nfit_dcr->dcr->code == dcr->code) 962 if (nfit_dcr->dcr->code == dcr->code)
963 continue; 963 continue;
964 rc = sprintf(buf, "%#x\n", 964 rc = sprintf(buf, "0x%04x\n",
965 be16_to_cpu(nfit_dcr->dcr->code)); 965 le16_to_cpu(nfit_dcr->dcr->code));
966 break; 966 break;
967 } 967 }
968 if (rc != ENXIO) 968 if (rc != ENXIO)
@@ -1131,11 +1131,11 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1131 1131
1132 /* 1132 /*
1133 * Until standardization materializes we need to consider up to 3 1133 * Until standardization materializes we need to consider up to 3
1134 * different command sets. Note, that checking for function0 (bit0) 1134 * different command sets. Note, that checking for zero functions
1135 * tells us if any commands are reachable through this uuid. 1135 * tells us if any commands might be reachable through this uuid.
1136 */ 1136 */
1137 for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++) 1137 for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++)
1138 if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1)) 1138 if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 0))
1139 break; 1139 break;
1140 1140
1141 /* limit the supported commands to those that are publicly documented */ 1141 /* limit the supported commands to those that are publicly documented */
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
index 11cb38348aef..02b9ea1e8d2e 100644
--- a/drivers/acpi/nfit.h
+++ b/drivers/acpi/nfit.h
@@ -53,12 +53,12 @@ enum nfit_uuids {
53}; 53};
54 54
55/* 55/*
56 * Region format interface codes are stored as an array of bytes in the 56 * Region format interface codes are stored with the interface as the
57 * NFIT DIMM Control Region structure 57 * LSB and the function as the MSB.
58 */ 58 */
59#define NFIT_FIC_BYTE cpu_to_be16(0x101) /* byte-addressable energy backed */ 59#define NFIT_FIC_BYTE cpu_to_le16(0x101) /* byte-addressable energy backed */
60#define NFIT_FIC_BLK cpu_to_be16(0x201) /* block-addressable non-energy backed */ 60#define NFIT_FIC_BLK cpu_to_le16(0x201) /* block-addressable non-energy backed */
61#define NFIT_FIC_BYTEN cpu_to_be16(0x301) /* byte-addressable non-energy backed */ 61#define NFIT_FIC_BYTEN cpu_to_le16(0x301) /* byte-addressable non-energy backed */
62 62
63enum { 63enum {
64 NFIT_BLK_READ_FLUSH = 1, 64 NFIT_BLK_READ_FLUSH = 1,
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 22c09952e177..b4de130f2d57 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -680,9 +680,6 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
680 u64 mask = 0; 680 u64 mask = 0;
681 union acpi_object *obj; 681 union acpi_object *obj;
682 682
683 if (funcs == 0)
684 return false;
685
686 obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL); 683 obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL);
687 if (!obj) 684 if (!obj)
688 return false; 685 return false;
@@ -695,6 +692,9 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
695 mask |= (((u64)obj->buffer.pointer[i]) << (i * 8)); 692 mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
696 ACPI_FREE(obj); 693 ACPI_FREE(obj);
697 694
695 if (funcs == 0)
696 return true;
697
698 /* 698 /*
699 * Bit 0 indicates whether there's support for any functions other than 699 * Bit 0 indicates whether there's support for any functions other than
700 * function 0 for the specified UUID and revision. 700 * function 0 for the specified UUID and revision.
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);
diff --git a/fs/dax.c b/fs/dax.c
index 761495bf5eb9..e207f8f9b700 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -208,7 +208,12 @@ static ssize_t dax_io(struct inode *inode, struct iov_iter *iter,
208 dax.addr += first; 208 dax.addr += first;
209 size = map_len - first; 209 size = map_len - first;
210 } 210 }
211 max = min(pos + size, end); 211 /*
212 * pos + size is one past the last offset for IO,
213 * so pos + size can overflow loff_t at extreme offsets.
214 * Cast to u64 to catch this and get the true minimum.
215 */
216 max = min_t(u64, pos + size, end);
212 } 217 }
213 218
214 if (iov_iter_rw(iter) == WRITE) { 219 if (iov_iter_rw(iter) == WRITE) {