Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70614ef6 authored by Zhenhua Huang's avatar Zhenhua Huang Committed by Gerrit - the friendly Code Review server
Browse files

Revert "Revert "ANDROID: Communicates LMK events to userland where they can be logged""



This reverts commit 9fd99422.
The feature caused crash so we may wait until it's stable.

Change-Id: Ibb5d9326dc9fde344dd76308878d7f106d21035a
Signed-off-by: default avatarZhenhua Huang <zhenhuah@codeaurora.org>
parent 97bb7bb6
Loading
Loading
Loading
Loading
+0 −157
Original line number Diff line number Diff line
@@ -98,159 +98,6 @@ 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;
	char taskname[MAX_TASKNAME];
	struct mm_struct *mm = get_task_mm(selected);

	if (mm) {
		rss_in_pages = get_mm_rss(mm);
		mmput(mm);
	}

	res = get_cmdline(selected, taskname, MAX_TASKNAME - 1);

	/* No valid process name means this is definitely not associated with a
	 * userspace activity.
	 */

	if (res <= 0 || res >= MAX_TASKNAME)
		return;

	taskname[res] = '\0';

	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];

	memcpy(event->taskname, taskname, res + 1);

	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)
{
@@ -802,9 +649,6 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
		     sc->nr_to_scan, sc->gfp_mask, rem);
	mutex_unlock(&scan_mutex);

	if (selected)
		handle_lmk_event(selected, min_score_adj);

	return rem;
}

@@ -818,7 +662,6 @@ 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);