aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ipv6.h2
-rw-r--r--net/ipv6/proc.c26
2 files changed, 11 insertions, 17 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 1df360eb079..4408def379b 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -172,7 +172,7 @@ int snmp6_alloc_dev(struct inet6_dev *idev);
172int snmp6_free_dev(struct inet6_dev *idev); 172int snmp6_free_dev(struct inet6_dev *idev);
173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); 173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
174void snmp6_mib_free(void *ptr[2]); 174void snmp6_mib_free(void *ptr[2]);
175void snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes); 175void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes);
176 176
177struct ip6_ra_chain 177struct ip6_ra_chain
178{ 178{
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index aba94316b77..7a00bedb6b9 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -23,6 +23,7 @@
23#include <linux/proc_fs.h> 23#include <linux/proc_fs.h>
24#include <linux/seq_file.h> 24#include <linux/seq_file.h>
25#include <linux/stddef.h> 25#include <linux/stddef.h>
26#include <asm/unaligned.h>
26#include <net/sock.h> 27#include <net/sock.h>
27#include <net/tcp.h> 28#include <net/tcp.h>
28#include <net/transp_v6.h> 29#include <net/transp_v6.h>
@@ -210,30 +211,23 @@ static const struct file_operations snmp6_seq_fops = {
210}; 211};
211#endif /* CONFIG_PROC_FS */ 212#endif /* CONFIG_PROC_FS */
212 213
213/*
214 * Stats may not be aligned for u64, so use memcpy to avoid
215 * unaligned accesses.
216 */
217static inline void __set_u64(void *p, u64 v)
218{
219 memcpy(p, &v, sizeof(u64));
220}
221
222static inline void 214static inline void
223__snmp6_fill_stats(void *stats, void **mib, int items, int bytes) 215__snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes)
224{ 216{
225 int i; 217 int i;
226 u8 *p = stats;
227 int pad = bytes - sizeof(u64) * items; 218 int pad = bytes - sizeof(u64) * items;
228 BUG_ON(pad < 0); 219 BUG_ON(pad < 0);
229 __set_u64(p, items); 220
230 for (i = 1, p += sizeof(u64); i < items; i++, p += sizeof(u64)) 221 /* Use put_unaligned() because stats may not be aligned for u64. */
231 __set_u64(p, fold_field(mib, i)); 222 put_unaligned(items, &stats[0]);
232 memset(p, 0, pad); 223 for (i = 1; i < items; i++)
224 put_unaligned(fold_field(mib, i), &stats[i]);
225
226 memset(&stats[items], 0, pad);
233} 227}
234 228
235void 229void
236snmp6_fill_stats(void *stats, struct inet6_dev *idev, int attrtype, int bytes) 230snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes)
237{ 231{
238 switch(attrtype) { 232 switch(attrtype) {
239 case IFLA_INET6_STATS: 233 case IFLA_INET6_STATS: