static int cmm_oom_notify(struct notifier_block *self, unsigned long dummy, void *parm) { unsigned long *freed = parm; long nr = 256; nr = cmm_free_pages(nr, &cmm_timed_pages, &cmm_timed_page_list); if (nr > 0) nr = cmm_free_pages(nr, &cmm_pages, &cmm_page_list); cmm_pages_target = cmm_pages; cmm_timed_pages_target = cmm_timed_pages; *freed += 256 - nr; return NOTIFY_OK; }
static void cmm_exit(void) { cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); #ifdef CONFIG_CMM_PROC unregister_sysctl_table(cmm_sysctl_header); #endif #ifdef CONFIG_CMM_IUCV smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); #endif /* Allow logical cpu 0 to be set offline again. */ smp_put_cpu(0); }
static void cmm_exit(void) { #ifdef CONFIG_CMM_PROC unregister_sysctl_table(cmm_sysctl_header); #endif #ifdef CONFIG_CMM_IUCV smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); #endif unregister_oom_notifier(&cmm_oom_nb); kthread_stop(cmm_thread_ptr); del_timer_sync(&cmm_timer); cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); }
/** * cmm_exit - Module exit * * Return value: * nothing **/ static void cmm_exit(void) { if (cmm_thread_ptr) kthread_stop(cmm_thread_ptr); unregister_oom_notifier(&cmm_oom_nb); cmm_free_pages(loaned_pages); cmm_unregister_sysfs(&cmm_sysdev); }
/** * cmm_reboot_notifier - Make sure pages are not still marked as "loaned" * **/ static int cmm_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) { if (action == SYS_RESTART) { if (cmm_thread_ptr) kthread_stop(cmm_thread_ptr); cmm_thread_ptr = NULL; cmm_free_pages(loaned_pages); } return NOTIFY_DONE; }
/** * cmm_exit - Module exit * * Return value: * nothing **/ static void cmm_exit(void) { if (cmm_thread_ptr) kthread_stop(cmm_thread_ptr); unregister_oom_notifier(&cmm_oom_nb); unregister_reboot_notifier(&cmm_reboot_nb); unregister_memory_notifier(&cmm_mem_nb); unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); cmm_free_pages(loaned_pages); cmm_unregister_sysfs(&cmm_dev); }
/** * cmm_oom_notify - OOM notifier * @self: notifier block struct * @dummy: not used * @parm: returned - number of pages freed * * Return value: * NOTIFY_OK **/ static int cmm_oom_notify(struct notifier_block *self, unsigned long dummy, void *parm) { unsigned long *freed = parm; long nr = KB2PAGES(oom_kb); cmm_dbg("OOM processing started\n"); nr = cmm_free_pages(nr); loaned_pages_target = loaned_pages; *freed += KB2PAGES(oom_kb) - nr; oom_freed_pages += KB2PAGES(oom_kb) - nr; cmm_dbg("OOM processing complete\n"); return NOTIFY_OK; }
static int cmm_thread(void *dummy) { int rc; daemonize("cmmthread"); set_cpus_allowed(current, cpumask_of_cpu(0)); while (1) { rc = wait_event_interruptible(cmm_thread_wait, (cmm_pages != cmm_pages_target || cmm_timed_pages != cmm_timed_pages_target)); if (rc == -ERESTARTSYS) { /* Got kill signal. End thread. */ clear_bit(0, &cmm_thread_active); cmm_pages_target = cmm_pages; cmm_timed_pages_target = cmm_timed_pages; break; } if (cmm_pages_target > cmm_pages) { if (cmm_alloc_pages(1, &cmm_pages, &cmm_page_list)) cmm_pages_target = cmm_pages; } else if (cmm_pages_target < cmm_pages) { cmm_free_pages(1, &cmm_pages, &cmm_page_list); } if (cmm_timed_pages_target > cmm_timed_pages) { if (cmm_alloc_pages(1, &cmm_timed_pages, &cmm_timed_page_list)) cmm_timed_pages_target = cmm_timed_pages; } else if (cmm_timed_pages_target < cmm_timed_pages) { cmm_free_pages(1, &cmm_timed_pages, &cmm_timed_page_list); } if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) cmm_set_timer(); } return 0; }
/** * cmm_thread - CMM task thread * @dummy: not used * * Return value: * 0 **/ static int cmm_thread(void *dummy) { unsigned long timeleft; while (1) { timeleft = msleep_interruptible(delay * 1000); if (kthread_should_stop() || timeleft) break; if (mutex_trylock(&hotplug_mutex)) { if (hotplug_occurred) { hotplug_occurred = 0; mutex_unlock(&hotplug_mutex); cmm_dbg("Hotplug operation has occurred, " "loaning activity suspended " "for %d seconds.\n", hotplug_delay); timeleft = msleep_interruptible(hotplug_delay * 1000); if (kthread_should_stop() || timeleft) break; continue; } mutex_unlock(&hotplug_mutex); } else { cmm_dbg("Hotplug operation in progress, activity " "suspended\n"); continue; } cmm_get_mpp(); if (loaned_pages_target > loaned_pages) { if (cmm_alloc_pages(loaned_pages_target - loaned_pages)) loaned_pages_target = loaned_pages; } else if (loaned_pages_target < loaned_pages) cmm_free_pages(loaned_pages - loaned_pages_target); } return 0; }
/** * cmm_set_disable - Disable/Enable CMM * * Return value: * 0 on success / other on failure **/ static int cmm_set_disable(const char *val, struct kernel_param *kp) { int disable = simple_strtoul(val, NULL, 10); if (disable != 0 && disable != 1) return -EINVAL; if (disable && !cmm_disabled) { if (cmm_thread_ptr) kthread_stop(cmm_thread_ptr); cmm_thread_ptr = NULL; cmm_free_pages(loaned_pages); } else if (!disable && cmm_disabled) { cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); if (IS_ERR(cmm_thread_ptr)) return PTR_ERR(cmm_thread_ptr); } cmm_disabled = disable; return 0; }
/** * cmm_thread - CMM task thread * @dummy: not used * * Return value: * 0 **/ static int cmm_thread(void *dummy) { unsigned long timeleft; while (1) { timeleft = msleep_interruptible(delay * 1000); if (kthread_should_stop() || timeleft) { loaned_pages_target = loaned_pages; break; } cmm_get_mpp(); if (loaned_pages_target > loaned_pages) { if (cmm_alloc_pages(loaned_pages_target - loaned_pages)) loaned_pages_target = loaned_pages; } else if (loaned_pages_target < loaned_pages) cmm_free_pages(loaned_pages - loaned_pages_target); } return 0; }