Re: [PATCH v5 04/14] memory-hotplug: remove /sys/firmware/memmap/X sysfs

2013-01-02 Thread Christoph Lameter
On Thu, 27 Dec 2012, Tang Chen wrote:

 On 12/26/2012 11:30 AM, Kamezawa Hiroyuki wrote:
  @@ -41,6 +42,7 @@ struct firmware_map_entry {
 const char  *type;  /* type of the memory range */
 struct list_headlist;   /* entry for the linked list */
 struct kobject  kobj;   /* kobject for each entry */
  +  unsigned intbootmem:1; /* allocated from bootmem */
 };
 
  Can't we detect from which the object is allocated from, slab or bootmem ?
 
  Hm, for example,
 
   PageReserved(virt_to_page(address_of_obj)) ?
   PageSlab(virt_to_page(address_of_obj)) ?
 

 Hi Kamezawa-san,

 I think we can detect it without a new member. I think bootmem:1 member
 is just for convenience. I think I can remove it. :)

Larger size slab allocations may fall back to the page allocator but then
the slabs do not track this allocation. That memory can be freed using the
page allocator.

If you see pageslab then you can always remove using the slab allocator.
Otherwise the page allocator should work (unless it was some
special case bootmem allocation).

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v5 04/14] memory-hotplug: remove /sys/firmware/memmap/X sysfs

2012-12-26 Thread Tang Chen
On 12/26/2012 11:30 AM, Kamezawa Hiroyuki wrote:
 @@ -41,6 +42,7 @@ struct firmware_map_entry {
  const char  *type;  /* type of the memory range */
  struct list_headlist;   /* entry for the linked list */
  struct kobject  kobj;   /* kobject for each entry */
 +unsigned intbootmem:1; /* allocated from bootmem */
};
 
 Can't we detect from which the object is allocated from, slab or bootmem ?
 
 Hm, for example,
 
  PageReserved(virt_to_page(address_of_obj)) ?
  PageSlab(virt_to_page(address_of_obj)) ?
 

Hi Kamezawa-san,

I think we can detect it without a new member. I think bootmem:1 member
is just for convenience. I think I can remove it. :)

Thanks. :)
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v5 04/14] memory-hotplug: remove /sys/firmware/memmap/X sysfs

2012-12-25 Thread Kamezawa Hiroyuki
(2012/12/24 21:09), Tang Chen wrote:
 From: Yasuaki Ishimatsu isimatu.yasu...@jp.fujitsu.com
 
 When (hot)adding memory into system, /sys/firmware/memmap/X/{end, start, type}
 sysfs files are created. But there is no code to remove these files. The patch
 implements the function to remove them.
 
 Note: The code does not free firmware_map_entry which is allocated by bootmem.
So the patch makes memory leak. But I think the memory leak size is
very samll. And it does not affect the system.
 
 Signed-off-by: Wen Congyang we...@cn.fujitsu.com
 Signed-off-by: Yasuaki Ishimatsu isimatu.yasu...@jp.fujitsu.com
 ---
   drivers/firmware/memmap.c|   98 
 +-
   include/linux/firmware-map.h |6 +++
   mm/memory_hotplug.c  |5 ++-
   3 files changed, 106 insertions(+), 3 deletions(-)
 
 diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
 index 90723e6..49be12a 100644
 --- a/drivers/firmware/memmap.c
 +++ b/drivers/firmware/memmap.c
 @@ -21,6 +21,7 @@
   #include linux/types.h
   #include linux/bootmem.h
   #include linux/slab.h
 +#include linux/mm.h
   
   /*
* Data types 
 --
 @@ -41,6 +42,7 @@ struct firmware_map_entry {
   const char  *type;  /* type of the memory range */
   struct list_headlist;   /* entry for the linked list */
   struct kobject  kobj;   /* kobject for each entry */
 + unsigned intbootmem:1; /* allocated from bootmem */
   };

Can't we detect from which the object is allocated from, slab or bootmem ?

Hm, for example,

PageReserved(virt_to_page(address_of_obj)) ?
PageSlab(virt_to_page(address_of_obj)) ?

Thanks,
-Kame

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v5 04/14] memory-hotplug: remove /sys/firmware/memmap/X sysfs

2012-12-24 Thread Tang Chen
From: Yasuaki Ishimatsu isimatu.yasu...@jp.fujitsu.com

When (hot)adding memory into system, /sys/firmware/memmap/X/{end, start, type}
sysfs files are created. But there is no code to remove these files. The patch
implements the function to remove them.

Note: The code does not free firmware_map_entry which is allocated by bootmem.
  So the patch makes memory leak. But I think the memory leak size is
  very samll. And it does not affect the system.

