Skip to content

Commit f32764b

Browse files
Dmitry Monakhovjankara
authored andcommitted
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 dde9588. [Jan Kara: Fixed patch to work on 32-bit archs as well] Reported-by: Rafael J. Wysocki <[email protected]> Signed-off-by: Dmitry Monakhov <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 1513b02 commit f32764b

File tree

2 files changed

+17
-45
lines changed

2 files changed

+17
-45
lines changed

fs/quota/dquot.c

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,6 @@ static struct hlist_head *dquot_hash;
228228

229229
struct dqstats dqstats;
230230
EXPORT_SYMBOL(dqstats);
231-
#ifdef CONFIG_SMP
232-
struct dqstats *dqstats_pcpu;
233-
EXPORT_SYMBOL(dqstats_pcpu);
234-
#endif
235231

236232
static qsize_t inode_get_rsv_space(struct inode *inode);
237233
static void __dquot_initialize(struct inode *inode, int type);
@@ -676,35 +672,20 @@ static void prune_dqcache(int count)
676672
}
677673
}
678674

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-
695675
/*
696676
* This is called from kswapd when we think we need some
697677
* more memory
698678
*/
699-
700679
static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
701680
{
702681
if (nr) {
703682
spin_lock(&dq_list_lock);
704683
prune_dqcache(nr);
705684
spin_unlock(&dq_list_lock);
706685
}
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;
708689
}
709690

710691
static struct shrinker dqcache_shrinker = {
@@ -2497,11 +2478,11 @@ EXPORT_SYMBOL(dquot_quotactl_ops);
24972478
static int do_proc_dqstats(struct ctl_table *table, int write,
24982479
void __user *buffer, size_t *lenp, loff_t *ppos)
24992480
{
2500-
#ifdef CONFIG_SMP
2501-
/* Update global table */
25022481
unsigned int type = (int *)table->data - dqstats.stat;
2503-
dqstats.stat[type] = dqstats_read(type);
2504-
#endif
2482+
2483+
/* Update global table */
2484+
dqstats.stat[type] =
2485+
percpu_counter_sum_positive(&dqstats.counter[type]);
25052486
return proc_dointvec(table, write, buffer, lenp, ppos);
25062487
}
25072488

@@ -2594,7 +2575,7 @@ static ctl_table sys_table[] = {
25942575

25952576
static int __init dquot_init(void)
25962577
{
2597-
int i;
2578+
int i, ret;
25982579
unsigned long nr_hash, order;
25992580

26002581
printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
@@ -2612,12 +2593,11 @@ static int __init dquot_init(void)
26122593
if (!dquot_hash)
26132594
panic("Cannot create dquot hash table");
26142595

2615-
#ifdef CONFIG_SMP
2616-
dqstats_pcpu = alloc_percpu(struct dqstats);
2617-
if (!dqstats_pcpu)
2618-
panic("Cannot create dquot stats table");
2619-
#endif
2620-
memset(&dqstats, 0, sizeof(struct dqstats));
2596+
for (i = 0; i < _DQST_DQSTAT_LAST; i++) {
2597+
ret = percpu_counter_init(&dqstats.counter[i], 0);
2598+
if (ret)
2599+
panic("Cannot create dquot stat counters");
2600+
}
26212601

26222602
/* Find power-of-two hlist_heads which can fit into allocation */
26232603
nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head);

include/linux/quota.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ enum {
174174
#include <linux/rwsem.h>
175175
#include <linux/spinlock.h>
176176
#include <linux/wait.h>
177-
#include <linux/percpu.h>
178-
#include <linux/smp.h>
177+
#include <linux/percpu_counter.h>
179178

180179
#include <linux/dqblk_xfs.h>
181180
#include <linux/dqblk_v1.h>
@@ -254,27 +253,20 @@ enum {
254253

255254
struct dqstats {
256255
int stat[_DQST_DQSTAT_LAST];
256+
struct percpu_counter counter[_DQST_DQSTAT_LAST];
257257
};
258258

259259
extern struct dqstats *dqstats_pcpu;
260260
extern struct dqstats dqstats;
261261

262262
static inline void dqstats_inc(unsigned int type)
263263
{
264-
#ifdef CONFIG_SMP
265-
per_cpu_ptr(dqstats_pcpu, smp_processor_id())->stat[type]++;
266-
#else
267-
dqstats.stat[type]++;
268-
#endif
264+
percpu_counter_inc(&dqstats.counter[type]);
269265
}
270266

271267
static inline void dqstats_dec(unsigned int type)
272268
{
273-
#ifdef CONFIG_SMP
274-
per_cpu_ptr(dqstats_pcpu, smp_processor_id())->stat[type]--;
275-
#else
276-
dqstats.stat[type]--;
277-
#endif
269+
percpu_counter_dec(&dqstats.counter[type]);
278270
}
279271

280272
#define DQ_MOD_B 0 /* dquot modified since read */

0 commit comments

Comments
 (0)