diff options
| -rw-r--r-- | fs/quota/dquot.c | 46 | ||||
| -rw-r--r-- | include/linux/quota.h | 16 |
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 | ||
| 229 | struct dqstats dqstats; | 229 | struct dqstats dqstats; |
| 230 | EXPORT_SYMBOL(dqstats); | 230 | EXPORT_SYMBOL(dqstats); |
| 231 | #ifdef CONFIG_SMP | ||
| 232 | struct dqstats *dqstats_pcpu; | ||
| 233 | EXPORT_SYMBOL(dqstats_pcpu); | ||
| 234 | #endif | ||
| 235 | 231 | ||
| 236 | static qsize_t inode_get_rsv_space(struct inode *inode); | 232 | static qsize_t inode_get_rsv_space(struct inode *inode); |
| 237 | static void __dquot_initialize(struct inode *inode, int type); | 233 | static void __dquot_initialize(struct inode *inode, int type); |
| @@ -676,27 +672,10 @@ static void prune_dqcache(int count) | |||
| 676 | } | 672 | } |
| 677 | } | 673 | } |
| 678 | 674 | ||
| 679 | static 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 | |||
| 700 | static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) | 679 | static 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 | ||
| 710 | static struct shrinker dqcache_shrinker = { | 691 | static struct shrinker dqcache_shrinker = { |
| @@ -2497,11 +2478,11 @@ EXPORT_SYMBOL(dquot_quotactl_ops); | |||
| 2497 | static int do_proc_dqstats(struct ctl_table *table, int write, | 2478 | static 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 | ||
| 2595 | static int __init dquot_init(void) | 2576 | static 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 | ||
| 255 | struct dqstats { | 254 | struct 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 | ||
| 259 | extern struct dqstats *dqstats_pcpu; | 259 | extern struct dqstats *dqstats_pcpu; |
| @@ -261,20 +261,12 @@ extern struct dqstats dqstats; | |||
| 261 | 261 | ||
| 262 | static inline void dqstats_inc(unsigned int type) | 262 | static 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 | ||
| 271 | static inline void dqstats_dec(unsigned int type) | 267 | static 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 */ |
