Skip to content

Commit a3c0e7b

Browse files
committed
Merge tag 'libnvdimm-fixes-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
More libnvdimm updates from Dan Williams: - Complete the reworks to interoperate with powerpc dynamic huge page sizes - Fix a crash due to missed accounting for the powerpc 'struct page'-memmap mapping granularity - Fix badblock initialization for volatile (DRAM emulated) pmem ranges - Stop triggering request_key() notifications to userspace when NVDIMM-security is disabled / not present - Miscellaneous small fixups * tag 'libnvdimm-fixes-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: libnvdimm/region: Enable MAP_SYNC for volatile regions libnvdimm: prevent nvdimm from requesting key when security is disabled libnvdimm/region: Initialize bad block for volatile namespaces libnvdimm/nfit_test: Fix acpi_handle redefinition libnvdimm/altmap: Track namespace boundaries in altmap libnvdimm: Fix endian conversion issues  libnvdimm/dax: Pick the right alignment default when creating dax devices powerpc/book3s64: Export has_transparent_hugepage() related functions.
2 parents 939ca9f + 4c806b8 commit a3c0e7b

File tree

15 files changed

+110
-51
lines changed

15 files changed

+110
-51
lines changed

arch/powerpc/include/asm/book3s/64/radix.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,13 @@ extern void radix__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
254254
extern pgtable_t radix__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
255255
extern pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm,
256256
unsigned long addr, pmd_t *pmdp);
257-
extern int radix__has_transparent_hugepage(void);
257+
static inline int radix__has_transparent_hugepage(void)
258+
{
259+
/* For radix 2M at PMD level means thp */
260+
if (mmu_psize_defs[MMU_PAGE_2M].shift == PMD_SHIFT)
261+
return 1;
262+
return 0;
263+
}
258264
#endif
259265

260266
extern int __meminit radix__vmemmap_create_mapping(unsigned long start,

arch/powerpc/mm/book3s64/hash_pgtable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ int hash__has_transparent_hugepage(void)
406406

407407
return 1;
408408
}
409+
EXPORT_SYMBOL_GPL(hash__has_transparent_hugepage);
410+
409411
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
410412

411413
#ifdef CONFIG_STRICT_KERNEL_RWX

arch/powerpc/mm/book3s64/radix_pgtable.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,13 +1027,6 @@ pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm,
10271027
return old_pmd;
10281028
}
10291029

1030-
int radix__has_transparent_hugepage(void)
1031-
{
1032-
/* For radix 2M at PMD level means thp */
1033-
if (mmu_psize_defs[MMU_PAGE_2M].shift == PMD_SHIFT)
1034-
return 1;
1035-
return 0;
1036-
}
10371030
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
10381031

10391032
void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,

arch/powerpc/mm/init_64.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ static __meminit void vmemmap_list_populate(unsigned long phys,
172172
vmemmap_list = vmem_back;
173173
}
174174

