2010-01-11 02:00:54

by Zheng, Shaohui

[permalink] [raw]
Subject: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

Resend the memmap patch v4 to mailing-list after follow up fengguang's review
comments.

memory-hotplug: create /sys/firmware/memmap entry for hot-added memory

Interface firmware_map_add was not called in explict, Remove it and add function
firmware_map_add_hotplug as hotplug interface of memmap.

When we hot-add new memory, sysfs does not export memmap entry for it. we add
a call in function add_memory to function firmware_map_add_hotplug.

Add a new function add_sysfs_fw_map_entry to create memmap entry, it can avoid
duplicated codes.

Thanks for the careful review from Fengguang Wu and Dave Hansen.

Signed-off-by: Shaohui Zheng <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Acked-by: Yasunori Goto <[email protected]>
Reviewed-by: Wu Fengguang <[email protected]>
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 56f9234..11baa6d 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -123,20 +123,40 @@ static int firmware_map_add_entry(u64 start, u64 end,
}

/**
- * firmware_map_add() - Adds a firmware mapping entry.
+ * Add memmap entry on sysfs
+ */
+static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+ static int map_entries_nr;
+ static struct kset *mmap_kset;
+
+ if (!mmap_kset) {
+ mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
+ if (!mmap_kset)
+ return -ENOMEM;
+ }
+
+ entry->kobj.kset = mmap_kset;
+ if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
+ kobject_put(&entry->kobj);
+
+ return 0;
+}
+
+/**
+ * firmware_map_add_early() - Adds a firmware mapping entry.
* @start: Start of the memory range.
* @end: End of the memory range (inclusive).
* @type: Type of the memory range.
*
- * This function uses kmalloc() for memory
- * allocation. Use firmware_map_add_early() if you want to use the bootmem
- * allocator.
+ * Adds a firmware mapping entry. This function uses the bootmem allocator
+ * for memory allocation.
*
* That function must be called before late_initcall.
*
* Returns 0 on success, or -ENOMEM if no memory could be allocated.
**/
-int firmware_map_add(u64 start, u64 end, const char *type)
+int __init firmware_map_add_early(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;

@@ -148,27 +168,31 @@ int firmware_map_add(u64 start, u64 end, const char *type)
}

/**
- * firmware_map_add_early() - Adds a firmware mapping entry.
+ * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
+ * memory hotplug.
* @start: Start of the memory range.
* @end: End of the memory range (inclusive).
* @type: Type of the memory range.
*
- * Adds a firmware mapping entry. This function uses the bootmem allocator
- * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
- *
- * That function must be called before late_initcall.
+ * Adds a firmware mapping entry. This function is for memory hotplug, it is
+ * simiar with function firmware_map_add_early. the only difference is that
+ * it will create the syfs entry dynamically.
*
* Returns 0 on success, or -ENOMEM if no memory could be allocated.
**/
-int __init firmware_map_add_early(u64 start, u64 end, const char *type)
+int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;

- entry = alloc_bootmem(sizeof(struct firmware_map_entry));
- if (WARN_ON(!entry))
+ entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
+ if (!entry)
return -ENOMEM;

- return firmware_map_add_entry(start, end, type, entry);
+ firmware_map_add_entry(start, end, type, entry);
+ /* create the memmap entry */
+ add_sysfs_fw_map_entry(entry);
+
+ return 0;
}

/*
@@ -214,18 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
*/
static int __init memmap_init(void)
{
- int i = 0;
struct firmware_map_entry *entry;
- struct kset *memmap_kset;
-
- memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
- if (WARN_ON(!memmap_kset))
- return -ENOMEM;

list_for_each_entry(entry, &map_entries, list) {
- entry->kobj.kset = memmap_kset;
- if (kobject_add(&entry->kobj, NULL, "%d", i++))
- kobject_put(&entry->kobj);
+ add_sysfs_fw_map_entry(entry);
}

return 0;
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 875451f..c6dcc1d 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -24,17 +24,17 @@
*/
#ifdef CONFIG_FIRMWARE_MEMMAP

-int firmware_map_add(u64 start, u64 end, const char *type);
int firmware_map_add_early(u64 start, u64 end, const char *type);
+int firmware_map_add_hotplug(u64 start, u64 end, const char *type);

#else /* CONFIG_FIRMWARE_MEMMAP */

-static inline int firmware_map_add(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
{
return 0;
}

-static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
return 0;
}
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 030ce8a..78e34e6 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -28,6 +28,7 @@
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/mm_inline.h>
+#include <linux/firmware-map.h>

#include <asm/tlbflush.h>

@@ -523,6 +524,9 @@ int __ref add_memory(int nid, u64 start, u64 size)
BUG_ON(ret);
}

