aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Monakhov <dmonakhov@openvz.org>2010-05-26 17:21:58 -0400
committerJan Kara <jack@suse.cz>2010-05-27 12:56:27 -0400
commitf32764bd2bbb6ea003c158b1d276b4dc9f900348 (patch)
tree7fbabde3796a97b8b121349ea76b22b23238230a
parent1513b02c8b537af275ea74fdfb380c618b9e6778 (diff)
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 dde9588853b1bde. [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>
-rw-r--r--fs/quota/dquot.c46
-rw-r--r--include/linux/quota.h16
2 files changed, 17 insertions, 45 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 1ff91314b8a0..531dee651ef7 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -228,10 +228,6 @@ static struct hlist_head *dquot_hash;
228 228
229struct dqstats dqstats; 229struct dqstats dqstats;
230EXPORT_SYMBOL(dqstats); 230EXPORT_SYMBOL(dqstats);
231#ifdef CONFIG_SMP
232struct dqstats *dqstats_pcpu;
233EXPORT_SYMBOL(dqstats_pcpu);
234#endif
235 231
236static qsize_t inode_get_rsv_space(struct inode *inode); 232static qsize_t inode_get_rsv_space(struct inode *inode);
237static void __dquot_initialize(struct inode *inode, int type); 233static void __dquot_initialize(struct inode *inode, int type);
@@ -676,27 +672,10 @@ static void prune_dqcache(int count)
676 } 672 }
677} 673}
678 674
679static int dqstats_read(unsigned int type)
680{
681 int count = 0;
682#ifdef CONFIG_SMP
683 int cpu;
684 for_each_possible_cpu(cpu)
685 count += per_cpu_ptr(dqstats_pcpu, cpu)->stat[type];
686 /* Statistics reading is racy, but absolute accuracy isn't required */
687 if (count < 0)
688 count = 0;
689#else
690 count = dqstats.stat[type];
691#endif
692 return count;
693}
694
695/* 675/*
696 * This is called from kswapd when we think we need some 676 * This is called from kswapd when we think we need some
697 * more memory 677 * more memory
698 */ 678 */
699
700static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) 679static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
701{ 680{
702 if (nr) { 681 if (nr) {
@@ -704,7 +683,9 @@ static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
704 prune_dqcache(nr); 683 prune_dqcache(nr);
705 spin_unlock(&dq_list_lock); 684 spin_unlock(&dq_list_lock);
706 } 685 }
707 return (dqstats_read(DQST_FREE_DQUOTS)/100) * sysctl_vfs_cache_pressure; 686 return ((unsigned)
687 percpu_counter_read_positive(&dqstats.counter[DQST_FREE_DQUOTS])
688 /100) * sysctl_vfs_cache_pressure;
708} 689}
709 690
710static struct shrinker dqcache_shrinker = { 691static struct shrinker dqcache_shrinker = {
@@ -2497,11 +2478,11 @@ EXPORT_SYMBOL(dquot_quotactl_ops);
2497static int do_proc_dqstats(struct ctl_table *table, int write, 2478static int do_proc_dqstats(struct ctl_table *table, int write,
2498 void __user *buffer, size_t *lenp, loff_t *ppos) 2479 void __user *buffer, size_t *lenp, loff_t *ppos)
2499{ 2480{
2500#ifdef CONFIG_SMP
2501 /* Update global table */
2502 unsigned int type = (int *)table->data - dqstats.stat; 2481 unsigned int type = (int *)table->data - dqstats.stat;
2503 dqstats.stat[type] = dqstats_read(type); 2482
2504#endif 2483 /* Update global table */
2484 dqstats.stat[type] =
2485 percpu_counter_sum_positive(&dqstats.counter[type]);
2505 return proc_dointvec(table, write, buffer, lenp, ppos); 2486 return proc_dointvec(table, write, buffer, lenp, ppos);
2506} 2487}
2507 2488
@@ -2594,7 +2575,7 @@ static ctl_table sys_table[] = {
2594 2575
2595static int __init dquot_init(void) 2576static int __init dquot_init(void)
2596{ 2577{
2597 int i; 2578 int i, ret;
2598 unsigned long nr_hash, order; 2579 unsigned long nr_hash, order;
2599 2580
2600 printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__); 2581 printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
@@ -2612,12 +2593,11 @@ static int __init dquot_init(void)
2612 if (!dquot_hash) 2593 if (!dquot_hash)
2613 panic("Cannot create dquot hash table"); 2594 panic("Cannot create dquot hash table");
2614 2595
2615#ifdef CONFIG_SMP 2596 for (i = 0; i < _DQST_DQSTAT_LAST; i++) {
2616 dqstats_pcpu = alloc_percpu(struct dqstats); 2597 ret = percpu_counter_init(&dqstats.counter[i], 0);
2617 if (!dqstats_pcpu) 2598 if (ret)
2618 panic("Cannot create dquot stats table"); 2599 panic("Cannot create dquot stat counters");
2619#endif 2600 }
2620 memset(&dqstats, 0, sizeof(struct dqstats));
2621 2601
2622 /* Find power-of-two hlist_heads which can fit into allocation */ 2602 /* Find power-of-two hlist_heads which can fit into allocation */
2623 nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head); 2603 nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 2789d07c37be..94c1f03b50eb 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -174,8 +174,7 @@ enum {
174#include <linux/rwsem.h> 174#include <linux/rwsem.h>
175#include <linux/spinlock.h> 175#include <linux/spinlock.h>
176#include <linux/wait.h> 176#include <linux/wait.h>
177#include <linux/percpu.h> 177#include <linux/percpu_counter.h>
178#include <linux/smp.h>
179 178
180#include <linux/dqblk_xfs.h> 179#include <linux/dqblk_xfs.h>
181#include <linux/dqblk_v1.h> 180#include <linux/dqblk_v1.h>
@@ -254,6 +253,7 @@ enum {
254 253
255struct dqstats { 254struct dqstats {
256 int stat[_DQST_DQSTAT_LAST]; 255 int stat[_DQST_DQSTAT_LAST];
256 struct percpu_counter counter[_DQST_DQSTAT_LAST];
257}; 257};
258 258
259extern struct dqstats *dqstats_pcpu; 259extern struct dqstats *dqstats_pcpu;
@@ -261,20 +261,12 @@ extern struct dqstats dqstats;
261 261
262static inline void dqstats_inc(unsigned int type) 262static inline void dqstats_inc(unsigned int type)
263{ 263{
264#ifdef CONFIG_SMP 264 percpu_counter_inc(&dqstats.counter[type]);
265 per_cpu_ptr(dqstats_pcpu, smp_processor_id())->stat[type]++;
266#else
267 dqstats.stat[type]++;
268#endif
269} 265}
270 266
271static inline void dqstats_dec(unsigned int type) 267static inline void dqstats_dec(unsigned int type)
272{ 268{
273#ifdef CONFIG_SMP 269 percpu_counter_dec(&dqstats.counter[type]);
274 per_cpu_ptr(dqstats_pcpu, smp_processor_id())->stat[type]--;
275#else
276 dqstats.stat[type]--;
277#endif
278} 270}
279 271
280#define DQ_MOD_B 0 /* dquot modified since read */ 272#define DQ_MOD_B 0 /* dquot modified since read */