Loading drivers/staging/android/lowmemorykiller.c +153 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,157 @@ static unsigned long lowmem_deathpending_timeout; pr_info(x); \ } while (0) static DECLARE_WAIT_QUEUE_HEAD(event_wait); static DEFINE_SPINLOCK(lmk_event_lock); static struct circ_buf event_buffer; #define MAX_BUFFERED_EVENTS 8 #define MAX_TASKNAME 128 struct lmk_event { char taskname[MAX_TASKNAME]; pid_t pid; uid_t uid; pid_t group_leader_pid; unsigned long min_flt; unsigned long maj_flt; unsigned long rss_in_pages; short oom_score_adj; short min_score_adj; unsigned long long start_time; struct list_head list; }; void handle_lmk_event(struct task_struct *selected, short min_score_adj) { int head; int tail; struct lmk_event *events; struct lmk_event *event; int res; long rss_in_pages = -1; struct mm_struct *mm = get_task_mm(selected); if (mm) { rss_in_pages = get_mm_rss(mm); mmput(mm); } spin_lock(&lmk_event_lock); head = event_buffer.head; tail = READ_ONCE(event_buffer.tail); /* Do not continue to log if no space remains in the buffer. */ if (CIRC_SPACE(head, tail, MAX_BUFFERED_EVENTS) < 1) { spin_unlock(&lmk_event_lock); return; } events = (struct lmk_event *) event_buffer.buf; event = &events[head]; res = get_cmdline(selected, event->taskname, MAX_TASKNAME - 1); /* No valid process name means this is definitely not associated with a * userspace activity. */ if (res <= 0 || res >= MAX_TASKNAME) { spin_unlock(&lmk_event_lock); return; } event->taskname[res] = '\0'; event->pid = selected->pid; event->uid = from_kuid_munged(current_user_ns(), task_uid(selected)); if (selected->group_leader) event->group_leader_pid = selected->group_leader->pid; else event->group_leader_pid = -1; event->min_flt = selected->min_flt; event->maj_flt = selected->maj_flt; event->oom_score_adj = selected->signal->oom_score_adj; event->start_time = nsec_to_clock_t(selected->real_start_time); event->rss_in_pages = rss_in_pages; event->min_score_adj = min_score_adj; event_buffer.head = (head + 1) & (MAX_BUFFERED_EVENTS - 1); spin_unlock(&lmk_event_lock); wake_up_interruptible(&event_wait); } static int lmk_event_show(struct seq_file *s, void *unused) { struct lmk_event *events = (struct lmk_event *) event_buffer.buf; int head; int tail; struct lmk_event *event; spin_lock(&lmk_event_lock); head = event_buffer.head; tail = event_buffer.tail; if (head == tail) { spin_unlock(&lmk_event_lock); return -EAGAIN; } event = &events[tail]; seq_printf(s, "%lu %lu %lu %lu %lu %lu %hd %hd %llu\n%s\n", (unsigned long) event->pid, (unsigned long) event->uid, (unsigned long) event->group_leader_pid, event->min_flt, event->maj_flt, event->rss_in_pages, event->oom_score_adj, event->min_score_adj, event->start_time, event->taskname); event_buffer.tail = (tail + 1) & (MAX_BUFFERED_EVENTS - 1); spin_unlock(&lmk_event_lock); return 0; } static unsigned int lmk_event_poll(struct file *file, poll_table *wait) { int ret = 0; poll_wait(file, &event_wait, wait); spin_lock(&lmk_event_lock); if (event_buffer.head != event_buffer.tail) ret = POLLIN; spin_unlock(&lmk_event_lock); return ret; } static int lmk_event_open(struct inode *inode, struct file *file) { return single_open(file, lmk_event_show, inode->i_private); } static const struct file_operations event_file_ops = { .open = lmk_event_open, .poll = lmk_event_poll, .read = seq_read }; static void lmk_event_init(void) { struct proc_dir_entry *entry; event_buffer.head = 0; event_buffer.tail = 0; event_buffer.buf = kmalloc( sizeof(struct lmk_event) * MAX_BUFFERED_EVENTS, GFP_KERNEL); if (!event_buffer.buf) return; entry = proc_create("lowmemorykiller", 0, NULL, &event_file_ops); if (!entry) pr_err("error creating kernel lmk event file\n"); } static unsigned long lowmem_count(struct shrinker *s, struct shrink_control *sc) { Loading Loading @@ -635,6 +786,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; rcu_read_unlock(); handle_lmk_event(selected, min_score_adj); /* give the system time to free up the memory */ msleep_interruptible(20); trace_almk_shrink(selected_tasksize, ret, Loading Loading @@ -662,6 +814,7 @@ static int __init lowmem_init(void) { register_shrinker(&lowmem_shrinker); vmpressure_notifier_register(&lmk_vmpr_nb); lmk_event_init(); return 0; } device_initcall(lowmem_init); Loading Loading
drivers/staging/android/lowmemorykiller.c +153 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,157 @@ static unsigned long lowmem_deathpending_timeout; pr_info(x); \ } while (0) static DECLARE_WAIT_QUEUE_HEAD(event_wait); static DEFINE_SPINLOCK(lmk_event_lock); static struct circ_buf event_buffer; #define MAX_BUFFERED_EVENTS 8 #define MAX_TASKNAME 128 struct lmk_event { char taskname[MAX_TASKNAME]; pid_t pid; uid_t uid; pid_t group_leader_pid; unsigned long min_flt; unsigned long maj_flt; unsigned long rss_in_pages; short oom_score_adj; short min_score_adj; unsigned long long start_time; struct list_head list; }; void handle_lmk_event(struct task_struct *selected, short min_score_adj) { int head; int tail; struct lmk_event *events; struct lmk_event *event; int res; long rss_in_pages = -1; struct mm_struct *mm = get_task_mm(selected); if (mm) { rss_in_pages = get_mm_rss(mm); mmput(mm); } spin_lock(&lmk_event_lock); head = event_buffer.head; tail = READ_ONCE(event_buffer.tail); /* Do not continue to log if no space remains in the buffer. */ if (CIRC_SPACE(head, tail, MAX_BUFFERED_EVENTS) < 1) { spin_unlock(&lmk_event_lock); return; } events = (struct lmk_event *) event_buffer.buf; event = &events[head]; res = get_cmdline(selected, event->taskname, MAX_TASKNAME - 1); /* No valid process name means this is definitely not associated with a * userspace activity. */ if (res <= 0 || res >= MAX_TASKNAME) { spin_unlock(&lmk_event_lock); return; } event->taskname[res] = '\0'; event->pid = selected->pid; event->uid = from_kuid_munged(current_user_ns(), task_uid(selected)); if (selected->group_leader) event->group_leader_pid = selected->group_leader->pid; else event->group_leader_pid = -1; event->min_flt = selected->min_flt; event->maj_flt = selected->maj_flt; event->oom_score_adj = selected->signal->oom_score_adj; event->start_time = nsec_to_clock_t(selected->real_start_time); event->rss_in_pages = rss_in_pages; event->min_score_adj = min_score_adj; event_buffer.head = (head + 1) & (MAX_BUFFERED_EVENTS - 1); spin_unlock(&lmk_event_lock); wake_up_interruptible(&event_wait); } static int lmk_event_show(struct seq_file *s, void *unused) { struct lmk_event *events = (struct lmk_event *) event_buffer.buf; int head; int tail; struct lmk_event *event; spin_lock(&lmk_event_lock); head = event_buffer.head; tail = event_buffer.tail; if (head == tail) { spin_unlock(&lmk_event_lock); return -EAGAIN; } event = &events[tail]; seq_printf(s, "%lu %lu %lu %lu %lu %lu %hd %hd %llu\n%s\n", (unsigned long) event->pid, (unsigned long) event->uid, (unsigned long) event->group_leader_pid, event->min_flt, event->maj_flt, event->rss_in_pages, event->oom_score_adj, event->min_score_adj, event->start_time, event->taskname); event_buffer.tail = (tail + 1) & (MAX_BUFFERED_EVENTS - 1); spin_unlock(&lmk_event_lock); return 0; } static unsigned int lmk_event_poll(struct file *file, poll_table *wait) { int ret = 0; poll_wait(file, &event_wait, wait); spin_lock(&lmk_event_lock); if (event_buffer.head != event_buffer.tail) ret = POLLIN; spin_unlock(&lmk_event_lock); return ret; } static int lmk_event_open(struct inode *inode, struct file *file) { return single_open(file, lmk_event_show, inode->i_private); } static const struct file_operations event_file_ops = { .open = lmk_event_open, .poll = lmk_event_poll, .read = seq_read }; static void lmk_event_init(void) { struct proc_dir_entry *entry; event_buffer.head = 0; event_buffer.tail = 0; event_buffer.buf = kmalloc( sizeof(struct lmk_event) * MAX_BUFFERED_EVENTS, GFP_KERNEL); if (!event_buffer.buf) return; entry = proc_create("lowmemorykiller", 0, NULL, &event_file_ops); if (!entry) pr_err("error creating kernel lmk event file\n"); } static unsigned long lowmem_count(struct shrinker *s, struct shrink_control *sc) { Loading Loading @@ -635,6 +786,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; rcu_read_unlock(); handle_lmk_event(selected, min_score_adj); /* give the system time to free up the memory */ msleep_interruptible(20); trace_almk_shrink(selected_tasksize, ret, Loading Loading @@ -662,6 +814,7 @@ static int __init lowmem_init(void) { register_shrinker(&lowmem_shrinker); vmpressure_notifier_register(&lmk_vmpr_nb); lmk_event_init(); return 0; } device_initcall(lowmem_init); Loading