+ /* create new memmap entry */
+ firmware_map_add_hotplug(start, start + size, "System RAM");
+
goto out;

error:

Thanks & Regards,
Shaohui




Attachments:
memory-hotplug-create-sys-firmware-memmap-entry-for-new-memory-v4.patch (5.41 kB)
memory-hotplug-create-sys-firmware-memmap-entry-for-new-memory-v4.patch

2010-01-13 22:30:37

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

On Mon, 11 Jan 2010 10:00:11 +0800
"Zheng, Shaohui" <[email protected]> wrote:

> Resend the memmap patch v4 to mailing-list after follow up fengguang's review
> comments.
>
> memory-hotplug: create /sys/firmware/memmap entry for hot-added memory
>
> Interface firmware_map_add was not called in explict, Remove it and add function
> firmware_map_add_hotplug as hotplug interface of memmap.
>
> When we hot-add new memory, sysfs does not export memmap entry for it. we add
> a call in function add_memory to function firmware_map_add_hotplug.
>
> Add a new function add_sysfs_fw_map_entry to create memmap entry, it can avoid
> duplicated codes.
>
> Thanks for the careful review from Fengguang Wu and Dave Hansen.
>

Please describe the format of the proposed sysfs file. Example output
would be suitable.

> @@ -123,20 +123,40 @@ static int firmware_map_add_entry(u64 start, u64 end,
> }
>
> /**
> - * firmware_map_add() - Adds a firmware mapping entry.
> + * Add memmap entry on sysfs
> + */
> +static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
> +{
> + static int map_entries_nr;
> + static struct kset *mmap_kset;
> +
> + if (!mmap_kset) {
> + mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
> + if (!mmap_kset)
> + return -ENOMEM;
> + }

This is a bit racy if two threads execute it at the same time. I guess
it doesn't matter.


> + entry->kobj.kset = mmap_kset;
> + if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
> + kobject_put(&entry->kobj);

hm. Is this refcounting correct?

> +
> + return 0;
> +}

One caller of add_sysfs_fw_map_entry() is __meminit and the other is
__init. So this function can be __meminit?

