ANDROID: Avoid taking multiple locks in handle_lmk_event
Conflicting lock events have been reported resulting from rcu_read_lock, mmap_sem (in get_cmdline) and lmk_event_lock. This CL avoids the possibility of these conditions by moving handle_lmk_event outside rcu_read_lock and invoking get_cmdline before lmk_event_lock is taken. Bug: 133479338, 133829075 Signed-off-by: Jim Blackler <jimblackler@google.com> Change-Id: Ib3c32587472bd972e3ac108798e2af3f4a5c329a
This commit is contained in:
parent
bcb576e1a7
commit
dd842551d5
1 changed files with 17 additions and 13 deletions
|
@ -102,6 +102,7 @@ void handle_lmk_event(struct task_struct *selected, short min_score_adj)
|
|||
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) {
|
||||
|
@ -109,6 +110,17 @@ void handle_lmk_event(struct task_struct *selected, short min_score_adj)
|
|||
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;
|
||||
|
@ -123,18 +135,8 @@ void handle_lmk_event(struct task_struct *selected, short min_score_adj)
|
|||
events = (struct lmk_event *) event_buffer.buf;
|
||||
event = &events[head];
|
||||
|
||||
res = get_cmdline(selected, event->taskname, MAX_TASKNAME - 1);
|
||||
memcpy(event->taskname, taskname, res + 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)
|
||||
|
@ -344,13 +346,15 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
|
|||
free);
|
||||
lowmem_deathpending_timeout = jiffies + HZ;
|
||||
rem += selected_tasksize;
|
||||
|
||||
handle_lmk_event(selected, min_score_adj);
|
||||
}
|
||||
|
||||
lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
|
||||
sc->nr_to_scan, sc->gfp_mask, rem);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (selected)
|
||||
handle_lmk_event(selected, min_score_adj);
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue