summaryrefslogtreecommitdiff
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-09-30 11:54:46 +0300
committerIngo Molnar <mingo@kernel.org>2016-09-30 11:54:46 +0300
commit0b429e18c284af3e7a39f8ec44d95116c473fef8 (patch)
tree7957f57dc70c95a32f71896c9a526ca88b5517ad /net/ipv4/route.c
parentd32cdbfb0ba319e44f75437afde868f7cafdc467 (diff)
parent53061afee43bc5041b67a45b6d793e7afdcf9ca7 (diff)
downloadlinux-0b429e18c284af3e7a39f8ec44d95116c473fef8.tar.xz
Merge branch 'linus' into locking/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a1f2830d8110..b5b47a26d4ec 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -476,12 +476,18 @@ u32 ip_idents_reserve(u32 hash, int segs)
atomic_t *p_id = ip_idents + hash % IP_IDENTS_SZ;
u32 old = ACCESS_ONCE(*p_tstamp);
u32 now = (u32)jiffies;
- u32 delta = 0;
+ u32 new, delta = 0;
if (old != now && cmpxchg(p_tstamp, old, now) == old)
delta = prandom_u32_max(now - old);
- return atomic_add_return(segs + delta, p_id) - segs;
+ /* Do not use atomic_add_return() as it makes UBSAN unhappy */
+ do {
+ old = (u32)atomic_read(p_id);
+ new = old + delta + segs;
+ } while (atomic_cmpxchg(p_id, old, new) != old);
+
+ return new - segs;
}
EXPORT_SYMBOL(ip_idents_reserve);