mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
quota: Convert quota statistics to generic percpu_counter
Generic per-cpu counter has some memory overhead but it is negligible for
modern systems and embedded systems compile without quota support. And code
reuse is a good thing. This patch should fix complain from preemptive kernels
which was introduced by dde9588853
.
[Jan Kara: Fixed patch to work on 32-bit archs as well]
Reported-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
1513b02c8b
commit
f32764bd2b
2 changed files with 17 additions and 45 deletions
|
@ -228,10 +228,6 @@ static struct hlist_head *dquot_hash;
|
|||
|
||||
struct dqstats dqstats;
|
||||
EXPORT_SYMBOL(dqstats);
|
||||
#ifdef CONFIG_SMP
|
||||
struct dqstats *dqstats_pcpu;
|
||||
EXPORT_SYMBOL(dqstats_pcpu);
|
||||
#endif
|
||||
|
||||
static qsize_t inode_get_rsv_space(struct inode *inode);
|
||||
static void __dquot_initialize(struct inode *inode, int type);
|
||||
|
@ -676,27 +672,10 @@ static void prune_dqcache(int count)
|
|||
}
|
||||
}
|
||||
|
||||
static int dqstats_read(unsigned int type)
|
||||
{
|
||||
int count = 0;
|
||||
#ifdef CONFIG_SMP
|
||||
int cpu;
|
||||
for_each_possible_cpu(cpu)
|
||||
count += per_cpu_ptr(dqstats_pcpu, cpu)->stat[type];
|
||||
/* Statistics reading is racy, but absolute accuracy isn't required */
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
#else
|
||||
count = dqstats.stat[type];
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from kswapd when we think we need some
|
||||
* more memory
|
||||
*/
|
||||
|
||||
static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
|
||||
{
|
||||
if (nr) {
|
||||
|
@ -704,7 +683,9 @@ static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
|
|||
prune_dqcache(nr);
|
||||
spin_unlock(&dq_list_lock);
|
||||
}
|
||||
return (dqstats_read(DQST_FREE_DQUOTS)/100) * sysctl_vfs_cache_pressure;
|
||||
return ((unsigned)
|
||||
percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS])
|
||||
/100) * sysctl_vfs_cache_pressure;
|
||||
}
|
||||
|
||||
static struct shrinker dqcache_shrinker = {
|
||||
|
@ -2497,11 +2478,11 @@ EXPORT_SYMBOL(dquot_quotactl_ops);
|
|||
static int do_proc_dqstats(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
/* Update global table */
|
||||
unsigned int type = (int *)table->data - dqstats.stat;
|
||||
dqstats.stat[type] = dqstats_read(type);
|
||||
#endif
|
||||
|
||||
/* Update global table */
|
||||
dqstats.stat[type] =
|
||||
percpu_counter_sum_positive(&dqstats.counter[type]);
|
||||
return proc_dointvec(table, write, buffer, lenp, ppos);
|
||||
}
|
||||
|
||||
|
@ -2594,7 +2575,7 @@ static ctl_table sys_table[] = {
|
|||
|
||||
static int __init dquot_init(void)
|
||||
{
|
||||
int i;
|
||||
int i, ret;
|
||||
unsigned long nr_hash, order;
|
||||
|
||||
printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
|
||||
|
@ -2612,12 +2593,11 @@ static int __init dquot_init(void)
|
|||
if (!dquot_hash)
|
||||
panic("Cannot create dquot hash table");
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
dqstats_pcpu = alloc_percpu(struct dqstats);
|
||||
if (!dqstats_pcpu)
|
||||
panic("Cannot create dquot stats table");
|
||||
#endif
|
||||
memset(&dqstats, 0, sizeof(struct dqstats));
|
||||
for (i = 0; i < _DQST_DQSTAT_LAST; i++) {
|
||||
ret = percpu_counter_init(&dqstats.counter[i], 0);
|
||||
if (ret)
|
||||
panic("Cannot create dquot stat counters");
|
||||
}
|
||||
|
||||
/* Find power-of-two hlist_heads which can fit into allocation */
|
||||
nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head);
|
||||
|
|
|
@ -174,8 +174,7 @@ enum {
|
|||
#include <linux/rwsem.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/percpu_counter.h>
|
||||
|
||||
#include <linux/dqblk_xfs.h>
|
||||
#include <linux/dqblk_v1.h>
|
||||
|
@ -254,6 +253,7 @@ enum {
|
|||
|
||||
struct dqstats {
|
||||
int stat[_DQST_DQSTAT_LAST];
|
||||
struct percpu_counter counter[_DQST_DQSTAT_LAST];
|
||||
};
|
||||
|
||||
extern struct dqstats *dqstats_pcpu;
|
||||
|
@ -261,20 +261,12 @@ extern struct dqstats dqstats;
|
|||
|
||||
static inline void dqstats_inc(unsigned int type)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
per_cpu_ptr(dqstats_pcpu, smp_processor_id())->stat[type]++;
|
||||
#else
|
||||
dqstats.stat[type]++;
|
||||
#endif
|
||||
percpu_counter_inc(&dqstats.counter[type]);
|
||||
}
|
||||
|
||||
static inline void dqstats_dec(unsigned int type)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
per_cpu_ptr(dqstats_pcpu, smp_processor_id())->stat[type]--;
|
||||
#else
|
||||
dqstats.stat[type]--;
|
||||
#endif
|
||||
percpu_counter_dec(&dqstats.counter[type]);
|
||||
}
|
||||
|
||||
#define DQ_MOD_B 0 /* dquot modified since read */
|
||||
|
|
Loading…
Reference in a new issue