> +/**
> + * firmware_map_add_early() - Adds a firmware mapping entry.
> * @start: Start of the memory range.
> * @end: End of the memory range (inclusive).
> * @type: Type of the memory range.
> *
> - * This function uses kmalloc() for memory
> - * allocation. Use firmware_map_add_early() if you want to use the bootmem
> - * allocator.
> + * Adds a firmware mapping entry. This function uses the bootmem allocator
> + * for memory allocation.
> *
> * That function must be called before late_initcall.
> *
> * Returns 0 on success, or -ENOMEM if no memory could be allocated.
> **/
> -int firmware_map_add(u64 start, u64 end, const char *type)
> +int __init firmware_map_add_early(u64 start, u64 end, const char *type)
> {
> struct firmware_map_entry *entry;
>
> @@ -148,27 +168,31 @@ int firmware_map_add(u64 start, u64 end, const char *type)
> }
>
> /**
> - * firmware_map_add_early() - Adds a firmware mapping entry.
> + * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
> + * memory hotplug.
> * @start: Start of the memory range.
> * @end: End of the memory range (inclusive).
> * @type: Type of the memory range.
> *
> - * Adds a firmware mapping entry. This function uses the bootmem allocator
> - * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
> - *
> - * That function must be called before late_initcall.
> + * Adds a firmware mapping entry. This function is for memory hotplug, it is
> + * simiar with function firmware_map_add_early. the only difference is that

s/simiar/similar/
s/with/to/
s/the/The/
s/function firmware_map_add_early/firmware_map_add_early()/

> + * it will create the syfs entry dynamically.
> *
> * Returns 0 on success, or -ENOMEM if no memory could be allocated.
> **/
> -int __init firmware_map_add_early(u64 start, u64 end, const char *type)
> +int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
> {
> struct firmware_map_entry *entry;
>
> - entry = alloc_bootmem(sizeof(struct firmware_map_entry));
> - if (WARN_ON(!entry))
> + entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
> + if (!entry)
> return -ENOMEM;
>
> - return firmware_map_add_entry(start, end, type, entry);
> + firmware_map_add_entry(start, end, type, entry);
> + /* create the memmap entry */
> + add_sysfs_fw_map_entry(entry);
> +
> + return 0;
> }
>
> /*
> @@ -214,18 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
> */
> static int __init memmap_init(void)
> {
> - int i = 0;
> struct firmware_map_entry *entry;
> - struct kset *memmap_kset;
> -
> - memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
> - if (WARN_ON(!memmap_kset))
> - return -ENOMEM;
>
> list_for_each_entry(entry, &map_entries, list) {
> - entry->kobj.kset = memmap_kset;
> - if (kobject_add(&entry->kobj, NULL, "%d", i++))
> - kobject_put(&entry->kobj);
> + add_sysfs_fw_map_entry(entry);
> }

The braces are now unneeded. checkpatch used to warn about this I
think. Either someone broke checkpatch or it doesn't understand
list_for_each_entry().

>
> ...
>

2010-01-19 08:33:48

by Zheng, Shaohui

[permalink] [raw]
Subject: RE: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

I did some investigation for my patch, I see that there is an error when I make v4 patch from v3, I change the function firmware_map_add_early() by carelessness,
The code
entry = alloc_bootmem(sizeof(struct firmware_map_entry));
was changed to
entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);


The modification from v3 to v4 is minor, so I did not do full testing for v4 patch, I apologize for my fault.

The patch works after I correct the this code. I will resend it.

Thanks & Regards,
Shaohui


-----Original Message-----
From: Andrew Morton [mailto:[email protected]]
Sent: Saturday, January 16, 2010 6:38 AM
To: Zheng, Shaohui
Cc: [email protected]; [email protected]; [email protected]; [email protected]; Dave Hansen; Wu, Fengguang; [email protected]
Subject: Re: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

On Mon, 11 Jan 2010 10:00:11 +0800
"Zheng, Shaohui" <[email protected]> wrote:

> memory-hotplug: create /sys/firmware/memmap entry for hot-added memory
>
> Interface firmware_map_add was not called in explict, Remove it and add function
> firmware_map_add_hotplug as hotplug interface of memmap.
>
> When we hot-add new memory, sysfs does not export memmap entry for it. we add
> a call in function add_memory to function firmware_map_add_hotplug.
>
> Add a new function add_sysfs_fw_map_entry to create memmap entry, it can avoid
> duplicated codes.

The patch causes an early exception in kmem_cache_alloc_notrace() -
probably due to a null cache pointer.

config: http://master.kernel.org/~akpm/config-akpm2.txt

2010-01-20 05:48:57

by Zheng, Shaohui

[permalink] [raw]
Subject: RE: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

Resend the v6 memmap patch after resolve the early exception. This patch was tested
on DELL Studio XPS(Core i7), I will always be careful to valid each patch before
sending it out.


memory-hotplug: create /sys/firmware/memmap entry for new memory

A memmap is a directory in sysfs which includes 3 text files: start, end and
type. For example:
start: 0x100000
end: 0x7e7b1cff
type: System RAM

Interface firmware_map_add was not called explicitly. Remove it and add function
firmware_map_add_hotplug as hotplug interface of memmap.

Each memory entry has a memmap in sysfs, When we hot-add new memory, sysfs does
not export memmap entry for it. We add a call in function add_memory to function
firmware_map_add_hotplug.

Add a new function add_sysfs_fw_map_entry() to create memmap entry, it will be
called when initialize memmap and hot-add memory.

Signed-off-by: Shaohui Zheng <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Acked-by: Yasunori Goto <[email protected]>
Reviewed-by: Wu Fengguang <[email protected]>
Cc: Dave Hansen <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 56f9234..821db6f 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -123,28 +123,52 @@ static int firmware_map_add_entry(u64 start, u64 end,
}

