diff options
Diffstat (limited to 'net/core/gen_stats.c')
-rw-r--r-- | net/core/gen_stats.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index 2ddbce4cce14..5ff8e80fe0bb 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c | |||
@@ -97,6 +97,43 @@ gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, | |||
97 | } | 97 | } |
98 | EXPORT_SYMBOL(gnet_stats_start_copy); | 98 | EXPORT_SYMBOL(gnet_stats_start_copy); |
99 | 99 | ||
100 | static void | ||
101 | __gnet_stats_copy_basic_cpu(struct gnet_stats_basic_packed *bstats, | ||
102 | struct gnet_stats_basic_cpu __percpu *cpu) | ||
103 | { | ||
104 | int i; | ||
105 | |||
106 | for_each_possible_cpu(i) { | ||
107 | struct gnet_stats_basic_cpu *bcpu = per_cpu_ptr(cpu, i); | ||
108 | unsigned int start; | ||
109 | __u64 bytes; | ||
110 | __u32 packets; | ||
111 | |||
112 | do { | ||
113 | start = u64_stats_fetch_begin_irq(&bcpu->syncp); | ||
114 | bytes = bcpu->bstats.bytes; | ||
115 | packets = bcpu->bstats.packets; | ||
116 | } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start)); | ||
117 | |||
118 | bstats->bytes += bcpu->bstats.bytes; | ||
119 | bstats->packets += bcpu->bstats.packets; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void | ||
124 | __gnet_stats_copy_basic(struct gnet_stats_basic_packed *bstats, | ||
125 | struct gnet_stats_basic_cpu __percpu *cpu, | ||
126 | struct gnet_stats_basic_packed *b) | ||
127 | { | ||
128 | if (cpu) { | ||
129 | __gnet_stats_copy_basic_cpu(bstats, cpu); | ||
130 | } else { | ||
131 | bstats->bytes = b->bytes; | ||
132 | bstats->packets = b->packets; | ||
133 | } | ||
134 | } | ||
135 | EXPORT_SYMBOL(__gnet_stats_copy_basic); | ||
136 | |||
100 | /** | 137 | /** |
101 | * gnet_stats_copy_basic - copy basic statistics into statistic TLV | 138 | * gnet_stats_copy_basic - copy basic statistics into statistic TLV |
102 | * @d: dumping handle | 139 | * @d: dumping handle |
@@ -109,19 +146,25 @@ EXPORT_SYMBOL(gnet_stats_start_copy); | |||
109 | * if the room in the socket buffer was not sufficient. | 146 | * if the room in the socket buffer was not sufficient. |
110 | */ | 147 | */ |
111 | int | 148 | int |
112 | gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_packed *b) | 149 | gnet_stats_copy_basic(struct gnet_dump *d, |
150 | struct gnet_stats_basic_cpu __percpu *cpu, | ||
151 | struct gnet_stats_basic_packed *b) | ||
113 | { | 152 | { |
153 | struct gnet_stats_basic_packed bstats = {0}; | ||
154 | |||
155 | __gnet_stats_copy_basic(&bstats, cpu, b); | ||
156 | |||
114 | if (d->compat_tc_stats) { | 157 | if (d->compat_tc_stats) { |
115 | d->tc_stats.bytes = b->bytes; | 158 | d->tc_stats.bytes = bstats.bytes; |
116 | d->tc_stats.packets = b->packets; | 159 | d->tc_stats.packets = bstats.packets; |
117 | } | 160 | } |
118 | 161 | ||
119 | if (d->tail) { | 162 | if (d->tail) { |
120 | struct gnet_stats_basic sb; | 163 | struct gnet_stats_basic sb; |
121 | 164 | ||
122 | memset(&sb, 0, sizeof(sb)); | 165 | memset(&sb, 0, sizeof(sb)); |
123 | sb.bytes = b->bytes; | 166 | sb.bytes = bstats.bytes; |
124 | sb.packets = b->packets; | 167 | sb.packets = bstats.packets; |
125 | return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb)); | 168 | return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb)); |
126 | } | 169 | } |
127 | return 0; | 170 | return 0; |