175+
static bool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long start,
176+
unsigned long page_size)
177+
{
178+
unsigned long nr_pfn = page_size / sizeof(struct page);
179+
unsigned long start_pfn = page_to_pfn((struct page *)start);
180+
181+
if ((start_pfn + nr_pfn) > altmap->end_pfn)
182+
return true;
183+
184+
if (start_pfn < altmap->base_pfn)
185+
return true;
186+
187+
return false;
188+
}
189+
175190
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
176191
struct vmem_altmap *altmap)
177192
{
@@ -194,7 +209,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
194209
* fail due to alignment issues when using 16MB hugepages, so
195210
* fall back to system memory if the altmap allocation fail.
196211
*/
197-
if (altmap) {
212+
if (altmap && !altmap_cross_boundary(altmap, start, page_size)) {
198213
p = altmap_alloc_block_buf(page_size, altmap);
199214
if (!p)
200215
pr_debug("altmap block allocation failed, falling back to system memory");

drivers/nvdimm/btt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ static int btt_flog_write(struct arena_info *arena, u32 lane, u32 sub,
392392
arena->freelist[lane].sub = 1 - arena->freelist[lane].sub;
393393
if (++(arena->freelist[lane].seq) == 4)
394394
arena->freelist[lane].seq = 1;
395-
if (ent_e_flag(ent->old_map))
395+
if (ent_e_flag(le32_to_cpu(ent->old_map)))
396396
arena->freelist[lane].has_err = 1;
397-
arena->freelist[lane].block = le32_to_cpu(ent_lba(ent->old_map));
397+
arena->freelist[lane].block = ent_lba(le32_to_cpu(ent->old_map));
398398

399399
return ret;
400400
}
@@ -560,8 +560,8 @@ static int btt_freelist_init(struct arena_info *arena)
560560
* FIXME: if error clearing fails during init, we want to make
561561
* the BTT read-only
562562
*/
563-
if (ent_e_flag(log_new.old_map) &&
564-
!ent_normal(log_new.old_map)) {
563+
if (ent_e_flag(le32_to_cpu(log_new.old_map)) &&
564+
!ent_normal(le32_to_cpu(log_new.old_map))) {
565565
arena->freelist[i].has_err = 1;
566566
ret = arena_clear_freelist_error(arena, i);
567567
if (ret)

drivers/nvdimm/bus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ static int nvdimm_clear_badblocks_region(struct device *dev, void *data)
180180
sector_t sector;
181181

182182
/* make sure device is a region */
183-
if (!is_nd_pmem(dev))
183+
if (!is_memory(dev))
184184
return 0;
185185

186186
nd_region = to_nd_region(dev);

drivers/nvdimm/namespace_devs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,7 +1987,7 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
19871987
nd_mapping = &nd_region->mapping[i];
19881988
label_ent = list_first_entry_or_null(&nd_mapping->labels,
19891989
typeof(*label_ent), list);
1990-
label0 = label_ent ? label_ent->label : 0;
1990+
label0 = label_ent ? label_ent->label : NULL;
19911991

19921992
if (!label0) {
19931993
WARN_ON(1);
@@ -2322,8 +2322,9 @@ static struct device **scan_labels(struct nd_region *nd_region)
23222322
continue;
23232323

23242324
/* skip labels that describe extents outside of the region */
2325-
if (nd_label->dpa < nd_mapping->start || nd_label->dpa > map_end)
2326-
continue;
2325+
if (__le64_to_cpu(nd_label->dpa) < nd_mapping->start ||
2326+
__le64_to_cpu(nd_label->dpa) > map_end)
2327+
continue;
23272328

23282329
i = add_namespace_resource(nd_region, nd_label, devs, count);
23292330
if (i < 0)

drivers/nvdimm/nd.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,7 @@ static inline struct device *nd_btt_create(struct nd_region *nd_region)
289289
struct nd_pfn *to_nd_pfn(struct device *dev);
290290
#if IS_ENABLED(CONFIG_NVDIMM_PFN)
291291

292-
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
293-
#define PFN_DEFAULT_ALIGNMENT HPAGE_PMD_SIZE
294-
#else
295-
#define PFN_DEFAULT_ALIGNMENT PAGE_SIZE
296-
#endif
292+
#define MAX_NVDIMM_ALIGN 4
297293

298294
int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns);
299295
bool is_nd_pfn(struct device *dev);

drivers/nvdimm/pfn_devs.c

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -103,39 +103,42 @@ static ssize_t align_show(struct device *dev,
103103
return sprintf(buf, "%ld\n", nd_pfn->align);
104104
}
105105

106-
static const unsigned long *nd_pfn_supported_alignments(void)
106+
static unsigned long *nd_pfn_supported_alignments(unsigned long *alignments)
107107
{
108-
/*
109-
* This needs to be a non-static variable because the *_SIZE
110-
* macros aren't always constants.
111-
*/
112-
const unsigned long supported_alignments[] = {
113-
PAGE_SIZE,
114-
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
115-
HPAGE_PMD_SIZE,
116-
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
117-
HPAGE_PUD_SIZE,
118-
#endif
119-
#endif
120-
0,
121-
};
122-
static unsigned long data[ARRAY_SIZE(supported_alignments)];
123108

124-
memcpy(data, supported_alignments, sizeof(data));
109+
alignments[0] = PAGE_SIZE;
110+
111+
if (has_transparent_hugepage()) {
112+
alignments[1] = HPAGE_PMD_SIZE;
113+
if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD))
114+
alignments[2] = HPAGE_PUD_SIZE;
115+
}
116+
117+
return alignments;
118+
}
119+
120+
/*
121+
* Use pmd mapping if supported as default alignment
122+
*/
123+
static unsigned long nd_pfn_default_alignment(void)
124+
{
125125

126-
return data;
126+
if (has_transparent_hugepage())
127+
return HPAGE_PMD_SIZE;
128+
return PAGE_SIZE;
127129
}
128130

129131
static ssize_t align_store(struct device *dev,
130132
struct device_attribute *attr, const char *buf, size_t len)
131133
{
132134
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
135+
unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
133136
ssize_t rc;
134137

135138
nd_device_lock(dev);
136139
nvdimm_bus_lock(dev);
137140
rc = nd_size_select_store(dev, buf, &nd_pfn->align,
138-
nd_pfn_supported_alignments());
141+
nd_pfn_supported_alignments(aligns));
139142
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
140143
buf[len - 1] == '\n' ? "" : "\n");
141144
nvdimm_bus_unlock(dev);
@@ -259,7 +262,10 @@ static DEVICE_ATTR_RO(size);
259262
static ssize_t supported_alignments_show(struct device *dev,
260263
struct device_attribute *attr, char *buf)
261264
{
262-
return nd_size_select_show(0, nd_pfn_supported_alignments(), buf);
265+
unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
266+
267+
return nd_size_select_show(0,
268+
nd_pfn_supported_alignments(aligns), buf);
263269
}
264270
static DEVICE_ATTR_RO(supported_alignments);
265271

@@ -302,7 +308,7 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
302308
return NULL;
303309

304310
nd_pfn->mode = PFN_MODE_NONE;
305-
nd_pfn->align = PFN_DEFAULT_ALIGNMENT;
311+
nd_pfn->align = nd_pfn_default_alignment();
306312
dev = &nd_pfn->dev;
307313
device_initialize(&nd_pfn->dev);
308314
if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) {
@@ -412,6 +418,21 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
412418
return 0;
413419
}
414420

421+
static bool nd_supported_alignment(unsigned long align)
422+
{
423+
int i;
424+
unsigned long supported[MAX_NVDIMM_ALIGN] = { [0] = 0, };
425+
426+
if (align == 0)
427+
return false;
428+
429+
nd_pfn_supported_alignments(supported);
430+
for (i = 0; supported[i]; i++)
431+
if (align == supported[i])
432+
return true;
433+
return false;
434+
}
435+
415436
/**
416437
* nd_pfn_validate - read and validate info-block
417438
* @nd_pfn: fsdax namespace runtime state / properties
@@ -496,6 +517,18 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
496517
return -EOPNOTSUPP;
497518
}
498519

520+
/*
521+
* Check whether the we support the alignment. For Dax if the
522+
* superblock alignment is not matching, we won't initialize
523+
* the device.
524+
*/
525+
if (!nd_supported_alignment(align) &&
526+
!memcmp(pfn_sb->signature, DAX_SIG, PFN_SIG_LEN)) {
527+
dev_err(&nd_pfn->dev, "init failed, alignment mismatch: "
528+
"%ld:%ld\n", nd_pfn->align, align);
529+
return -EOPNOTSUPP;
530+
}
531+
499532
if (!nd_pfn->uuid) {
500533
/*
501534
* When probing a namepace via nd_pfn_probe() the uuid
@@ -639,9 +672,11 @@ static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap)
639672
struct nd_namespace_common *ndns = nd_pfn->ndns;
640673
struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
641674
resource_size_t base = nsio->res.start + start_pad;
675+
resource_size_t end = nsio->res.end - end_trunc;
642676
struct vmem_altmap __altmap = {
643677
.base_pfn = init_altmap_base(base),
644678
.reserve = init_altmap_reserve(base),
679+
.end_pfn = PHYS_PFN(end),
645680
};
646681

647682
memcpy(res, &nsio->res, sizeof(*res));

drivers/nvdimm/region.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static int nd_region_probe(struct device *dev)
3434
if (rc)
3535
return rc;
3636

37-
if (is_nd_pmem(&nd_region->dev)) {
37+
if (is_memory(&nd_region->dev)) {
3838
struct resource ndr_res;
3939

4040
if (devm_init_badblocks(dev, &nd_region->bb))
@@ -123,7 +123,7 @@ static void nd_region_notify(struct device *dev, enum nvdimm_event event)
123123
struct nd_region *nd_region = to_nd_region(dev);
124124
struct resource res;
125125

126-
if (is_nd_pmem(&nd_region->dev)) {
126+
if (is_memory(&nd_region->dev)) {
127127
res.start = nd_region->ndr_start;
128128
res.end = nd_region->ndr_start +
129129
nd_region->ndr_size - 1;

0 commit comments

Comments
 (0)