Make the dump operation aware of changes on radio list and corresponding inconsistent dumps. Changed variable name for better understanding. Signed-off-by: Benjamin Beichler <benjamin.beichler@xxxxxxxxxxxxxx> --- drivers/net/wireless/mac80211_hwsim.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 8baf61dea961..7cff948ef438 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -492,6 +492,7 @@ static spinlock_t hwsim_radio_lock; static LIST_HEAD(hwsim_radios); static struct rhashtable hwsim_radios_rht; static int hwsim_radio_idx; +static int hwsim_radios_generation = 1; static struct platform_driver mac80211_hwsim_driver = { .driver = { @@ -2808,6 +2809,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, } list_add_tail(&data->list, &hwsim_radios); + hwsim_radios_generation++; spin_unlock_bh(&hwsim_radio_lock); if (idx > 0) @@ -3273,6 +3275,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) list_del(&data->list); rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, hwsim_rht_params); + hwsim_radios_generation++; spin_unlock_bh(&hwsim_radio_lock); mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), info); @@ -3329,17 +3332,19 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) static int hwsim_dump_radio_nl(struct sk_buff *skb, struct netlink_callback *cb) { - int idx = cb->args[0]; + int last_idx = cb->args[0]; struct mac80211_hwsim_data *data = NULL; - int res; + int res = 0; + void *hdr; spin_lock_bh(&hwsim_radio_lock); + cb->seq = hwsim_radios_generation; - if (idx == hwsim_radio_idx) + if (last_idx >= hwsim_radio_idx-1) goto done; list_for_each_entry(data, &hwsim_radios, list) { - if (data->idx < idx) + if (data->idx <= last_idx) continue; if (!net_eq(wiphy_net(data->hw->wiphy), sock_net(skb->sk))) @@ -3352,14 +3357,25 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb, if (res < 0) break; - idx = data->idx + 1; + last_idx = data->idx; } - cb->args[0] = idx; + cb->args[0] = last_idx; + + /* list changed, but no new element sent, set interrupted flag */ + if (skb->len == 0 && cb->prev_seq && cb->seq != cb->prev_seq) { + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &hwsim_genl_family, + NLM_F_MULTI, HWSIM_CMD_GET_RADIO); + if (!hdr) + res = -EMSGSIZE; + genl_dump_check_consistent(cb, hdr); + genlmsg_end(skb, hdr); + } done: spin_unlock_bh(&hwsim_radio_lock); - return skb->len; + return (res)? res : skb->len; } /* Generic Netlink operations array */ @@ -3417,6 +3433,7 @@ static void destroy_radio(struct work_struct *work) struct mac80211_hwsim_data *data = container_of(work, struct mac80211_hwsim_data, destroy_work); + hwsim_radios_generation++; mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL); } -- 2.15.1