Commit e8ced39d5e8911c662d4d69a342b9d053eaaac4e
Committed by
Theodore Ts'o
1 parent
64769240bd
Exists in
master
and in
20 other branches
percpu_counter: new function percpu_counter_sum_and_set
Delayed allocation need to check free blocks at every write time. percpu_counter_read_positive() is not quit accurate. delayed allocation need a more accurate accounting, but using percpu_counter_sum_positive() is frequently is quite expensive. This patch added a new function to update center counter when sum per-cpu counter, to increase the accurate rate for next percpu_counter_read() and require less calling expensive percpu_counter_sum(). Signed-off-by: Mingming Cao <cmm@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Showing 3 changed files with 16 additions and 5 deletions Side-by-side Diff
fs/ext4/balloc.c
... | ... | @@ -1621,7 +1621,7 @@ |
1621 | 1621 | #ifdef CONFIG_SMP |
1622 | 1622 | if (free_blocks - root_blocks < FBC_BATCH) |
1623 | 1623 | free_blocks = |
1624 | - percpu_counter_sum_positive(&sbi->s_freeblocks_counter); | |
1624 | + percpu_counter_sum_and_set(&sbi->s_freeblocks_counter); | |
1625 | 1625 | #endif |
1626 | 1626 | if (free_blocks - root_blocks < nblocks) |
1627 | 1627 | return free_blocks - root_blocks; |
include/linux/percpu_counter.h
... | ... | @@ -35,7 +35,7 @@ |
35 | 35 | void percpu_counter_destroy(struct percpu_counter *fbc); |
36 | 36 | void percpu_counter_set(struct percpu_counter *fbc, s64 amount); |
37 | 37 | void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch); |
38 | -s64 __percpu_counter_sum(struct percpu_counter *fbc); | |
38 | +s64 __percpu_counter_sum(struct percpu_counter *fbc, int set); | |
39 | 39 | |
40 | 40 | static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount) |
41 | 41 | { |
42 | 42 | |
43 | 43 | |
... | ... | @@ -44,13 +44,19 @@ |
44 | 44 | |
45 | 45 | static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc) |
46 | 46 | { |
47 | - s64 ret = __percpu_counter_sum(fbc); | |
47 | + s64 ret = __percpu_counter_sum(fbc, 0); | |
48 | 48 | return ret < 0 ? 0 : ret; |
49 | 49 | } |
50 | 50 | |
51 | +static inline s64 percpu_counter_sum_and_set(struct percpu_counter *fbc) | |
52 | +{ | |
53 | + return __percpu_counter_sum(fbc, 1); | |
54 | +} | |
55 | + | |
56 | + | |
51 | 57 | static inline s64 percpu_counter_sum(struct percpu_counter *fbc) |
52 | 58 | { |
53 | - return __percpu_counter_sum(fbc); | |
59 | + return __percpu_counter_sum(fbc, 0); | |
54 | 60 | } |
55 | 61 | |
56 | 62 | static inline s64 percpu_counter_read(struct percpu_counter *fbc) |
lib/percpu_counter.c
... | ... | @@ -52,7 +52,7 @@ |
52 | 52 | * Add up all the per-cpu counts, return the result. This is a more accurate |
53 | 53 | * but much slower version of percpu_counter_read_positive() |
54 | 54 | */ |
55 | -s64 __percpu_counter_sum(struct percpu_counter *fbc) | |
55 | +s64 __percpu_counter_sum(struct percpu_counter *fbc, int set) | |
56 | 56 | { |
57 | 57 | s64 ret; |
58 | 58 | int cpu; |
59 | 59 | |
... | ... | @@ -62,7 +62,12 @@ |
62 | 62 | for_each_online_cpu(cpu) { |
63 | 63 | s32 *pcount = per_cpu_ptr(fbc->counters, cpu); |
64 | 64 | ret += *pcount; |
65 | + if (set) | |
66 | + *pcount = 0; | |
65 | 67 | } |
68 | + if (set) | |
69 | + fbc->count = ret; | |
70 | + | |
66 | 71 | spin_unlock(&fbc->lock); |
67 | 72 | return ret; |
68 | 73 | } |