Skip to content

Commit 46b1ee3

Browse files
Ralph Campbelltorvalds
authored andcommitted
mm/mremap_pages: fix static key devmap_managed_key updates
commit 6f42193 ("memremap: don't use a separate devm action for devmap_managed_enable_get") changed the static key updates such that we now call devmap_managed_enable_put() without doing the equivalent devmap_managed_enable_get(). devmap_managed_enable_get() is only called for MEMORY_DEVICE_PRIVATE and MEMORY_DEVICE_FS_DAX, But memunmap_pages() get called for other pgmap types too. This results in the below warning when switching between system-ram and devdax mode for devdax namespace. jump label: negative count! WARNING: CPU: 52 PID: 1335 at kernel/jump_label.c:235 static_key_slow_try_dec+0x88/0xa0 Modules linked in: .... NIP static_key_slow_try_dec+0x88/0xa0 LR static_key_slow_try_dec+0x84/0xa0 Call Trace: static_key_slow_try_dec+0x84/0xa0 __static_key_slow_dec_cpuslocked+0x34/0xd0 static_key_slow_dec+0x54/0xf0 memunmap_pages+0x36c/0x500 devm_action_release+0x30/0x50 release_nodes+0x2f4/0x3e0 device_release_driver_internal+0x17c/0x280 bus_remove_device+0x124/0x210 device_del+0x1d4/0x530 unregister_dev_dax+0x48/0xe0 devm_action_release+0x30/0x50 release_nodes+0x2f4/0x3e0 device_release_driver_internal+0x17c/0x280 unbind_store+0x130/0x170 drv_attr_store+0x40/0x60 sysfs_kf_write+0x6c/0xb0 kernfs_fop_write+0x118/0x280 vfs_write+0xe8/0x2a0 ksys_write+0x84/0x140 system_call_exception+0x120/0x270 system_call_common+0xf0/0x27c Reported-by: Aneesh Kumar K.V <[email protected]> Signed-off-by: Ralph Campbell <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Tested-by: Sachin Sant <[email protected]> Reviewed-by: Aneesh Kumar K.V <[email protected]> Reviewed-by: Ira Weiny <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Cc: Dan Williams <[email protected]> Cc: Jason Gunthorpe <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 3cea11c commit 46b1ee3

File tree

1 file changed

+16
-23
lines changed

1 file changed

+16
-23
lines changed

mm/memremap.c

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,28 +41,24 @@ EXPORT_SYMBOL_GPL(memremap_compat_align);
4141
DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
4242
EXPORT_SYMBOL(devmap_managed_key);
4343

44-
static void devmap_managed_enable_put(void)
44+
static void devmap_managed_enable_put(struct dev_pagemap *pgmap)
4545
{
46-
static_branch_dec(&devmap_managed_key);
46+
if (pgmap->type == MEMORY_DEVICE_PRIVATE ||
47+
pgmap->type == MEMORY_DEVICE_FS_DAX)
48+
static_branch_dec(&devmap_managed_key);
4749
}
4850

49-
static int devmap_managed_enable_get(struct dev_pagemap *pgmap)
51+
static void devmap_managed_enable_get(struct dev_pagemap *pgmap)
5052
{
51-
if (pgmap->type == MEMORY_DEVICE_PRIVATE &&
52-
(!pgmap->ops || !pgmap->ops->page_free)) {
53-
WARN(1, "Missing page_free method\n");
54-
return -EINVAL;
55-
}
56-
57-
static_branch_inc(&devmap_managed_key);
58-
return 0;
53+
if (pgmap->type == MEMORY_DEVICE_PRIVATE ||
54+
pgmap->type == MEMORY_DEVICE_FS_DAX)
55+
static_branch_inc(&devmap_managed_key);
5956
}
6057
#else
61-
static int devmap_managed_enable_get(struct dev_pagemap *pgmap)
58+
static void devmap_managed_enable_get(struct dev_pagemap *pgmap)
6259
{
63-
return -EINVAL;
6460
}
65-
static void devmap_managed_enable_put(void)
61+
static void devmap_managed_enable_put(struct dev_pagemap *pgmap)
6662
{
6763
}
6864
#endif /* CONFIG_DEV_PAGEMAP_OPS */
@@ -169,7 +165,7 @@ void memunmap_pages(struct dev_pagemap *pgmap)
169165
pageunmap_range(pgmap, i);
170166

171167
WARN_ONCE(pgmap->altmap.alloc, "failed to free all reserved pages\n");
172-
devmap_managed_enable_put();
168+
devmap_managed_enable_put(pgmap);
173169
}
174170
EXPORT_SYMBOL_GPL(memunmap_pages);
175171

@@ -307,7 +303,6 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
307303
.pgprot = PAGE_KERNEL,
308304
};
309305
const int nr_range = pgmap->nr_range;
310-
bool need_devmap_managed = true;
311306
int error, i;
312307

313308
if (WARN_ONCE(!nr_range, "nr_range must be specified\n"))
@@ -323,6 +318,10 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
323318
WARN(1, "Missing migrate_to_ram method\n");
324319
return ERR_PTR(-EINVAL);
325320
}
321+
if (!pgmap->ops->page_free) {
322+
WARN(1, "Missing page_free method\n");
323+
return ERR_PTR(-EINVAL);
324+
}
326325
if (!pgmap->owner) {
327326
WARN(1, "Missing owner\n");
328327
return ERR_PTR(-EINVAL);
@@ -336,11 +335,9 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
336335
}
337336
break;
338337
case MEMORY_DEVICE_GENERIC:
339-
need_devmap_managed = false;
340338
break;
341339
case MEMORY_DEVICE_PCI_P2PDMA:
342340
params.pgprot = pgprot_noncached(params.pgprot);
343-
need_devmap_managed = false;
344341
break;
345342
default:
346343
WARN(1, "Invalid pgmap type %d\n", pgmap->type);
@@ -364,11 +361,7 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
364361
}
365362
}
366363

367-
if (need_devmap_managed) {
368-
error = devmap_managed_enable_get(pgmap);
369-
if (error)
370-
return ERR_PTR(error);
371-
}
364+
devmap_managed_enable_get(pgmap);
372365

373366
/*
374367
* Clear the pgmap nr_range as it will be incremented for each

0 commit comments

Comments
 (0)