History

powerpc/pseries/cmm: Convert loaned_pages to an atomic_long_t

When switching to balloon compaction, we want to drop the cmm_lock and completely rely on the balloon compaction list lock internally. loaned_pages is currently protected under the cmm_lock. Note: Right now cmm_alloc_pages() and cmm_free_pages() can be called at the same time, e.g., via the thread and a concurrent OOM notifier.

David Hildenbrand committed 7 years ago

Commit 1ef2f061 parent 7659f5d1 file · +19 −16Browse files

Unified · Split

arch/powerpc/platforms/pseries/cmm.c+19−16
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(debug, "Enable module debugging logging. Set to 1 to enable. " · 72 unmodified lines
73 73
74#define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); }74#define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); }
75 75
76static unsigned long loaned_pages;76static atomic_long_t loaned_pages;
77static unsigned long loaned_pages_target;77static unsigned long loaned_pages_target;
78static unsigned long oom_freed_pages;78static unsigned long oom_freed_pages;
79 79
@@ -159,7 +159,7 @@ static long cmm_alloc_pages(long nr) · 79 unmodified lines
159 }159 }
160 160
161 list_add(&page->lru, &cmm_page_list);161 list_add(&page->lru, &cmm_page_list);
162 loaned_pages++;162 atomic_long_inc(&loaned_pages);
163 adjust_managed_page_count(page, -1);163 adjust_managed_page_count(page, -1);
164 spin_unlock(&cmm_lock);164 spin_unlock(&cmm_lock);
165 nr--;165 nr--;
@@ -189,7 +189,7 @@ static long cmm_free_pages(long nr) · 23 unmodified lines
189 list_del(&page->lru);189 list_del(&page->lru);
190 adjust_managed_page_count(page, 1);190 adjust_managed_page_count(page, 1);
191 __free_page(page);191 __free_page(page);
192 loaned_pages--;192 atomic_long_dec(&loaned_pages);
193 nr--;193 nr--;
194 }194 }
195 spin_unlock(&cmm_lock);195 spin_unlock(&cmm_lock);
@@ -214,7 +214,7 @@ static int cmm_oom_notify(struct notifier_block *self, · 18 unmodified lines
214 214
215 cmm_dbg("OOM processing started\n");215 cmm_dbg("OOM processing started\n");
216 nr = cmm_free_pages(nr);216 nr = cmm_free_pages(nr);
217 loaned_pages_target = loaned_pages;217 loaned_pages_target = atomic_long_read(&loaned_pages);
218 *freed += KB2PAGES(oom_kb) - nr;218 *freed += KB2PAGES(oom_kb) - nr;
219 oom_freed_pages += KB2PAGES(oom_kb) - nr;219 oom_freed_pages += KB2PAGES(oom_kb) - nr;
220 cmm_dbg("OOM processing complete\n");220 cmm_dbg("OOM processing complete\n");
@@ -231,10 +231,11 @@ static int cmm_oom_notify(struct notifier_block *self, · 10 unmodified lines
231 **/231 **/
232static void cmm_get_mpp(void)232static void cmm_get_mpp(void)
233{233{
234 const long __loaned_pages = atomic_long_read(&loaned_pages);
235 const long total_pages = totalram_pages() + __loaned_pages;
234 int rc;236 int rc;
235 struct hvcall_mpp_data mpp_data;237 struct hvcall_mpp_data mpp_data;
236 signed long active_pages_target, page_loan_request, target;238 signed long active_pages_target, page_loan_request, target;
237 signed long total_pages = totalram_pages() + loaned_pages;
238 signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE;239 signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE;
239 240
240 rc = h_get_mpp(&mpp_data);241 rc = h_get_mpp(&mpp_data);
@@ -243,7 +244,7 @@ static void cmm_get_mpp(void) · 2 unmodified lines
243 return;244 return;
244 245
245 page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE);246 page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE);
246 target = page_loan_request + (signed long)loaned_pages;247 target = page_loan_request + __loaned_pages;
247 248
248 if (target < 0 || total_pages < min_mem_pages)249 if (target < 0 || total_pages < min_mem_pages)
249 target = 0;250 target = 0;
@@ -264,7 +265,7 @@ static void cmm_get_mpp(void) · 14 unmodified lines
264 loaned_pages_target = target;265 loaned_pages_target = target;
265 266
266 cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",267 cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",
267 page_loan_request, loaned_pages, loaned_pages_target,268 page_loan_request, __loaned_pages, loaned_pages_target,
268 oom_freed_pages, totalram_pages());269 oom_freed_pages, totalram_pages());
269}270}
270 271
@@ -282,6 +283,7 @@ static struct notifier_block cmm_oom_nb = { · 11 unmodified lines
282static int cmm_thread(void *dummy)283static int cmm_thread(void *dummy)
283{284{
284 unsigned long timeleft;285 unsigned long timeleft;
286 long __loaned_pages;
285 287
286 while (1) {288 while (1) {
287 timeleft = msleep_interruptible(delay * 1000);289 timeleft = msleep_interruptible(delay * 1000);
@@ -312,11 +314,12 @@ static int cmm_thread(void *dummy) · 24 unmodified lines
312 314
313 cmm_get_mpp();315 cmm_get_mpp();
314 316
315 if (loaned_pages_target > loaned_pages) {317 __loaned_pages = atomic_long_read(&loaned_pages);
316 if (cmm_alloc_pages(loaned_pages_target - loaned_pages))318 if (loaned_pages_target > __loaned_pages) {
317 loaned_pages_target = loaned_pages;319 if (cmm_alloc_pages(loaned_pages_target - __loaned_pages))
318 } else if (loaned_pages_target < loaned_pages)320 loaned_pages_target = __loaned_pages;
319 cmm_free_pages(loaned_pages - loaned_pages_target);321 } else if (loaned_pages_target < __loaned_pages)
322 cmm_free_pages(__loaned_pages - loaned_pages_target);
320 }323 }
321 return 0;324 return 0;
322}325}
@@ -330,7 +333,7 @@ static int cmm_thread(void *dummy) · 7 unmodified lines
330 } \333 } \
331 static DEVICE_ATTR(name, 0444, show_##name, NULL)334 static DEVICE_ATTR(name, 0444, show_##name, NULL)
332 335
333CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages));336CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(atomic_long_read(&loaned_pages)));
334CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));337CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
335 338
336static ssize_t show_oom_pages(struct device *dev,339static ssize_t show_oom_pages(struct device *dev,
@@ -433,7 +436,7 @@ static int cmm_reboot_notifier(struct notifier_block *nb, · 96 unmodified lines
433 if (cmm_thread_ptr)436 if (cmm_thread_ptr)
434 kthread_stop(cmm_thread_ptr);437 kthread_stop(cmm_thread_ptr);
435 cmm_thread_ptr = NULL;438 cmm_thread_ptr = NULL;
436 cmm_free_pages(loaned_pages);439 cmm_free_pages(atomic_long_read(&loaned_pages));
437 }440 }
438 return NOTIFY_DONE;441 return NOTIFY_DONE;
439}442}
@@ -540,7 +543,7 @@ static void cmm_exit(void) · 100 unmodified lines
540 unregister_oom_notifier(&cmm_oom_nb);543 unregister_oom_notifier(&cmm_oom_nb);
541 unregister_reboot_notifier(&cmm_reboot_nb);544 unregister_reboot_notifier(&cmm_reboot_nb);
542 unregister_memory_notifier(&cmm_mem_nb);545 unregister_memory_notifier(&cmm_mem_nb);
543 cmm_free_pages(loaned_pages);546 cmm_free_pages(atomic_long_read(&loaned_pages));
544 cmm_unregister_sysfs(&cmm_dev);547 cmm_unregister_sysfs(&cmm_dev);
545}548}
546 549
@@ -561,7 +564,7 @@ static int cmm_set_disable(const char *val, const struct kernel_param *kp) · 14 unmodified lines
561 if (cmm_thread_ptr)564 if (cmm_thread_ptr)
562 kthread_stop(cmm_thread_ptr);565 kthread_stop(cmm_thread_ptr);
563 cmm_thread_ptr = NULL;566 cmm_thread_ptr = NULL;
564 cmm_free_pages(loaned_pages);567 cmm_free_pages(atomic_long_read(&loaned_pages));
565 } else if (!disable && cmm_disabled) {568 } else if (!disable && cmm_disabled) {
566 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");569 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
567 if (IS_ERR(cmm_thread_ptr))570 if (IS_ERR(cmm_thread_ptr))