Signed-off-by: Wen Congyang we...@cn.fujitsu.com
Signed-off-by: Yasuaki Ishimatsu isimatu.yasu...@jp.fujitsu.com
---
 drivers/firmware/memmap.c|   98 +-
 include/linux/firmware-map.h |6 +++
 mm/memory_hotplug.c  |5 ++-
 3 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 90723e6..49be12a 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -21,6 +21,7 @@
 #include linux/types.h
 #include linux/bootmem.h
 #include linux/slab.h
+#include linux/mm.h
 
 /*
  * Data types 
--
@@ -41,6 +42,7 @@ struct firmware_map_entry {
const char  *type;  /* type of the memory range */
struct list_headlist;   /* entry for the linked list */
struct kobject  kobj;   /* kobject for each entry */
+   unsigned intbootmem:1; /* allocated from bootmem */
 };
 
 /*
@@ -79,7 +81,26 @@ static const struct sysfs_ops memmap_attr_ops = {
.show = memmap_attr_show,
 };
 
+
+static inline struct firmware_map_entry *
+to_memmap_entry(struct kobject *kobj)
+{
+   return container_of(kobj, struct firmware_map_entry, kobj);
+}
+
+static void release_firmware_map_entry(struct kobject *kobj)
+{
+   struct firmware_map_entry *entry = to_memmap_entry(kobj);
+
+   if (entry-bootmem)
+   /* There is no way to free memory allocated from bootmem */
+   return;
+
+   kfree(entry);
+}
+
 static struct kobj_type memmap_ktype = {
+   .release= release_firmware_map_entry,
.sysfs_ops  = memmap_attr_ops,
.default_attrs  = def_attrs,
 };
@@ -94,6 +115,7 @@ static struct kobj_type memmap_ktype = {
  * in firmware initialisation code in one single thread of execution.
  */
 static LIST_HEAD(map_entries);
+static DEFINE_SPINLOCK(map_entries_lock);
 
 /**
  * firmware_map_add_entry() - Does the real work to add a firmware memmap 
entry.
@@ -118,11 +140,25 @@ static int firmware_map_add_entry(u64 start, u64 end,
INIT_LIST_HEAD(entry-list);
kobject_init(entry-kobj, memmap_ktype);
 
+   spin_lock(map_entries_lock);
list_add_tail(entry-list, map_entries);
+   spin_unlock(map_entries_lock);
 
return 0;
 }
 
+/**
+ * firmware_map_remove_entry() - Does the real work to remove a firmware
+ * memmap entry.
+ * @entry: removed entry.
+ **/
+static inline void firmware_map_remove_entry(struct firmware_map_entry *entry)
+{
+   spin_lock(map_entries_lock);
+   list_del(entry-list);
+   spin_unlock(map_entries_lock);
+}
+
 /*
  * Add memmap entry on sysfs
  */
@@ -144,6 +180,35 @@ static int add_sysfs_fw_map_entry(struct 
firmware_map_entry *entry)
return 0;
 }
 
+/*
+ * Remove memmap entry on sysfs
+ */
+static inline void remove_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+   kobject_put(entry-kobj);
+}
+
+/*
+ * Search memmap entry
+ */
+
+static struct firmware_map_entry * __meminit
+firmware_map_find_entry(u64 start, u64 end, const char *type)
+{
+   struct firmware_map_entry *entry;
+
+   spin_lock(map_entries_lock);
+   list_for_each_entry(entry, map_entries, list)
+   if ((entry-start == start)  (entry-end == end) 
+   (!strcmp(entry-type, type))) {
+   spin_unlock(map_entries_lock);
+   return entry;
+   }
+
+   spin_unlock(map_entries_lock);
+   return NULL;
+}
+
 /**
  * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
  * memory hotplug.
@@ -193,9 +258,36 @@ int __init firmware_map_add_early(u64 start, u64 end, 
const char *type)
if (WARN_ON(!entry))
return -ENOMEM;
 
+   entry-bootmem = 1;
return firmware_map_add_entry(start, end, type, entry);
 }
 
+/**
+ * firmware_map_remove() - remove a firmware mapping entry
+ * @start: Start of the memory range.
+ * @end:   End of the memory range.
+ * @type:  Type of the memory range.
+ *
+ * removes a firmware mapping entry.
+ *
+ * Returns 0 on success, or -EINVAL if no entry.
+ **/
+int __meminit firmware_map_remove(u64 start, u64 end, const char *type)
+{
+   struct firmware_map_entry *entry;
+
+   entry = firmware_map_find_entry(start, end - 1, type);
+   if (!entry)
+   return -EINVAL;
+
+   firmware_map_remove_entry(entry);
+
+   /* remove the