Commit a685c6d0 authored by Viresh Kumar's avatar Viresh Kumar Committed by Rafael J. Wysocki

cpufreq: stats: create sysfs group once we are ready

Userspace is free to read value of any file from cpufreq/stats directory once
they are created. __cpufreq_stats_create_table() is creating the sysfs files
first and then allocating resources for them. Though it would be quite difficult
to trigger the racy situation here, but for the sake of keeping sensible code
lets create sysfs entries only after we are ready to go.

This also does some makeup to the routine to make it look better.
Reviewed-by: default avatarPrarit Bhargava <prarit@redhat.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent d9f35446
...@@ -164,12 +164,13 @@ static void cpufreq_stats_free_table(unsigned int cpu) ...@@ -164,12 +164,13 @@ static void cpufreq_stats_free_table(unsigned int cpu)
static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
{ {
unsigned int i, count = 0, ret = 0; unsigned int i = 0, count = 0, ret = -ENOMEM;
struct cpufreq_stats *stats; struct cpufreq_stats *stats;
unsigned int alloc_size; unsigned int alloc_size;
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct cpufreq_frequency_table *pos, *table; struct cpufreq_frequency_table *pos, *table;
/* We need cpufreq table for creating stats table */
table = cpufreq_frequency_get_table(cpu); table = cpufreq_frequency_get_table(cpu);
if (unlikely(!table)) if (unlikely(!table))
return 0; return 0;
...@@ -179,15 +180,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) ...@@ -179,15 +180,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
return -EEXIST; return -EEXIST;
stats = kzalloc(sizeof(*stats), GFP_KERNEL); stats = kzalloc(sizeof(*stats), GFP_KERNEL);
if ((stats) == NULL) if (!stats)
return -ENOMEM; return -ENOMEM;
ret = sysfs_create_group(&policy->kobj, &stats_attr_group); /* Find total allocation size */
if (ret)
goto error_out;
policy->stats = stats;
cpufreq_for_each_valid_entry(pos, table) cpufreq_for_each_valid_entry(pos, table)
count++; count++;
...@@ -196,32 +192,42 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) ...@@ -196,32 +192,42 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
alloc_size += count * count * sizeof(int); alloc_size += count * count * sizeof(int);
#endif #endif
stats->max_state = count;
/* Allocate memory for time_in_state/freq_table/trans_table in one go */
stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
if (!stats->time_in_state) { if (!stats->time_in_state)
ret = -ENOMEM; goto free_stat;
goto error_alloc;
}
stats->freq_table = (unsigned int *)(stats->time_in_state + count); stats->freq_table = (unsigned int *)(stats->time_in_state + count);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
stats->trans_table = stats->freq_table + count; stats->trans_table = stats->freq_table + count;
#endif #endif
i = 0;
stats->max_state = count;
/* Find valid-unique entries */
cpufreq_for_each_valid_entry(pos, table) cpufreq_for_each_valid_entry(pos, table)
if (freq_table_get_index(stats, pos->frequency) == -1) if (freq_table_get_index(stats, pos->frequency) == -1)
stats->freq_table[i++] = pos->frequency; stats->freq_table[i++] = pos->frequency;
stats->state_num = i; stats->state_num = i;
spin_lock(&cpufreq_stats_lock); spin_lock(&cpufreq_stats_lock);
stats->last_time = get_jiffies_64(); stats->last_time = get_jiffies_64();
stats->last_index = freq_table_get_index(stats, policy->cur); stats->last_index = freq_table_get_index(stats, policy->cur);
spin_unlock(&cpufreq_stats_lock); spin_unlock(&cpufreq_stats_lock);
policy->stats = stats;
ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
if (!ret)
return 0; return 0;
error_alloc:
sysfs_remove_group(&policy->kobj, &stats_attr_group); /* We failed, release resources */
error_out:
kfree(stats);
policy->stats = NULL; policy->stats = NULL;
kfree(stats->time_in_state);
free_stat:
kfree(stats);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment