From 4d81db4156caef7b223dde07e50db0144d12a192 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Fri, 12 Jun 2015 21:24:40 -0700 Subject: [PATCH] rocker: fix neigh tbl index increment race rocker->neigh_tbl_next_index is used to generate unique indices for neigh entries programmed into the device. The way new indices were generated was racy with the new prepare-commit transaction model. A simple fix here removes the race. The race was with two processes getting the same index, one process using prepare-commit, the other not: Proc A Proc B PREPARE phase get neigh_tbl_next_index NONE phase get neigh_tbl_next_index neigh_tbl_next_index++ COMMIT phase neigh_tbl_next_index++ Both A and B got the same index. The fix is to store and increment neigh_tbl_next_index in the PREPARE (or NONE) phase and use value in COMMIT phase: Proc A Proc B PREPARE phase get neigh_tbl_next_index neigh_tbl_next_index++ NONE phase get neigh_tbl_next_index neigh_tbl_next_index++ COMMIT phase // use value stashed in PREPARE phase Reported-by: Simon Horman Signed-off-by: Scott Feldman Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index c6a6e3c36d90..a9d15590743e 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -2901,10 +2901,10 @@ static void _rocker_neigh_add(struct rocker *rocker, enum switchdev_trans trans, struct rocker_neigh_tbl_entry *entry) { - entry->index = rocker->neigh_tbl_next_index; + if (trans != SWITCHDEV_TRANS_COMMIT) + entry->index = rocker->neigh_tbl_next_index++; if (trans == SWITCHDEV_TRANS_PREPARE) return; - rocker->neigh_tbl_next_index++; entry->ref_count++; hash_add(rocker->neigh_tbl, &entry->entry, be32_to_cpu(entry->ip_addr)); -- 2.20.1