From fc5015d369ed892bf497d326ccd327ae207c14da Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Sat, 24 Jul 2021 22:53:36 +0300 Subject: [PATCH] Squashed revert of CPU UID time commits * Reverting the following wahoo commits to reduce merge conflicts with android-4.4-p * android-4.4-p has a more up to date version of these patches Revert "cpufreq: stats: optimize proc files" This reverts commit df9e853de74c77aa360cb401f0e91b2bae40edb3. Revert "cpufreq: times: add text versions of uid concurrent_*_time files" This reverts commit 09a579d84b8a672bf086ae10617dc536cb28ffc9. Revert "cpufreq_stats: Reset cpufreq_task_stats right after dup_task_struct" This reverts commit 9fdce3a6ec2ee8d8c391389be5cdd5184b748b1f. Revert "kernel: initialize and free cpufreq stats properly" This reverts commit 990b5d60956471419705300af885f6dff9e12796. Revert "kernel: Fix massive cpufreq stats memory leaks" This reverts commit 33d963afe62c03f85455429b4f81c2b85c715261. Revert "cpufreq: stats: use seq iterator for large uid-related files" This reverts commit 085b2438b2827cf7b9349a6a8594dcc11b7428d8. Revert "cpufreq: stats: update uid data in acct_update_power" This reverts commit c2d219600e1a61a72ccee133c5827d61042bc65d. Revert "ANDROID: cpufreq: change uid_cpupower to use u32" This reverts commit 422d5f8279ba73b3aa5d163d4b45f2dc4627c4cb. Revert "STOPSHIP: ANDROID: cpufreq: concurrent_*_time P/H experiment" This reverts commit 74e7c2c05ed9a267d2f187136778f48b35dbe944. Revert "ANDROID: cpufreq: Remove seq_printf from critical path" This reverts commit 2b7f873be121e17939a8a985bfef0c11f126a361. Revert "ANDROID: cpufreq: update conditions for recording cputime" This reverts commit 3ef73b4845a1eafbb3cc444c0d613f2cee0171fa. Revert "ANDROID: cpufreq: uid_concurrent_policy_time" This reverts commit 9892125368426521075d79c464123076213ea3b7. Revert "ANDROID: cpufreq: uid_concurrent_active_time" This reverts commit c89e69136fecb2ab4aa8dceaaf371cdcaae8bec2. Revert "ANDROID: cpufreq: concurrent_policy_time by pid" This reverts commit 7afc0cf00242a00dcde448aa83fca5d724826748. Revert "ANDROID: cpufreq: concurrent_active_time by pid" This reverts commit a88a869505d33bb77ee7bca67602f5fe6048205d. Revert "ANDROID: cpufreq: Add time_in_state to /proc/uid directories" This reverts commit 0c042ef0b32206d73f4111a8963ff870784adc7b. Revert "ANDROID: cpufreq: stats: Fix dead stats clearing timing" This reverts commit 502920bb136f9e1c2b47ab21ea6fe0716aa67691. Revert "ANDROID: cpufreq: stats: Fix sleeping while atomic in cpufreq_task_stats_init" This reverts commit 99735fa7c3d1baa9b11e21632b1b07dd9ad55cd6. Revert "ANDROID: cpufreq: stats: Fix NULL policy scenarios" This reverts commit a24d2dd696de8f5e8f620334bc593ca96241f9bd. Revert "ANDROID: cpufreq: stats: add per task/uid/freq/cluster stats" This reverts commit fc4ac15a006ba23eda0b898739a466ac968eaff6. Revert "proc: add null check in proc_uid_init" This reverts commit aaf63e511169e04c981f505ad3e19bdde5d10bcc. Revert "ANDROID: proc: Add /proc/uid directory" This reverts commit 9ef787ad55030ec517d0400969738f21070c5852. Revert "uid_sys_stats: fix overflow when io usage delta is negative" This reverts commit 8e7913772d0065841e307735f37f8a69ab5d5ab9. Change-Id: I5fc16b03944fae9c2997192bfb842444c7142764 --- drivers/cpufreq/cpufreq_stats.c | 1291 ++++--------------------------- drivers/misc/uid_sys_stats.c | 35 +- fs/proc/Makefile | 1 - fs/proc/base.c | 11 - fs/proc/internal.h | 5 - fs/proc/root.c | 2 +- fs/proc/uid.c | 291 ------- include/linux/cpufreq.h | 32 - include/linux/proc_fs.h | 2 - include/linux/sched.h | 4 - kernel/exit.c | 1 - kernel/fork.c | 8 - kernel/sched/core.c | 10 - kernel/sched/cputime.c | 11 - kernel/user.c | 3 - 15 files changed, 147 insertions(+), 1560 deletions(-) delete mode 100644 fs/proc/uid.c diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index c14c0a3aa6b4..1be58ffd3bce 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -9,677 +9,38 @@ * published by the Free Software Foundation. */ -#include #include #include -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include - -#define UID_HASH_BITS 10 - -DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS); +#include static spinlock_t cpufreq_stats_lock; -static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */ -static DEFINE_SPINLOCK(task_concurrent_active_time_lock); - /* task->concurrent_active_time */ -static DEFINE_SPINLOCK(task_concurrent_policy_time_lock); - /* task->concurrent_policy_time */ -static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */ - -struct uid_entry { - uid_t uid; - unsigned int max_state; - struct hlist_node hash; - struct rcu_head rcu; - atomic64_t *concurrent_active_time; - atomic64_t *concurrent_policy_time; - u64 time_in_state[0]; -}; - struct cpufreq_stats { unsigned int total_trans; unsigned long long last_time; unsigned int max_state; - int prev_states; - atomic_t curr_state; + unsigned int state_num; + unsigned int last_index; u64 *time_in_state; unsigned int *freq_table; +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS + unsigned int *trans_table; +#endif }; -static int cpufreq_max_state; -static int cpufreq_last_max_state; -static unsigned int *cpufreq_states; -static bool cpufreq_stats_initialized; -static struct proc_dir_entry *uid_cpupower; - -/* STOPSHIP: uid_cpupower_enable is used to enable/disable concurrent_*_time - * This varible will be used in P/H experiments and should be removed before - * launch. - * - * Because it is being used to test performance and power, it should have a - * minimum impact on both. For these performance reasons, it will not be guarded - * by a lock or protective barriers. This limits what it can safely - * enable/disable. - * - * It is safe to check it before updating any concurrent_*_time stats. If there - * are changes uid_cpupower_enable state while we are updating the stats, we - * will simply ignore the changes until the next attempt to update the stats. - * This may result in a couple ms where the uid_cpupower_enable is in one state - * and the code is acting in another. Since the P/H experiments are done over - * the course of many days, a couple ms delay should not be an issue. - * - * It is not safe to delete the associated proc files without additional locking - * mechanisms that would hurt performance. Leaving the files empty but intact - * will not have any impact on the P/H experiments provided that userspace does - * not attempt to read them. Since the P/H experiment will also disable the code - * that reads these files from userspace, this is not a concern. - */ -static char uid_cpupower_enable; - -struct cpufreq_stats_attribute { - struct attribute attr; - - ssize_t (*show)(struct cpufreq_stats *, char *); -}; - -/* Caller must hold rcu_read_lock() */ -static struct uid_entry *find_uid_entry_rcu(uid_t uid) -{ - struct uid_entry *uid_entry; - - hash_for_each_possible_rcu(uid_hash_table, uid_entry, hash, uid) { - if (uid_entry->uid == uid) - return uid_entry; - } - return NULL; -} - -/* Caller must hold uid lock */ -static struct uid_entry *find_uid_entry(uid_t uid) -{ - struct uid_entry *uid_entry; - - hash_for_each_possible(uid_hash_table, uid_entry, hash, uid) { - if (uid_entry->uid == uid) - return uid_entry; - } - return NULL; -} - -/* Caller must hold uid lock */ -static struct uid_entry *find_or_register_uid(uid_t uid) -{ - struct uid_entry *uid_entry; - struct uid_entry *temp; - atomic64_t *times; - unsigned int max_state = READ_ONCE(cpufreq_max_state); - size_t alloc_size = sizeof(*uid_entry) + max_state * - sizeof(uid_entry->time_in_state[0]); - - uid_entry = find_uid_entry(uid); - if (uid_entry) { - if (uid_entry->max_state == max_state) - return uid_entry; - /* uid_entry->time_in_state is too small to track all freqs, so - * expand it. - */ - temp = __krealloc(uid_entry, alloc_size, GFP_ATOMIC); - if (!temp) - return uid_entry; - temp->max_state = max_state; - memset(temp->time_in_state + uid_entry->max_state, 0, - (max_state - uid_entry->max_state) * - sizeof(uid_entry->time_in_state[0])); - if (temp != uid_entry) { - hlist_replace_rcu(&uid_entry->hash, &temp->hash); - kfree_rcu(uid_entry, rcu); - } - return temp; - } - - uid_entry = kzalloc(alloc_size, GFP_ATOMIC); - if (!uid_entry) - return NULL; - /* Single allocation for both active & policy time arrays */ - times = kcalloc(num_possible_cpus() * 2, sizeof(atomic64_t), - GFP_ATOMIC); - if (!times) { - kfree(uid_entry); - return NULL; - } - - uid_entry->uid = uid; - uid_entry->max_state = max_state; - uid_entry->concurrent_active_time = times; - uid_entry->concurrent_policy_time = times + num_possible_cpus(); - - hash_add_rcu(uid_hash_table, &uid_entry->hash, uid); - - return uid_entry; -} - -static int single_uid_time_in_state_show(struct seq_file *m, void *ptr) -{ - struct uid_entry *uid_entry; - unsigned int i; - u64 time; - uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private); - - if (uid == overflowuid) - return -EINVAL; - if (!cpufreq_stats_initialized) - return 0; - - rcu_read_lock(); - uid_entry = find_uid_entry_rcu(uid); - - if (!uid_entry) { - rcu_read_unlock(); - return 0; - } - - for (i = 0; i < uid_entry->max_state; ++i) { - time = cputime_to_clock_t(uid_entry->time_in_state[i]); - seq_write(m, &time, sizeof(time)); - } - - rcu_read_unlock(); - - return 0; -} - -static void *uid_seq_start(struct seq_file *seq, loff_t *pos) -{ - if (!cpufreq_stats_initialized) - return NULL; - - if (*pos >= HASH_SIZE(uid_hash_table)) - return NULL; - - return &uid_hash_table[*pos]; -} - -static void *uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - do { - (*pos)++; - - if (*pos >= HASH_SIZE(uid_hash_table)) - return NULL; - } while (hlist_empty(&uid_hash_table[*pos])); - - return &uid_hash_table[*pos]; -} - -static void uid_seq_stop(struct seq_file *seq, void *v) { } - -static int uid_time_in_state_seq_show(struct seq_file *m, void *v) -{ - struct uid_entry *uid_entry; - struct cpufreq_policy *last_policy = NULL; - int i; - - if (!cpufreq_stats_initialized) - return 0; - - if (v == uid_hash_table) { - seq_puts(m, "uid:"); - for_each_possible_cpu(i) { - struct cpufreq_frequency_table *table, *pos; - struct cpufreq_policy *policy; - - policy = cpufreq_cpu_get(i); - if (!policy) - continue; - table = cpufreq_frequency_get_table(i); - - /* Assumes cpus are colocated within a policy */ - if (table && last_policy != policy) { - last_policy = policy; - cpufreq_for_each_valid_entry(pos, table) - seq_put_decimal_ull(m, ' ', - pos->frequency); - } - cpufreq_cpu_put(policy); - } - seq_putc(m, '\n'); - } - - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - if (uid_entry->max_state) { - seq_put_decimal_ull(m, (char)0, uid_entry->uid); - seq_putc(m, ':'); - } - for (i = 0; i < uid_entry->max_state; ++i) { - u64 time = cputime_to_clock_t( - uid_entry->time_in_state[i]); - seq_put_decimal_ull(m, ' ', time); - } - if (uid_entry->max_state) - seq_putc(m, '\n'); - } - - rcu_read_unlock(); - return 0; -} - -/* - * time_in_state is an array of u32's in the following format: - * [n, uid0, time0a, time0b, ..., time0n, - * uid1, time1a, time1b, ..., time1n, - * uid2, time2a, time2b, ..., time2n, etc.] - * where n is the total number of frequencies - */ -static int time_in_state_seq_show(struct seq_file *m, void *v) -{ - struct uid_entry *uid_entry; - u32 cpufreq_max_state_u32 = READ_ONCE(cpufreq_max_state); - u32 uid, time; - int i; - - if (!cpufreq_stats_initialized) - return 0; - - if (v == uid_hash_table) - seq_write(m, &cpufreq_max_state_u32, - sizeof(cpufreq_max_state_u32)); - - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - if (uid_entry->max_state) { - uid = (u32) uid_entry->uid; - seq_write(m, &uid, sizeof(uid)); - } - - for (i = 0; i < uid_entry->max_state; ++i) { - time = (u32) - cputime_to_clock_t(uid_entry->time_in_state[i]); - seq_write(m, &time, sizeof(time)); - } - } - - rcu_read_unlock(); - return 0; -} - -/* - * concurrent_active_time is an array of u32's in the following format: - * [n, uid0, time0a, time0b, ..., time0n, - * uid1, time1a, time1b, ..., time1n, - * uid2, time2a, time2b, ..., time2n, etc.] - * where n is the total number of cpus (num_possible_cpus) - */ -static int concurrent_active_time_seq_show(struct seq_file *m, void *v) -{ - struct uid_entry *uid_entry; - u32 uid, time, num_possible_cpus = num_possible_cpus(); - int i; - - if (!cpufreq_stats_initialized || !uid_cpupower_enable) - return 0; - - if (v == uid_hash_table) - seq_write(m, &num_possible_cpus, sizeof(num_possible_cpus)); - - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - uid = (u32) uid_entry->uid; - seq_write(m, &uid, sizeof(uid)); - - for (i = 0; i < num_possible_cpus; ++i) { - time = (u32) cputime_to_clock_t( - atomic64_read( - &uid_entry->concurrent_active_time[i])); - seq_write(m, &time, sizeof(time)); - } - } - - rcu_read_unlock(); - return 0; -} - -/* - * concurrent_policy_time is an array of u32's in the following format: - * [n, x0, ..., xn, uid0, time0a, time0b, ..., time0n, - * uid1, time1a, time1b, ..., time1n, - * uid2, time2a, time2b, ..., time2n, etc.] - * where n is the number of policies - * xi is the number cpus on a particular policy - */ -static int concurrent_policy_time_seq_show(struct seq_file *m, void *v) -{ - struct uid_entry *uid_entry; - struct cpufreq_policy *policy; - struct cpufreq_policy *last_policy = NULL; - u32 buf[num_possible_cpus()]; - u32 uid, time; - int i, cnt = 0, num_possible_cpus = num_possible_cpus(); - - if (!cpufreq_stats_initialized || !uid_cpupower_enable) - return 0; - - if (v == uid_hash_table) { - for_each_possible_cpu(i) { - policy = cpufreq_cpu_get(i); - if (!policy) - continue; - if (policy != last_policy) { - cnt++; - if (last_policy) - cpufreq_cpu_put(last_policy); - last_policy = policy; - buf[cnt] = 0; - } else { - cpufreq_cpu_put(policy); - } - ++buf[cnt]; - } - if (last_policy) - cpufreq_cpu_put(last_policy); - - buf[0] = (u32) cnt; - seq_write(m, buf, (cnt + 1) * sizeof(*buf)); - } - rcu_read_lock(); - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - uid = (u32) uid_entry->uid; - seq_write(m, &uid, sizeof(uid)); - - for (i = 0; i < num_possible_cpus; ++i) { - time = (u32) cputime_to_clock_t( - atomic64_read( - &uid_entry->concurrent_policy_time[i])); - seq_write(m, &time, sizeof(time)); - } - } - rcu_read_unlock(); - return 0; -} - -static int concurrent_time_text_seq_show(struct seq_file *m, void *v, - atomic64_t *(*get_times)(struct uid_entry *)) -{ - struct uid_entry *uid_entry; - int i, num_possible_cpus = num_possible_cpus(); - - if (!uid_cpupower_enable) - return 0; - - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - atomic64_t *times = get_times(uid_entry); - seq_put_decimal_ull(m, 0, (u64)uid_entry->uid); - seq_putc(m, ':'); - - for (i = 0; i < num_possible_cpus; ++i) { - u64 time = cputime_to_clock_t(atomic64_read(×[i])); - seq_put_decimal_ull(m, ' ', time); - } - seq_putc(m, '\n'); - } - - rcu_read_unlock(); - - return 0; -} - -static inline atomic64_t *get_active_times(struct uid_entry *uid_entry) -{ - return uid_entry->concurrent_active_time; -} - -static int concurrent_active_time_text_seq_show(struct seq_file *m, void *v) -{ - if (!cpufreq_stats_initialized || !uid_cpupower_enable) - return 0; - - if (v == uid_hash_table) { - seq_puts(m, "cpus: "); - seq_put_decimal_ull(m, 0, num_possible_cpus()); - seq_putc(m, '\n'); - } - - return concurrent_time_text_seq_show(m, v, get_active_times); -} - -static inline atomic64_t *get_policy_times(struct uid_entry *uid_entry) -{ - return uid_entry->concurrent_policy_time; -} - -static int concurrent_policy_time_text_seq_show(struct seq_file *m, void *v) -{ - int i; - struct cpufreq_policy *policy, *last_policy = NULL; - if (v == uid_hash_table) { - int cnt = 0; - for_each_possible_cpu(i) { - policy = cpufreq_cpu_get(i); - if (!policy) - continue; - if (policy != last_policy) { - if (last_policy) { - seq_put_decimal_ull(m, 0, cnt); - seq_putc(m, ' '); - cnt = 0; - cpufreq_cpu_put(last_policy); - } - seq_puts(m, "policy"); - seq_put_decimal_ll(m, 0, i); - seq_puts(m, ": "); - - last_policy = policy; - } else { - cpufreq_cpu_put(policy); - } - cnt++; - } - if (last_policy) { - cpufreq_cpu_put(last_policy); - seq_put_decimal_ull(m, 0, cnt); - seq_putc(m, '\n'); - } - } - return concurrent_time_text_seq_show(m, v, get_policy_times); -} - -static int uid_cpupower_enable_show(struct seq_file *m, void *v) -{ - seq_putc(m, uid_cpupower_enable); - seq_putc(m, '\n'); - - return 0; -} - -static ssize_t uid_cpupower_enable_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - char enable; - - if (count >= sizeof(enable)) - count = sizeof(enable); - - if (copy_from_user(&enable, buffer, count)) - return -EFAULT; - - if (enable == '0') - uid_cpupower_enable = 0; - else if (enable == '1') - uid_cpupower_enable = 1; - else - return -EINVAL; - - return count; -} - static int cpufreq_stats_update(struct cpufreq_stats *stats) { unsigned long long cur_time = get_jiffies_64(); spin_lock(&cpufreq_stats_lock); - stats->time_in_state[atomic_read(&stats->curr_state)] += - cur_time - stats->last_time; + stats->time_in_state[stats->last_index] += cur_time - stats->last_time; stats->last_time = cur_time; spin_unlock(&cpufreq_stats_lock); return 0; } -void cpufreq_task_stats_init(struct task_struct *p) -{ - unsigned long flags; - spin_lock_irqsave(&task_time_in_state_lock, flags); - p->time_in_state = NULL; - spin_unlock_irqrestore(&task_time_in_state_lock, flags); - WRITE_ONCE(p->max_state, 0); - spin_lock_irqsave(&task_concurrent_active_time_lock, flags); - p->concurrent_active_time = NULL; - spin_unlock_irqrestore(&task_concurrent_active_time_lock, flags); - spin_lock_irqsave(&task_concurrent_policy_time_lock, flags); - p->concurrent_policy_time = NULL; - spin_unlock_irqrestore(&task_concurrent_policy_time_lock, flags); -} - -void cpufreq_task_stats_alloc(struct task_struct *p) -{ - size_t alloc_size; - void *temp; - unsigned long flags; - - if (!cpufreq_stats_initialized) - return; - - /* We use one array to avoid multiple allocs per task */ - WRITE_ONCE(p->max_state, cpufreq_max_state); - - alloc_size = p->max_state * sizeof(p->time_in_state[0]); - temp = kzalloc(alloc_size, GFP_ATOMIC); - - spin_lock_irqsave(&task_time_in_state_lock, flags); - p->time_in_state = temp; - spin_unlock_irqrestore(&task_time_in_state_lock, flags); - - alloc_size = num_possible_cpus() * sizeof(u64); - temp = kzalloc(alloc_size, GFP_ATOMIC); - - spin_lock_irqsave(&task_concurrent_active_time_lock, flags); - p->concurrent_active_time = temp; - spin_unlock_irqrestore(&task_concurrent_active_time_lock, flags); - - temp = kzalloc(alloc_size, GFP_ATOMIC); - - spin_lock_irqsave(&task_concurrent_policy_time_lock, flags); - p->concurrent_policy_time = temp; - spin_unlock_irqrestore(&task_concurrent_policy_time_lock, flags); -} - -int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, - struct pid *pid, struct task_struct *p) -{ - int i; - cputime_t cputime; - unsigned long flags; - - if (!cpufreq_stats_initialized || !p->time_in_state) - return 0; - - spin_lock(&cpufreq_stats_lock); - for (i = 0; i < p->max_state; ++i) { - cputime = 0; - spin_lock_irqsave(&task_time_in_state_lock, flags); - if (p->time_in_state) - cputime = atomic_read(&p->time_in_state[i]); - spin_unlock_irqrestore(&task_time_in_state_lock, flags); - - seq_printf(m, "%d %lu\n", cpufreq_states[i], - (unsigned long)cputime_to_clock_t(cputime)); - } - spin_unlock(&cpufreq_stats_lock); - - return 0; -} - -int proc_concurrent_active_time_show(struct seq_file *m, - struct pid_namespace *ns, struct pid *pid, struct task_struct *p) -{ - int i; - cputime_t cputime; - unsigned long flags; - - if (!cpufreq_stats_initialized || !p->concurrent_active_time) - return 0; - - spin_lock(&cpufreq_stats_lock); - for (i = 0; i < num_possible_cpus(); ++i) { - cputime = 0; - spin_lock_irqsave(&task_concurrent_active_time_lock, flags); - if (p->concurrent_active_time) - cputime = atomic_read(&p->concurrent_active_time[i]); - spin_unlock_irqrestore(&task_concurrent_active_time_lock, - flags); - - seq_printf(m, "%d %lu\n", i, - (unsigned long)cputime_to_clock_t(cputime)); - } - spin_unlock(&cpufreq_stats_lock); - - return 0; -} - -int proc_concurrent_policy_time_show(struct seq_file *m, - struct pid_namespace *ns, struct pid *pid, struct task_struct *p) -{ - struct cpufreq_policy *policy; - struct cpufreq_policy *last_policy = NULL; - int cpu, cnt; - cputime_t cputime; - unsigned long flags; - - if (!cpufreq_stats_initialized || !p->concurrent_policy_time) - return 0; - - spin_lock(&cpufreq_stats_lock); - for (cpu = 0; cpu < num_possible_cpus(); ++cpu) { - - policy = cpufreq_cpu_get(cpu); - if (policy != last_policy) { - cnt = 0; - last_policy = policy; - seq_printf(m, "policy%i\n", cpu); - } - cpufreq_cpu_put(policy); - cnt++; - - cputime = 0; - spin_lock_irqsave(&task_concurrent_policy_time_lock, flags); - if (p->concurrent_policy_time) - cputime = atomic_read(&p->concurrent_policy_time[cpu]); - spin_unlock_irqrestore(&task_concurrent_policy_time_lock, - flags); - - seq_printf(m, "%d %lu\n", cnt, - (unsigned long)cputime_to_clock_t(cputime)); - } - spin_unlock(&cpufreq_stats_lock); - - return 0; -} - static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) { return sprintf(buf, "%d\n", policy->stats->total_trans); @@ -692,7 +53,7 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) int i; cpufreq_stats_update(stats); - for (i = 0; i < stats->max_state; i++) { + for (i = 0; i < stats->state_num; i++) { len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], (unsigned long long) jiffies_64_to_clock_t(stats->time_in_state[i])); @@ -700,151 +61,49 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) return len; } -/* Called without cpufreq_stats_lock held */ -void acct_update_power(struct task_struct *task, cputime_t cputime) -{ - struct cpufreq_stats *stats; - struct cpufreq_policy *policy; - struct uid_entry *uid_entry; - unsigned int cpu_num; - unsigned int state; - unsigned int active_cpu_cnt = 0; - unsigned int policy_cpu_cnt = 0; - unsigned int policy_first_cpu; - unsigned int index; - unsigned long flags; - int cpu = 0; - uid_t uid = from_kuid_munged(current_user_ns(), task_uid(task)); - - if (!task) - return; - - cpu_num = task_cpu(task); - policy = cpufreq_cpu_get(cpu_num); - if (!policy) - return; - - stats = policy->stats; - if (!stats) { - cpufreq_cpu_put(policy); - return; - } - - state = stats->prev_states + atomic_read(&policy->stats->curr_state); - - /* This function is called from a different context - * Interruptions in between reads/assignements are ok - */ - if (cpufreq_stats_initialized && - !(task->flags & PF_EXITING) && - state < READ_ONCE(task->max_state)) { - spin_lock_irqsave(&task_time_in_state_lock, flags); - if (task->time_in_state) - atomic64_add(cputime, &task->time_in_state[state]); - spin_unlock_irqrestore(&task_time_in_state_lock, flags); - } - - spin_lock_irqsave(&uid_lock, flags); - uid_entry = find_or_register_uid(uid); - if (uid_entry && state < uid_entry->max_state) - uid_entry->time_in_state[state] += cputime; - spin_unlock_irqrestore(&uid_lock, flags); - - if (uid_cpupower_enable) { - rcu_read_lock(); - uid_entry = find_uid_entry_rcu(uid); - - for_each_possible_cpu(cpu) - if (!idle_cpu(cpu)) - ++active_cpu_cnt; - - index = active_cpu_cnt - 1; - spin_lock_irqsave(&task_concurrent_active_time_lock, flags); - if (cpufreq_stats_initialized && !(task->flags & PF_EXITING) && - task->concurrent_active_time) - atomic64_add(cputime, - &task->concurrent_active_time[index]); - spin_unlock_irqrestore(&task_concurrent_active_time_lock, flags); - - if (uid_entry) { - atomic64_add(cputime, - &uid_entry->concurrent_active_time[index]); - } - - for_each_cpu(cpu, policy->related_cpus) - if (!idle_cpu(cpu)) - ++policy_cpu_cnt; - - policy_first_cpu = cpumask_first(policy->related_cpus); - - index = policy_first_cpu + policy_cpu_cnt - 1; - spin_lock_irqsave(&task_concurrent_policy_time_lock, flags); - if (cpufreq_stats_initialized && !(task->flags & PF_EXITING) && - task->concurrent_policy_time) - atomic64_add(cputime, - &task->concurrent_policy_time[index]); - spin_unlock_irqrestore(&task_concurrent_policy_time_lock, flags); - - if (uid_entry) { - atomic64_add(cputime, - &uid_entry->concurrent_policy_time[index]); - } - rcu_read_unlock(); - } - - cpufreq_cpu_put(policy); - -} -EXPORT_SYMBOL_GPL(acct_update_power); - -static ssize_t show_all_time_in_state(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS +static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) { + struct cpufreq_stats *stats = policy->stats; ssize_t len = 0; - unsigned int i, cpu, freq; - struct cpufreq_policy *policy; - struct cpufreq_stats *stats; + int i, j; - len += scnprintf(buf + len, PAGE_SIZE - len, "freq\t\t"); - for_each_possible_cpu(cpu) { - policy = cpufreq_cpu_get(cpu); - if (!policy) - continue; - stats = policy->stats; - len += scnprintf(buf + len, PAGE_SIZE - len, "cpu%u\t\t", cpu); - cpufreq_stats_update(stats); - cpufreq_cpu_put(policy); + len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); + len += snprintf(buf + len, PAGE_SIZE - len, " : "); + for (i = 0; i < stats->state_num; i++) { + if (len >= PAGE_SIZE) + break; + len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", + stats->freq_table[i]); } + if (len >= PAGE_SIZE) + return PAGE_SIZE; - if (!cpufreq_stats_initialized) - goto out; - for (i = 0; i < cpufreq_max_state; i++) { - freq = cpufreq_states[i]; - len += scnprintf(buf + len, PAGE_SIZE - len, "\n%u\t\t", freq); - for_each_possible_cpu(cpu) { - policy = cpufreq_cpu_get(cpu); - if (!policy) - continue; - stats = policy->stats; - if (i >= stats->prev_states && - i < stats->prev_states + stats->max_state) { - len += scnprintf(buf + len, PAGE_SIZE - len, - "%lu\t\t", (unsigned long) - cputime64_to_clock_t( - stats->time_in_state[i - - stats->prev_states])); - } else { - len += scnprintf(buf + len, PAGE_SIZE - len, - "N/A\t\t"); - } - cpufreq_cpu_put(policy); + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + + for (i = 0; i < stats->state_num; i++) { + if (len >= PAGE_SIZE) + break; + + len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ", + stats->freq_table[i]); + + for (j = 0; j < stats->state_num; j++) { + if (len >= PAGE_SIZE) + break; + len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", + stats->trans_table[i*stats->max_state+j]); } + if (len >= PAGE_SIZE) + break; + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); } - -out: - len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); + if (len >= PAGE_SIZE) + return PAGE_SIZE; return len; } +cpufreq_freq_attr_ro(trans_table); +#endif cpufreq_freq_attr_ro(total_trans); cpufreq_freq_attr_ro(time_in_state); @@ -852,6 +111,9 @@ cpufreq_freq_attr_ro(time_in_state); static struct attribute *default_attrs[] = { &total_trans.attr, &time_in_state.attr, +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS + &trans_table.attr, +#endif NULL }; static struct attribute_group stats_attr_group = { @@ -859,10 +121,6 @@ static struct attribute_group stats_attr_group = { .name = "stats" }; -static struct kobj_attribute _attr_all_time_in_state = __ATTR(all_time_in_state, - 0444, show_all_time_in_state, NULL); - - static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq) { int index; @@ -876,6 +134,7 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) { struct cpufreq_stats *stats = policy->stats; + /* Already freed */ if (!stats) return; @@ -885,7 +144,6 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) kfree(stats->time_in_state); kfree(stats); policy->stats = NULL; - /* cpufreq_last_max_state is always incrementing, not changed here */ } static void cpufreq_stats_free_table(unsigned int cpu) @@ -896,152 +154,103 @@ static void cpufreq_stats_free_table(unsigned int cpu) if (!policy) return; - if (cpufreq_frequency_get_table(policy->cpu)) - __cpufreq_stats_free_table(policy); + __cpufreq_stats_free_table(policy); cpufreq_cpu_put(policy); } - -static int cpufreq_stats_create_all_table(void) +static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) { - struct cpufreq_policy *last_policy = NULL; - struct cpufreq_policy *policy; - struct cpufreq_stats *stats; - int cpu, i; - - cpufreq_states = kcalloc(cpufreq_max_state, sizeof(unsigned int), - GFP_KERNEL); - if (cpufreq_states == NULL) - return -ENOMEM; - - for_each_possible_cpu(cpu) { - policy = cpufreq_cpu_get(cpu); - if (!policy) - continue; - stats = policy->stats; - if (policy != last_policy) { - for (i = 0; i < stats->max_state; ++i) - cpufreq_states[stats->prev_states + i] - = stats->freq_table[i]; - last_policy = policy; - } - cpufreq_cpu_put(policy); - } - return 0; -} - -static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, int count) -{ - unsigned int i, ret = 0; + unsigned int i = 0, count = 0, ret = -ENOMEM; struct cpufreq_stats *stats; unsigned int alloc_size; - struct cpufreq_frequency_table *pos; + unsigned int cpu = policy->cpu; + struct cpufreq_frequency_table *pos, *table; + /* We need cpufreq table for creating stats table */ + table = cpufreq_frequency_get_table(cpu); + if (unlikely(!table)) + return 0; + + /* stats already initialized */ if (policy->stats) - return -EBUSY; + return -EEXIST; stats = kzalloc(sizeof(*stats), GFP_KERNEL); - if (stats == NULL) + if (!stats) return -ENOMEM; - ret = sysfs_create_group(&policy->kobj, &stats_attr_group); - if (ret) - pr_warn("Cannot create stats attr group\n"); + /* Find total allocation size */ + cpufreq_for_each_valid_entry(pos, table) + count++; - alloc_size = count * sizeof(u64) + count * sizeof(unsigned int); + alloc_size = count * sizeof(int) + count * sizeof(u64); +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS + alloc_size += count * count * sizeof(int); +#endif + + /* Allocate memory for time_in_state/freq_table/trans_table in one go */ stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); - if (!stats->time_in_state) { - ret = -ENOMEM; - goto error_alloc; - } + if (!stats->time_in_state) + goto free_stat; + stats->freq_table = (unsigned int *)(stats->time_in_state + count); - i = 0; +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS + stats->trans_table = stats->freq_table + count; +#endif + + stats->max_state = count; + + /* Find valid-unique entries */ cpufreq_for_each_valid_entry(pos, table) if (freq_table_get_index(stats, pos->frequency) == -1) stats->freq_table[i++] = pos->frequency; - cpufreq_last_max_state = cpufreq_max_state; - stats->prev_states = cpufreq_last_max_state; - stats->max_state = count; - cpufreq_max_state += count; - - spin_lock(&cpufreq_stats_lock); + stats->state_num = i; stats->last_time = get_jiffies_64(); - atomic_set(&stats->curr_state, - freq_table_get_index(stats, policy->cur)); - spin_unlock(&cpufreq_stats_lock); + stats->last_index = freq_table_get_index(stats, policy->cur); + policy->stats = stats; - return 0; -error_alloc: - sysfs_remove_group(&policy->kobj, &stats_attr_group); - kfree(stats); + ret = sysfs_create_group(&policy->kobj, &stats_attr_group); + if (!ret) + return 0; + + /* We failed, release resources */ policy->stats = NULL; + kfree(stats->time_in_state); +free_stat: + kfree(stats); + return ret; } -static void cpufreq_stats_create_table(struct cpufreq_policy *policy) +static void cpufreq_stats_create_table(unsigned int cpu) { - struct cpufreq_frequency_table *table, *pos; - int count = 0; + struct cpufreq_policy *policy; - table = cpufreq_frequency_get_table(policy->cpu); - if (likely(table)) { - cpufreq_for_each_valid_entry(pos, table) - count++; + /* + * "likely(!policy)" because normally cpufreq_stats will be registered + * before cpufreq driver + */ + policy = cpufreq_cpu_get(cpu); + if (likely(!policy)) + return; - __cpufreq_stats_create_table(policy, table, count); - } -} + __cpufreq_stats_create_table(policy); -static void uid_entry_reclaim(struct rcu_head *rcu) -{ - struct uid_entry *uid_entry = container_of(rcu, struct uid_entry, rcu); - - kfree(uid_entry->concurrent_active_time); - kfree(uid_entry); -} - -void cpufreq_task_stats_remove_uids(uid_t uid_start, uid_t uid_end) -{ - struct uid_entry *uid_entry; - struct hlist_node *tmp; - unsigned long flags; - - spin_lock_irqsave(&uid_lock, flags); - - for (; uid_start <= uid_end; uid_start++) { - hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp, - hash, uid_start) { - if (uid_start == uid_entry->uid) { - hash_del_rcu(&uid_entry->hash); - call_rcu(&uid_entry->rcu, uid_entry_reclaim); - } - } - } - - spin_unlock_irqrestore(&uid_lock, flags); + cpufreq_cpu_put(policy); } static int cpufreq_stat_notifier_policy(struct notifier_block *nb, - unsigned long val, void *data) + unsigned long val, void *data) { - int ret = 0, count = 0; + int ret = 0; struct cpufreq_policy *policy = data; - struct cpufreq_frequency_table *table, *pos; - - table = cpufreq_frequency_get_table(policy->cpu); - if (!table) - return 0; - - cpufreq_for_each_valid_entry(pos, table) - count++; if (val == CPUFREQ_CREATE_POLICY) - ret = __cpufreq_stats_create_table(policy, table, count); + ret = __cpufreq_stats_create_table(policy); else if (val == CPUFREQ_REMOVE_POLICY) __cpufreq_stats_free_table(policy); @@ -1049,209 +258,51 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, } static int cpufreq_stat_notifier_trans(struct notifier_block *nb, - unsigned long val, void *data) + unsigned long val, void *data) { struct cpufreq_freqs *freq = data; - struct cpufreq_stats *stat; - struct cpufreq_policy *policy; + struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu); + struct cpufreq_stats *stats; + int old_index, new_index; - if (val != CPUFREQ_POSTCHANGE) - return 0; - - policy = cpufreq_cpu_get(freq->cpu); - if (!policy) - return 0; - - stat = policy->stats; - if (!stat) { - cpufreq_cpu_put(policy); + if (!policy) { + pr_err("%s: No policy found\n", __func__); return 0; } - cpufreq_stats_update(policy->stats); - spin_lock(&cpufreq_stats_lock); - atomic_set(&stat->curr_state, freq_table_get_index(stat, freq->new)); - stat->total_trans++; - spin_unlock(&cpufreq_stats_lock); + if (val != CPUFREQ_POSTCHANGE) + goto put_policy; + + if (!policy->stats) { + pr_debug("%s: No stats found\n", __func__); + goto put_policy; + } + + stats = policy->stats; + + old_index = stats->last_index; + new_index = freq_table_get_index(stats, freq->new); + + /* We can't do stats->time_in_state[-1]= .. */ + if (old_index == -1 || new_index == -1) + goto put_policy; + + if (old_index == new_index) + goto put_policy; + + cpufreq_stats_update(stats); + + stats->last_index = new_index; +#ifdef CONFIG_CPU_FREQ_STAT_DETAILS + stats->trans_table[old_index * stats->max_state + new_index]++; +#endif + stats->total_trans++; + +put_policy: cpufreq_cpu_put(policy); return 0; } - -static int process_notifier(struct notifier_block *self, - unsigned long cmd, void *v) -{ - struct task_struct *task = v; - unsigned long flags; - void *temp_time_in_state, *temp_concurrent_active_time, - *temp_concurrent_policy_time; - - if (!task) - return NOTIFY_OK; - - spin_lock_irqsave(&task_time_in_state_lock, flags); - temp_time_in_state = task->time_in_state; - task->time_in_state = NULL; - spin_unlock_irqrestore(&task_time_in_state_lock, flags); - - spin_lock_irqsave(&task_concurrent_active_time_lock, flags); - temp_concurrent_active_time = task->concurrent_active_time; - task->concurrent_active_time = NULL; - spin_unlock_irqrestore(&task_concurrent_active_time_lock, flags); - - spin_lock_irqsave(&task_concurrent_policy_time_lock, flags); - temp_concurrent_policy_time = task->concurrent_policy_time; - task->concurrent_policy_time = NULL; - spin_unlock_irqrestore(&task_concurrent_policy_time_lock, flags); - - kfree(temp_time_in_state); - kfree(temp_concurrent_active_time); - kfree(temp_concurrent_policy_time); - - return NOTIFY_OK; -} - -void cpufreq_task_stats_free(struct task_struct *p) -{ - kfree(p->time_in_state); - kfree(p->concurrent_active_time); - kfree(p->concurrent_policy_time); -} - -static const struct seq_operations uid_time_in_state_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = uid_time_in_state_seq_show, -}; - -static int uid_time_in_state_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &uid_time_in_state_seq_ops); -} - -int single_uid_time_in_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, single_uid_time_in_state_show, - &(inode->i_uid)); -} - -static const struct file_operations uid_time_in_state_fops = { - .open = uid_time_in_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations time_in_state_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = time_in_state_seq_show, -}; - -int time_in_state_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &time_in_state_seq_ops); -} - -const struct file_operations time_in_state_fops = { - .open = time_in_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations concurrent_active_time_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = concurrent_active_time_seq_show, -}; - -static int concurrent_active_time_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &concurrent_active_time_seq_ops); -} - -static const struct file_operations concurrent_active_time_fops = { - .open = concurrent_active_time_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations concurrent_active_time_text_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = concurrent_active_time_text_seq_show, -}; - -static int concurrent_active_time_text_open(struct inode *inode, - struct file *file) -{ - return seq_open(file, &concurrent_active_time_text_seq_ops); -} - -static const struct file_operations concurrent_active_time_text_fops = { - .open = concurrent_active_time_text_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations concurrent_policy_time_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = concurrent_policy_time_seq_show, -}; - -static int concurrent_policy_time_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &concurrent_policy_time_seq_ops); -} - -static const struct file_operations concurrent_policy_time_fops = { - .open = concurrent_policy_time_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations concurrent_policy_time_text_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = concurrent_policy_time_text_seq_show, -}; - -static int concurrent_policy_time_text_open(struct inode *inode, - struct file *file) -{ - return seq_open(file, &concurrent_policy_time_text_seq_ops); -} - -static const struct file_operations concurrent_policy_time_text_fops = { - .open = concurrent_policy_time_text_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int uid_cpupower_enable_open(struct inode *inode, struct file *file) -{ - return single_open(file, uid_cpupower_enable_show, PDE_DATA(inode)); -} - -static const struct file_operations uid_cpupower_enable_fops = { - .open = uid_cpupower_enable_open, - .read = seq_read, - .release = single_release, - .write = uid_cpupower_enable_write, -}; - static struct notifier_block notifier_policy_block = { .notifier_call = cpufreq_stat_notifier_policy }; @@ -1260,16 +311,10 @@ static struct notifier_block notifier_trans_block = { .notifier_call = cpufreq_stat_notifier_trans }; -static struct notifier_block process_notifier_block = { - .notifier_call = process_notifier, -}; - static int __init cpufreq_stats_init(void) { int ret; unsigned int cpu; - struct cpufreq_policy *policy; - struct cpufreq_policy *last_policy = NULL; spin_lock_init(&cpufreq_stats_lock); ret = cpufreq_register_notifier(¬ifier_policy_block, @@ -1278,24 +323,10 @@ static int __init cpufreq_stats_init(void) return ret; get_online_cpus(); - for_each_online_cpu(cpu) { - policy = cpufreq_cpu_get(cpu); - if (!policy) - continue; - if (policy != last_policy) { - cpufreq_stats_create_table(policy); - last_policy = policy; - } - cpufreq_cpu_put(policy); - } + for_each_online_cpu(cpu) + cpufreq_stats_create_table(cpu); put_online_cpus(); - /* XXX TODO task support for time_in_state doesn't update freq - * info for tasks already initialized, so tasks initialized early - * (before cpufreq_stat_init is done) do not get time_in_state data - * and CPUFREQ_TRANSITION_NOTIFIER does not update freq info for - * tasks already created - */ ret = cpufreq_register_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); if (ret) { @@ -1307,47 +338,7 @@ static int __init cpufreq_stats_init(void) put_online_cpus(); return ret; } - ret = sysfs_create_file(cpufreq_global_kobject, - &_attr_all_time_in_state.attr); - if (ret) - pr_warn("Cannot create sysfs file for cpufreq stats\n"); - proc_create_data("uid_time_in_state", 0444, NULL, - &uid_time_in_state_fops, NULL); - - proc_create_data("uid_concurrent_active_time", 0444, NULL, - &concurrent_active_time_text_fops, NULL); - - proc_create_data("uid_concurrent_policy_time", 0444, NULL, - &concurrent_policy_time_text_fops, NULL); - - profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); - - ret = cpufreq_stats_create_all_table(); - if (ret) - pr_warn("Cannot create cpufreq all freqs table\n"); - - uid_cpupower = proc_mkdir("uid_cpupower", NULL); - if (!uid_cpupower) { - pr_warn("%s: failed to create uid_cputime proc entry\n", - __func__); - } else { - proc_create_data("enable", 0666, uid_cpupower, - &uid_cpupower_enable_fops, NULL); - - proc_create_data("time_in_state", 0444, uid_cpupower, - &time_in_state_fops, NULL); - - proc_create_data("concurrent_active_time", 0444, uid_cpupower, - &concurrent_active_time_fops, NULL); - - proc_create_data("concurrent_policy_time", 0444, uid_cpupower, - &concurrent_policy_time_fops, NULL); - - uid_cpupower_enable = 1; - } - - cpufreq_stats_initialized = true; return 0; } static void __exit cpufreq_stats_exit(void) diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index f126bfa635bc..3c9d311106cd 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -26,7 +26,6 @@ #include #include #include -#include #define UID_HASH_BITS 10 DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); @@ -187,14 +186,6 @@ static ssize_t uid_remove_write(struct file *file, kstrtol(end_uid, 10, &uid_end) != 0) { return -EINVAL; } - - /* TODO need to unify uid_sys_stats interface with uid_time_in_state. - * Here we are reusing remove_uid_range to reduce the number of - * sys calls made by userspace clients, remove_uid_range removes uids - * from both here as well as from cpufreq uid_time_in_state - */ - cpufreq_task_stats_remove_uids(uid_start, uid_end); - rt_mutex_lock(&uid_lock); for (; uid_start <= uid_end; uid_start++) { @@ -242,29 +233,13 @@ static void compute_uid_io_bucket_stats(struct io_stats *io_bucket, struct io_stats *io_last, struct io_stats *io_dead) { - s64 delta; - - delta = io_curr->read_bytes + io_dead->read_bytes - + io_bucket->read_bytes += io_curr->read_bytes + io_dead->read_bytes - io_last->read_bytes; - if (delta > 0) - io_bucket->read_bytes += delta; - - delta = io_curr->write_bytes + io_dead->write_bytes - + io_bucket->write_bytes += io_curr->write_bytes + io_dead->write_bytes - io_last->write_bytes; - if (delta > 0) - io_bucket->write_bytes += delta; - - delta = io_curr->rchar + io_dead->rchar - io_last->rchar; - if (delta > 0) - io_bucket->rchar += delta; - - delta = io_curr->wchar + io_dead->wchar - io_last->wchar; - if (delta > 0) - io_bucket->wchar += delta; - - delta = io_curr->fsync + io_dead->fsync - io_last->fsync; - if (delta > 0) - io_bucket->fsync += delta; + io_bucket->rchar += io_curr->rchar + io_dead->rchar - io_last->rchar; + io_bucket->wchar += io_curr->wchar + io_dead->wchar - io_last->wchar; + io_bucket->fsync += io_curr->fsync + io_dead->fsync - io_last->fsync; io_last->read_bytes = io_curr->read_bytes; io_last->write_bytes = io_curr->write_bytes; diff --git a/fs/proc/Makefile b/fs/proc/Makefile index 2c739a51a65d..7151ea428041 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -24,7 +24,6 @@ proc-y += softirqs.o proc-y += namespaces.o proc-y += self.o proc-y += thread_self.o -proc-y += uid.o proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o proc-$(CONFIG_NET) += proc_net.o proc-$(CONFIG_PROC_KCORE) += kcore.o diff --git a/fs/proc/base.c b/fs/proc/base.c index 65f20a64e340..4b830af77502 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -87,7 +87,6 @@ #include #include #include -#include #ifdef CONFIG_HARDWALL #include #endif @@ -2980,11 +2979,6 @@ static const struct pid_entry tgid_base_stuff[] = { REG("timers", S_IRUGO, proc_timers_operations), #endif REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations), -#ifdef CONFIG_CPU_FREQ_STAT - ONE("time_in_state", 0444, proc_time_in_state_show), - ONE("concurrent_active_time", 0444, proc_concurrent_active_time_show), - ONE("concurrent_policy_time", 0444, proc_concurrent_policy_time_show), -#endif }; static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) @@ -3370,11 +3364,6 @@ static const struct pid_entry tid_base_stuff[] = { REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), #endif -#ifdef CONFIG_CPU_FREQ_STAT - ONE("time_in_state", 0444, proc_time_in_state_show), - ONE("concurrent_active_time", 0444, proc_concurrent_active_time_show), - ONE("concurrent_policy_time", 0444, proc_concurrent_policy_time_show), -#endif }; static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) diff --git a/fs/proc/internal.h b/fs/proc/internal.h index a171baf2b4ce..3448a19478d4 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -256,11 +256,6 @@ static inline void proc_sys_init(void) { } static inline void sysctl_head_put(struct ctl_table_header *head) { } #endif -/* - * uid.c - */ -extern int proc_uid_init(void); - /* * proc_tty.c */ diff --git a/fs/proc/root.c b/fs/proc/root.c index 1d0b6a125563..ec649c92d270 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -182,7 +182,7 @@ void __init proc_root_init(void) proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); - proc_uid_init(); + #ifdef CONFIG_SYSVIPC proc_mkdir("sysvipc", NULL); #endif diff --git a/fs/proc/uid.c b/fs/proc/uid.c deleted file mode 100644 index f096e36b4946..000000000000 --- a/fs/proc/uid.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * /proc/uid support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "internal.h" - -struct proc_dir_entry *proc_uid; - -#define UID_HASH_BITS 10 - -static DECLARE_HASHTABLE(proc_uid_hash_table, UID_HASH_BITS); - -static DEFINE_RT_MUTEX(proc_uid_lock); /* proc_uid_hash_table */ - -struct uid_hash_entry { - uid_t uid; - struct hlist_node hash; -}; - -/* Caller must hold proc_uid_lock */ -static bool uid_hash_entry_exists(uid_t uid) -{ - struct uid_hash_entry *entry; - - hash_for_each_possible(proc_uid_hash_table, entry, hash, uid) { - if (entry->uid == uid) - return true; - } - return false; -} - -void proc_register_uid(kuid_t kuid) -{ - struct uid_hash_entry *entry; - bool exists; - uid_t uid = from_kuid_munged(current_user_ns(), kuid); - - rt_mutex_lock(&proc_uid_lock); - exists = uid_hash_entry_exists(uid); - rt_mutex_unlock(&proc_uid_lock); - if (exists) - return; - - entry = kzalloc(sizeof(struct uid_hash_entry), GFP_KERNEL); - if (!entry) - return; - entry->uid = uid; - - rt_mutex_lock(&proc_uid_lock); - if (uid_hash_entry_exists(uid)) { - kfree(entry); - } else { - hash_add(proc_uid_hash_table, &entry->hash, uid); - } - rt_mutex_unlock(&proc_uid_lock); -} - -struct uid_entry { - const char *name; - int len; - umode_t mode; - const struct inode_operations *iop; - const struct file_operations *fop; -}; - -#define NOD(NAME, MODE, IOP, FOP) { \ - .name = (NAME), \ - .len = sizeof(NAME) - 1, \ - .mode = MODE, \ - .iop = IOP, \ - .fop = FOP, \ -} - -#ifdef CONFIG_CPU_FREQ_STAT -const struct file_operations proc_uid_time_in_state_operations = { - .open = single_uid_time_in_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -static const struct uid_entry uid_base_stuff[] = { -#ifdef CONFIG_CPU_FREQ_STAT - NOD("time_in_state", 0444, NULL, &proc_uid_time_in_state_operations), -#endif -}; - -const struct inode_operations proc_uid_def_inode_operations = { - .setattr = proc_setattr, -}; - -struct inode *proc_uid_make_inode(struct super_block *sb, kuid_t kuid) -{ - struct inode *inode; - - inode = new_inode(sb); - if (!inode) - return NULL; - - inode->i_ino = get_next_ino(); - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_op = &proc_uid_def_inode_operations; - inode->i_uid = kuid; - - return inode; -} - -static int proc_uident_instantiate(struct inode *dir, struct dentry *dentry, - struct task_struct *unused, const void *ptr) -{ - const struct uid_entry *u = ptr; - struct inode *inode; - - inode = proc_uid_make_inode(dir->i_sb, dir->i_uid); - if (!inode) - return -ENOENT; - - inode->i_mode = u->mode; - if (S_ISDIR(inode->i_mode)) - set_nlink(inode, 2); - if (u->iop) - inode->i_op = u->iop; - if (u->fop) - inode->i_fop = u->fop; - d_add(dentry, inode); - return 0; -} - -static struct dentry *proc_uid_base_lookup(struct inode *dir, - struct dentry *dentry, - unsigned int flags) -{ - const struct uid_entry *u, *last; - unsigned int nents = ARRAY_SIZE(uid_base_stuff); - - if (nents == 0) - return ERR_PTR(-ENOENT); - - last = &uid_base_stuff[nents - 1]; - for (u = uid_base_stuff; u <= last; u++) { - if (u->len != dentry->d_name.len) - continue; - if (!memcmp(dentry->d_name.name, u->name, u->len)) - break; - } - if (u > last) - return ERR_PTR(-ENOENT); - - return ERR_PTR(proc_uident_instantiate(dir, dentry, NULL, u)); -} - -static int proc_uid_base_readdir(struct file *file, struct dir_context *ctx) -{ - unsigned int nents = ARRAY_SIZE(uid_base_stuff); - const struct uid_entry *u; - - if (!dir_emit_dots(file, ctx)) - return 0; - - if (ctx->pos >= nents + 2) - return 0; - - for (u = uid_base_stuff + (ctx->pos - 2); - u <= uid_base_stuff + nents - 1; u++) { - if (!proc_fill_cache(file, ctx, u->name, u->len, - proc_uident_instantiate, NULL, u)) - break; - ctx->pos++; - } - - return 0; -} - -static const struct inode_operations proc_uid_base_inode_operations = { - .lookup = proc_uid_base_lookup, - .setattr = proc_setattr, -}; - -static const struct file_operations proc_uid_base_operations = { - .read = generic_read_dir, - .iterate = proc_uid_base_readdir, - .llseek = default_llseek, -}; - -static int proc_uid_instantiate(struct inode *dir, struct dentry *dentry, - struct task_struct *unused, const void *ptr) -{ - unsigned int i, len; - nlink_t nlinks; - kuid_t *kuid = (kuid_t *)ptr; - struct inode *inode = proc_uid_make_inode(dir->i_sb, *kuid); - - if (!inode) - return -ENOENT; - - inode->i_mode = S_IFDIR | 0555; - inode->i_op = &proc_uid_base_inode_operations; - inode->i_fop = &proc_uid_base_operations; - inode->i_flags |= S_IMMUTABLE; - - nlinks = 2; - len = ARRAY_SIZE(uid_base_stuff); - for (i = 0; i < len; ++i) { - if (S_ISDIR(uid_base_stuff[i].mode)) - ++nlinks; - } - set_nlink(inode, nlinks); - - d_add(dentry, inode); - - return 0; -} - -static int proc_uid_readdir(struct file *file, struct dir_context *ctx) -{ - int last_shown, i; - unsigned long bkt; - struct uid_hash_entry *entry; - - if (!dir_emit_dots(file, ctx)) - return 0; - - i = 0; - last_shown = ctx->pos - 2; - rt_mutex_lock(&proc_uid_lock); - hash_for_each(proc_uid_hash_table, bkt, entry, hash) { - int len; - char buf[PROC_NUMBUF]; - - if (i < last_shown) - continue; - len = snprintf(buf, sizeof(buf), "%u", entry->uid); - if (!proc_fill_cache(file, ctx, buf, len, - proc_uid_instantiate, NULL, &entry->uid)) - break; - i++; - ctx->pos++; - } - rt_mutex_unlock(&proc_uid_lock); - return 0; -} - -static struct dentry *proc_uid_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - int result = -ENOENT; - - uid_t uid = name_to_int(&dentry->d_name); - bool uid_exists; - - rt_mutex_lock(&proc_uid_lock); - uid_exists = uid_hash_entry_exists(uid); - rt_mutex_unlock(&proc_uid_lock); - if (uid_exists) { - kuid_t kuid = make_kuid(current_user_ns(), uid); - - result = proc_uid_instantiate(dir, dentry, NULL, &kuid); - } - return ERR_PTR(result); -} - -static const struct file_operations proc_uid_operations = { - .read = generic_read_dir, - .iterate = proc_uid_readdir, - .llseek = default_llseek, -}; - -static const struct inode_operations proc_uid_inode_operations = { - .lookup = proc_uid_lookup, - .setattr = proc_setattr, -}; - -int __init proc_uid_init(void) -{ - proc_uid = proc_mkdir("uid", NULL); - if (!proc_uid) - return -ENOMEM; - proc_uid->proc_iops = &proc_uid_inode_operations; - proc_uid->proc_fops = &proc_uid_operations; - - return 0; -} diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index e790a5b4322e..73c442557b03 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -651,8 +650,6 @@ int cpufreq_boost_supported(void); int cpufreq_boost_enabled(void); int cpufreq_enable_boost_support(void); bool policy_has_boost_freq(struct cpufreq_policy *policy); -void acct_update_power(struct task_struct *p, cputime_t cputime); -void cpufreq_task_stats_init(struct task_struct *p); #else static inline int cpufreq_boost_trigger_state(int state) { @@ -696,32 +693,3 @@ struct sched_domain; unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu); unsigned long cpufreq_scale_max_freq_capacity(int cpu); #endif /* _LINUX_CPUFREQ_H */ - -/********************************************************************* - * CPUFREQ STATS * - *********************************************************************/ - -#ifdef CONFIG_CPU_FREQ_STAT - -void acct_update_power(struct task_struct *p, cputime_t cputime); -void cpufreq_task_stats_init(struct task_struct *p); -void cpufreq_task_stats_alloc(struct task_struct *p); -void cpufreq_task_stats_free(struct task_struct *p); -void cpufreq_task_stats_remove_uids(uid_t uid_start, uid_t uid_end); -int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, - struct pid *pid, struct task_struct *p); -int proc_concurrent_active_time_show(struct seq_file *m, - struct pid_namespace *ns, struct pid *pid, struct task_struct *p); -int proc_concurrent_policy_time_show(struct seq_file *m, - struct pid_namespace *ns, struct pid *pid, struct task_struct *p); -int single_uid_time_in_state_open(struct inode *inode, struct file *file); -#else -static inline void acct_update_power(struct task_struct *p, - cputime_t cputime) {} -static inline void cpufreq_task_stats_init(struct task_struct *p) {} -static inline void cpufreq_task_stats_alloc(struct task_struct *p) {} -static inline void cpufreq_task_stats_free(struct task_struct *p) {} -static inline void cpufreq_task_stats_exit(struct task_struct *p) {} -static inline void cpufreq_task_stats_remove_uids(uid_t uid_start, - uid_t uid_end) {} -#endif diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index ad82a044460f..b97bf2ef996e 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -41,7 +41,6 @@ extern void *proc_get_parent_data(const struct inode *); extern void proc_remove(struct proc_dir_entry *); extern void remove_proc_entry(const char *, struct proc_dir_entry *); extern int remove_proc_subtree(const char *, struct proc_dir_entry *); -extern void proc_register_uid(kuid_t uid); #else /* CONFIG_PROC_FS */ @@ -72,7 +71,6 @@ static inline void *proc_get_parent_data(const struct inode *inode) { BUG(); ret static inline void proc_remove(struct proc_dir_entry *de) {} #define remove_proc_entry(name, parent) do {} while (0) static inline int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) { return 0; } -static inline void proc_register_uid(kuid_t uid) {} #endif /* CONFIG_PROC_FS */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 64e87adb99f5..bbdfe09abbf1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1721,8 +1721,6 @@ struct task_struct { cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; - atomic64_t *time_in_state; - unsigned int max_state; struct prev_cputime prev_cputime; #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN seqlock_t vtime_seqlock; @@ -2041,8 +2039,6 @@ struct task_struct { unsigned long task_state_change; #endif int pagefault_disabled; - atomic64_t *concurrent_active_time; - atomic64_t *concurrent_policy_time; /* CPU-specific state of this task */ struct thread_struct thread; /* diff --git a/kernel/exit.c b/kernel/exit.c index 09b605e13606..a08ce205b5bf 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -54,7 +54,6 @@ #include #include #include -#include #include "sched/tune.h" diff --git a/kernel/fork.c b/kernel/fork.c index 2b2b231ef044..82cbc0a2dca7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -78,7 +78,6 @@ #include #include #include -#include #include #include @@ -228,9 +227,6 @@ static void account_kernel_stack(unsigned long *stack, int account) void free_task(struct task_struct *tsk) { -#ifdef CONFIG_CPU_FREQ_STAT - cpufreq_task_stats_free(tsk); -#endif account_kernel_stack(tsk->stack, -1); arch_release_thread_stack(tsk->stack); free_thread_stack(tsk->stack); @@ -1368,10 +1364,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, if (!p) goto fork_out; -#ifdef CONFIG_CPU_FREQ_STAT - cpufreq_task_stats_init(p); -#endif - /* * This _must_ happen before we call free_task(), i.e. before we jump * to any of the bad_fork_* labels. This is to avoid freeing diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8ac573367bb2..c2b9071c8e7e 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -75,7 +75,6 @@ #include #include #include -#include #include #include @@ -2180,10 +2179,6 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) memset(&p->se.statistics, 0, sizeof(p->se.statistics)); #endif -#ifdef CONFIG_CPU_FREQ_STAT - cpufreq_task_stats_init(p); -#endif - RB_CLEAR_NODE(&p->dl.rb_node); init_dl_task_timer(&p->dl); __dl_clear_params(p); @@ -2262,11 +2257,6 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) int cpu = get_cpu(); __sched_fork(clone_flags, p); - -#ifdef CONFIG_CPU_FREQ_STAT - cpufreq_task_stats_alloc(p); -#endif - /* * We mark the process as running here. This guarantees that * nobody will actually run it, and a signal or other external diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index c92ddb265e3c..acde1d7c763c 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "sched.h" #include "walt.h" @@ -166,11 +165,6 @@ void account_user_time(struct task_struct *p, cputime_t cputime, /* Account for user time used */ acct_account_cputime(p); - -#ifdef CONFIG_CPU_FREQ_STAT - /* Account power usage for system time */ - acct_update_power(p, cputime); -#endif } /* @@ -221,11 +215,6 @@ void __account_system_time(struct task_struct *p, cputime_t cputime, /* Account for system time used */ acct_account_cputime(p); - -#ifdef CONFIG_CPU_FREQ_STAT - /* Account power usage for system time */ - acct_update_power(p, cputime); -#endif } /* diff --git a/kernel/user.c b/kernel/user.c index 41e94e453836..b069ccbfb0b0 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -16,7 +16,6 @@ #include #include #include -#include #include /* @@ -202,7 +201,6 @@ struct user_struct *alloc_uid(kuid_t uid) } spin_unlock_irq(&uidhash_lock); } - proc_register_uid(uid); return up; @@ -224,7 +222,6 @@ static int __init uid_cache_init(void) spin_lock_irq(&uidhash_lock); uid_hash_insert(&root_user, uidhashentry(GLOBAL_ROOT_UID)); spin_unlock_irq(&uidhash_lock); - proc_register_uid(GLOBAL_ROOT_UID); return 0; }