forked from mirrors/linux
		
	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
	
	 Dmitry Monakhov
						Dmitry Monakhov