From c6724bfedaadcbe81f7985f938d22c3701e6cee8 Mon Sep 17 00:00:00 2001 From: Peifeng Li Date: Tue, 19 Sep 2023 17:35:11 +0800 Subject: [PATCH] ANDROID: uid_sys_stat: instead update_io_stats_uid_locked to update_io_stats_uid Update_io_stats_uid_locked would take a long lock-time of uid_lock due to call do_each_thread to compute uid_entry->io, which would cause to lock competition sometime. Using uid_entry_tmp to get the result of update_io_stats_uid, so that we can unlock_uid during update_io_stats_uid, in order to avoid the unnecessary lock-time of uid_lock. Bug: 278138377 Signed-off-by: Peifeng Li (cherry picked from https://android-review.googlesource.com/q/commit:c1fa53f3cf85c0a1c23f0e0a944986b4aa049073) Merged-In: I5be62105e57e2a896a95d906e3c14e17c7f8077d Change-Id: I5be62105e57e2a896a95d906e3c14e17c7f8077d --- drivers/misc/uid_sys_stats.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index f713de2b3a08..095962102ac7 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -558,7 +558,11 @@ static void update_io_stats_all(void) } } +#ifndef CONFIG_UID_SYS_STATS_DEBUG +static void update_io_stats_uid(struct uid_entry *uid_entry) +#else static void update_io_stats_uid_locked(struct uid_entry *uid_entry) +#endif { struct task_struct *task, *temp; struct user_namespace *user_ns = current_user_ns(); @@ -639,6 +643,9 @@ static ssize_t uid_procstat_write(struct file *file, uid_t uid; int argc, state; char input[128]; +#ifndef CONFIG_UID_SYS_STATS_DEBUG + struct uid_entry uid_entry_tmp; +#endif if (count >= sizeof(input)) return -EINVAL; @@ -667,11 +674,39 @@ static ssize_t uid_procstat_write(struct file *file, return count; } +#ifndef CONFIG_UID_SYS_STATS_DEBUG + /* + * Update_io_stats_uid_locked would take a long lock-time of uid_lock + * due to call do_each_thread to compute uid_entry->io, which would + * cause to lock competition sometime. + * + * Using uid_entry_tmp to get the result of Update_io_stats_uid, + * so that we can unlock_uid during update_io_stats_uid, in order + * to avoid the unnecessary lock-time of uid_lock. + */ + uid_entry_tmp.uid = uid_entry->uid; + memcpy(uid_entry_tmp.io, uid_entry->io, + sizeof(struct io_stats) * UID_STATE_SIZE); + unlock_uid(uid); + update_io_stats_uid(&uid_entry_tmp); + + lock_uid(uid); + hlist_for_each_entry(uid_entry, &hash_table[hash_min(uid, HASH_BITS(hash_table))], hash) { + if (uid_entry->uid == uid_entry_tmp.uid) { + memcpy(uid_entry->io, uid_entry_tmp.io, + sizeof(struct io_stats) * UID_STATE_SIZE); + uid_entry->state = state; + break; + } + } + unlock_uid(uid); +#else update_io_stats_uid_locked(uid_entry); uid_entry->state = state; unlock_uid(uid); +#endif return count; }