/**
- * firmware_map_add() - Adds a firmware mapping entry.
+ * Add memmap entry on sysfs
+ */
+static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+ static int map_entries_nr;
+ static struct kset *mmap_kset;
+
+ if (!mmap_kset) {
+ mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
+ if (!mmap_kset)
+ return -ENOMEM;
+ }
+
+ entry->kobj.kset = mmap_kset;
+ if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
+ kobject_put(&entry->kobj);
+
+ return 0;
+}
+
+/**
+ * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
+ * memory hotplug.
* @start: Start of the memory range.
* @end: End of the memory range (inclusive).
* @type: Type of the memory range.
*
- * This function uses kmalloc() for memory
- * allocation. Use firmware_map_add_early() if you want to use the bootmem
- * allocator.
- *
- * That function must be called before late_initcall.
+ * Adds a firmware mapping entry. This function is for memory hotplug, it is
+ * similar to function firmware_map_add_early(). The only difference is that
+ * it will create the syfs entry dynamically.
*
* Returns 0 on success, or -ENOMEM if no memory could be allocated.
**/
-int firmware_map_add(u64 start, u64 end, const char *type)
+int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;

- entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
+ entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
if (!entry)
return -ENOMEM;

- return firmware_map_add_entry(start, end, type, entry);
+ firmware_map_add_entry(start, end, type, entry);
+ /* create the memmap entry */
+ add_sysfs_fw_map_entry(entry);
+
+ return 0;
}

/**
@@ -154,7 +178,7 @@ int firmware_map_add(u64 start, u64 end, const char *type)
* @type: Type of the memory range.
*
* Adds a firmware mapping entry. This function uses the bootmem allocator
- * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
+ * for memory allocation.
*
* That function must be called before late_initcall.
*
@@ -214,19 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
*/
static int __init memmap_init(void)
{
- int i = 0;
struct firmware_map_entry *entry;
- struct kset *memmap_kset;
-
- memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
- if (WARN_ON(!memmap_kset))
- return -ENOMEM;

- list_for_each_entry(entry, &map_entries, list) {
- entry->kobj.kset = memmap_kset;
- if (kobject_add(&entry->kobj, NULL, "%d", i++))
- kobject_put(&entry->kobj);
- }
+ list_for_each_entry(entry, &map_entries, list)
+ add_sysfs_fw_map_entry(entry);

return 0;
}
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 875451f..c6dcc1d 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -24,17 +24,17 @@
*/
#ifdef CONFIG_FIRMWARE_MEMMAP

-int firmware_map_add(u64 start, u64 end, const char *type);
int firmware_map_add_early(u64 start, u64 end, const char *type);
+int firmware_map_add_hotplug(u64 start, u64 end, const char *type);

#else /* CONFIG_FIRMWARE_MEMMAP */

-static inline int firmware_map_add(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
{
return 0;
}

-static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
return 0;
}
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 030ce8a..78e34e6 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -28,6 +28,7 @@
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/mm_inline.h>
+#include <linux/firmware-map.h>

#include <asm/tlbflush.h>

@@ -523,6 +524,9 @@ int __ref add_memory(int nid, u64 start, u64 size)
BUG_ON(ret);
}

+ /* create new memmap entry */
+ firmware_map_add_hotplug(start, start + size, "System RAM");
+
goto out;

error:

Thanks & Regards,
Shaohui


Attachments:
memory-hotplug-create-sys-firmware-memmap-entry-for-new-memory-v6.patch (5.13 kB)
memory-hotplug-create-sys-firmware-memmap-entry-for-new-memory-v6.patch

2010-01-15 03:41:22

by Zheng, Shaohui

[permalink] [raw]
Subject: RE: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

On Mon, 11 Jan 2010 10:00:11 +0800
"Zheng, Shaohui" <[email protected]> wrote:

> Resend the memmap patch v4 to mailing-list after follow up fengguang's review
> comments.
>
> memory-hotplug: create /sys/firmware/memmap entry for hot-added memory
>
> Interface firmware_map_add was not called in explict, Remove it and add function
> firmware_map_add_hotplug as hotplug interface of memmap.
>
> When we hot-add new memory, sysfs does not export memmap entry for it. we add
> a call in function add_memory to function firmware_map_add_hotplug.
>
> Add a new function add_sysfs_fw_map_entry to create memmap entry, it can avoid
> duplicated codes.
>
> Thanks for the careful review from Fengguang Wu and Dave Hansen.
>

Please describe the format of the proposed sysfs file. Example output
would be suitable.

> @@ -123,20 +123,40 @@ static int firmware_map_add_entry(u64 start, u64 end,
> }
>
> /**
> - * firmware_map_add() - Adds a firmware mapping entry.
> + * Add memmap entry on sysfs
> + */
> +static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
> +{
> + static int map_entries_nr;
> + static struct kset *mmap_kset;
> +
> + if (!mmap_kset) {
> + mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
> + if (!mmap_kset)
> + return -ENOMEM;
> + }

This is a bit racy if two threads execute it at the same time. I guess
it doesn't matter.
[Zheng, Shaohui] function add_sysfs_fw_map_entry will be called when OS boots up and we hot-add memory, it never has chance to be execute in two threads, it should be okay.


> + entry->kobj.kset = mmap_kset;
> + if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
> + kobject_put(&entry->kobj);

hm. Is this refcounting correct?
[Zheng, Shaohui] all objects of firmware_map_entry shares the same kset, I use a static pointer to store it. When create next entry, we can get the reference easier. I already test it, it works fine.

> +
> + return 0;
> +}

One caller of add_sysfs_fw_map_entry() is __meminit and the other is
__init. So this function can be __meminit?
[Zheng, Shaohui] function add_sysfs_fw_map_entry() should be still here after booting up, it will be called when we hot-add new memory, so it can not be _init. __meminit should be the correct since this function is related memory hot-plug.

> +/**
> + * firmware_map_add_early() - Adds a firmware mapping entry.
> * @start: Start of the memory range.
> * @end: End of the memory range (inclusive).
> * @type: Type of the memory range.
> *
> - * This function uses kmalloc() for memory
> - * allocation. Use firmware_map_add_early() if you want to use the bootmem
> - * allocator.
> + * Adds a firmware mapping entry. This function uses the bootmem allocator
> + * for memory allocation.
> *
> * That function must be called before late_initcall.
> *
> * Returns 0 on success, or -ENOMEM if no memory could be allocated.
> **/
> -int firmware_map_add(u64 start, u64 end, const char *type)
> +int __init firmware_map_add_early(u64 start, u64 end, const char *type)
> {
> struct firmware_map_entry *entry;
>
> @@ -148,27 +168,31 @@ int firmware_map_add(u64 start, u64 end, const char *type)
> }
>
> /**
> - * firmware_map_add_early() - Adds a firmware mapping entry.
> + * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
> + * memory hotplug.
> * @start: Start of the memory range.
> * @end: End of the memory range (inclusive).
> * @type: Type of the memory range.
> *
> - * Adds a firmware mapping entry. This function uses the bootmem allocator
> - * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
> - *
> - * That function must be called before late_initcall.
> + * Adds a firmware mapping entry. This function is for memory hotplug, it is
> + * simiar with function firmware_map_add_early. the only difference is that

s/simiar/similar/
s/with/to/
s/the/The/
s/function firmware_map_add_early/firmware_map_add_early()/
[Zheng, Shaohui] sorry for my carelessness.

> + * it will create the syfs entry dynamically.
> *
> * Returns 0 on success, or -ENOMEM if no memory could be allocated.
> **/
> -int __init firmware_map_add_early(u64 start, u64 end, const char *type)
> +int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
> {
> struct firmware_map_entry *entry;
>
> - entry = alloc_bootmem(sizeof(struct firmware_map_entry));
> - if (WARN_ON(!entry))
> + entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
> + if (!entry)
> return -ENOMEM;
>
> - return firmware_map_add_entry(start, end, type, entry);
> + firmware_map_add_entry(start, end, type, entry);
> + /* create the memmap entry */
> + add_sysfs_fw_map_entry(entry);
> +
> + return 0;
> }
>
> /*
> @@ -214,18 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
> */
> static int __init memmap_init(void)
> {
> - int i = 0;
> struct firmware_map_entry *entry;
> - struct kset *memmap_kset;
> -
> - memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
> - if (WARN_ON(!memmap_kset))
> - return -ENOMEM;
>
> list_for_each_entry(entry, &map_entries, list) {
> - entry->kobj.kset = memmap_kset;
> - if (kobject_add(&entry->kobj, NULL, "%d", i++))
> - kobject_put(&entry->kobj);
> + add_sysfs_fw_map_entry(entry);
> }

The braces are now unneeded. checkpatch used to warn about this I
think. Either someone broke checkpatch or it doesn't understand
list_for_each_entry().
[Zheng, Shaohui] I will remove the unneeded braces.

>
> ...
>

2010-01-15 14:34:06

by Zheng, Shaohui

[permalink] [raw]
Subject: [PATCH-RESEND v5] memory-hotplug: create /sys/firmware/memmap entry for new memory

memory-hotplug: create /sys/firmware/memmap entry for new memory

A memmap is a directory in sysfys which includes 3 text files: start, end and
type. For example:
start: 0x100000
end: 0x7e7b1cff
type: System RAM

Each memory entry has a memmap in sysfs, When we hot-add new memory, sysfs does
not export memmap entry for it. We add a call in function add_memory to function
firmware_map_add_hotplug.

Interface firmware_map_add was not called explictly. Remove it and add function
firmware_map_add_hotplug as hotplug interface of memmap.

Add a new function add_sysfs_fw_map_entry() to create memmap entry, it will be
called when initialize memmap and hot-add memory.

Signed-off-by: Shaohui Zheng <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Acked-by: Yasunori Goto <[email protected]>
Reviewed-by: Wu Fengguang <[email protected]>
Cc: Dave Hansen <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 56f9234..2d1812f 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -123,20 +123,40 @@ static int firmware_map_add_entry(u64 start, u64 end,
}

/**
- * firmware_map_add() - Adds a firmware mapping entry.
+ * Add memmap entry on sysfs
+ */
+static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+ static int map_entries_nr;
+ static struct kset *mmap_kset;
+
+ if (!mmap_kset) {
+ mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
+ if (!mmap_kset)
+ return -ENOMEM;
+ }
+
+ entry->kobj.kset = mmap_kset;
+ if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
+ kobject_put(&entry->kobj);
+
+ return 0;
+}
+
+/**
+ * firmware_map_add_early() - Adds a firmware mapping entry.
* @start: Start of the memory range.
* @end: End of the memory range (inclusive).
* @type: Type of the memory range.
*
- * This function uses kmalloc() for memory
- * allocation. Use firmware_map_add_early() if you want to use the bootmem
- * allocator.
+ * Adds a firmware mapping entry. This function uses the bootmem allocator
+ * for memory allocation.
*
* That function must be called before late_initcall.
*
* Returns 0 on success, or -ENOMEM if no memory could be allocated.
**/
-int firmware_map_add(u64 start, u64 end, const char *type)
+int __init firmware_map_add_early(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;

@@ -148,27 +168,31 @@ int firmware_map_add(u64 start, u64 end, const char *type)
}

/**
- * firmware_map_add_early() - Adds a firmware mapping entry.
+ * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
+ * memory hotplug.
* @start: Start of the memory range.
* @end: End of the memory range (inclusive).
* @type: Type of the memory range.
*
- * Adds a firmware mapping entry. This function uses the bootmem allocator
- * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
- *
- * That function must be called before late_initcall.
+ * Adds a firmware mapping entry. This function is for memory hotplug, it is
+ * similar to function firmware_map_add_early(). The only difference is that
+ * it will create the syfs entry dynamically.
*
* Returns 0 on success, or -ENOMEM if no memory could be allocated.
**/
-int __init firmware_map_add_early(u64 start, u64 end, const char *type)
+int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;

- entry = alloc_bootmem(sizeof(struct firmware_map_entry));
- if (WARN_ON(!entry))
+ entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
+ if (!entry)
return -ENOMEM;

- return firmware_map_add_entry(start, end, type, entry);
+ firmware_map_add_entry(start, end, type, entry);
+ /* create the memmap entry */
+ add_sysfs_fw_map_entry(entry);
+
+ return 0;
}

/*
@@ -214,19 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
*/
static int __init memmap_init(void)
{
- int i = 0;
struct firmware_map_entry *entry;
- struct kset *memmap_kset;

- memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
- if (WARN_ON(!memmap_kset))
- return -ENOMEM;
-
- list_for_each_entry(entry, &map_entries, list) {
- entry->kobj.kset = memmap_kset;
- if (kobject_add(&entry->kobj, NULL, "%d", i++))
- kobject_put(&entry->kobj);
- }
+ list_for_each_entry(entry, &map_entries, list)
+ add_sysfs_fw_map_entry(entry);

return 0;
}
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 875451f..c6dcc1d 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -24,17 +24,17 @@
*/
#ifdef CONFIG_FIRMWARE_MEMMAP

-int firmware_map_add(u64 start, u64 end, const char *type);
int firmware_map_add_early(u64 start, u64 end, const char *type);
+int firmware_map_add_hotplug(u64 start, u64 end, const char *type);

#else /* CONFIG_FIRMWARE_MEMMAP */

-static inline int firmware_map_add(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
{
return 0;
}

-static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
return 0;
}
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 030ce8a..78e34e6 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -28,6 +28,7 @@
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/mm_inline.h>
+#include <linux/firmware-map.h>

#include <asm/tlbflush.h>

@@ -523,6 +524,9 @@ int __ref add_memory(int nid, u64 start, u64 size)
BUG_ON(ret);
}

+ /* create new memmap entry */
+ firmware_map_add_hotplug(start, start + size, "System RAM");
+
goto out;

error:

Thanks & Regards,
Shaohui


Attachments:
memory-hotplug-create-sys-firmware-memmap-entry-for-new-memory-v5.patch (5.70 kB)
memory-hotplug-create-sys-firmware-memmap-entry-for-new-memory-v5.patch

2010-01-15 22:39:04

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

On Mon, 11 Jan 2010 10:00:11 +0800
"Zheng, Shaohui" <[email protected]> wrote:

> memory-hotplug: create /sys/firmware/memmap entry for hot-added memory
>
> Interface firmware_map_add was not called in explict, Remove it and add function
> firmware_map_add_hotplug as hotplug interface of memmap.
>
> When we hot-add new memory, sysfs does not export memmap entry for it. we add
> a call in function add_memory to function firmware_map_add_hotplug.
>
> Add a new function add_sysfs_fw_map_entry to create memmap entry, it can avoid
> duplicated codes.

The patch causes an early exception in kmem_cache_alloc_notrace() -
probably due to a null cache pointer.

config: http://master.kernel.org/~akpm/config-akpm2.txt

2010-01-16 01:08:49

by Zheng, Shaohui

[permalink] [raw]
Subject: RE: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

It is very strange issue since I already test it before sending it out, I will retry it in local.

Thanks & Regards,
Shaohui


-----Original Message-----
From: Andrew Morton [mailto:[email protected]]
Sent: Saturday, January 16, 2010 6:38 AM
To: Zheng, Shaohui
Cc: [email protected]; [email protected]; [email protected]; [email protected]; Dave Hansen; Wu, Fengguang; [email protected]
Subject: Re: [PATCH-RESEND v4] memory-hotplug: create /sys/firmware/memmap entry for new memory

On Mon, 11 Jan 2010 10:00:11 +0800
"Zheng, Shaohui" <[email protected]> wrote:

> memory-hotplug: create /sys/firmware/memmap entry for hot-added memory
>
> Interface firmware_map_add was not called in explict, Remove it and add function
> firmware_map_add_hotplug as hotplug interface of memmap.
>
> When we hot-add new memory, sysfs does not export memmap entry for it. we add
> a call in function add_memory to function firmware_map_add_hotplug.
>
> Add a new function add_sysfs_fw_map_entry to create memmap entry, it can avoid
> duplicated codes.

The patch causes an early exception in kmem_cache_alloc_notrace() -
probably due to a null cache pointer.

config: http://master.kernel.org/~akpm/config-akpm2.txt