diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memory_hotplug.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 26f1840879d6..c37319542b70 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -52,6 +52,9 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn) | |||
52 | int nr_pages = PAGES_PER_SECTION; | 52 | int nr_pages = PAGES_PER_SECTION; |
53 | int ret; | 53 | int ret; |
54 | 54 | ||
55 | if (pfn_valid(phys_start_pfn)) | ||
56 | return -EEXIST; | ||
57 | |||
55 | ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); | 58 | ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); |
56 | 59 | ||
57 | if (ret < 0) | 60 | if (ret < 0) |
@@ -220,10 +223,9 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat) | |||
220 | } | 223 | } |
221 | 224 | ||
222 | /* add this memory to iomem resource */ | 225 | /* add this memory to iomem resource */ |
223 | static int register_memory_resource(u64 start, u64 size) | 226 | static struct resource *register_memory_resource(u64 start, u64 size) |
224 | { | 227 | { |
225 | struct resource *res; | 228 | struct resource *res; |
226 | int ret = 0; | ||
227 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); | 229 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); |
228 | BUG_ON(!res); | 230 | BUG_ON(!res); |
229 | 231 | ||
@@ -235,9 +237,18 @@ static int register_memory_resource(u64 start, u64 size) | |||
235 | printk("System RAM resource %llx - %llx cannot be added\n", | 237 | printk("System RAM resource %llx - %llx cannot be added\n", |
236 | (unsigned long long)res->start, (unsigned long long)res->end); | 238 | (unsigned long long)res->start, (unsigned long long)res->end); |
237 | kfree(res); | 239 | kfree(res); |
238 | ret = -EEXIST; | 240 | res = NULL; |
239 | } | 241 | } |
240 | return ret; | 242 | return res; |
243 | } | ||
244 | |||
245 | static void release_memory_resource(struct resource *res) | ||
246 | { | ||
247 | if (!res) | ||
248 | return; | ||
249 | release_resource(res); | ||
250 | kfree(res); | ||
251 | return; | ||
241 | } | 252 | } |
242 | 253 | ||
243 | 254 | ||
@@ -246,8 +257,13 @@ int add_memory(int nid, u64 start, u64 size) | |||
246 | { | 257 | { |
247 | pg_data_t *pgdat = NULL; | 258 | pg_data_t *pgdat = NULL; |
248 | int new_pgdat = 0; | 259 | int new_pgdat = 0; |
260 | struct resource *res; | ||
249 | int ret; | 261 | int ret; |
250 | 262 | ||
263 | res = register_memory_resource(start, size); | ||
264 | if (!res) | ||
265 | return -EEXIST; | ||
266 | |||
251 | if (!node_online(nid)) { | 267 | if (!node_online(nid)) { |
252 | pgdat = hotadd_new_pgdat(nid, start); | 268 | pgdat = hotadd_new_pgdat(nid, start); |
253 | if (!pgdat) | 269 | if (!pgdat) |
@@ -277,14 +293,13 @@ int add_memory(int nid, u64 start, u64 size) | |||
277 | BUG_ON(ret); | 293 | BUG_ON(ret); |
278 | } | 294 | } |
279 | 295 | ||
280 | /* register this memory as resource */ | ||
281 | ret = register_memory_resource(start, size); | ||
282 | |||
283 | return ret; | 296 | return ret; |
284 | error: | 297 | error: |
285 | /* rollback pgdat allocation and others */ | 298 | /* rollback pgdat allocation and others */ |
286 | if (new_pgdat) | 299 | if (new_pgdat) |
287 | rollback_node_hotadd(nid, pgdat); | 300 | rollback_node_hotadd(nid, pgdat); |
301 | if (res) | ||
302 | release_memory_resource(res); | ||
288 | 303 | ||
289 | return ret; | 304 | return ret; |
290 | } | 305 | } |