Commit 6335698e authored by Benjamin Beichler's avatar Benjamin Beichler Committed by Johannes Berg

mac80211_hwsim: add generation count for netlink dump operation

Make the dump operation aware of changes on radio list and corresponding
inconsistent dumps. Changed variable name for better understanding.
Signed-off-by: default avatarBenjamin Beichler <benjamin.beichler@uni-rostock.de>
[compress ternary operator]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 301b0404
...@@ -493,6 +493,7 @@ static LIST_HEAD(hwsim_radios); ...@@ -493,6 +493,7 @@ static LIST_HEAD(hwsim_radios);
static struct workqueue_struct *hwsim_wq; static struct workqueue_struct *hwsim_wq;
static struct rhashtable hwsim_radios_rht; static struct rhashtable hwsim_radios_rht;
static int hwsim_radio_idx; static int hwsim_radio_idx;
static int hwsim_radios_generation = 1;
static struct platform_driver mac80211_hwsim_driver = { static struct platform_driver mac80211_hwsim_driver = {
.driver = { .driver = {
...@@ -2807,6 +2808,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -2807,6 +2808,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
} }
list_add_tail(&data->list, &hwsim_radios); list_add_tail(&data->list, &hwsim_radios);
hwsim_radios_generation++;
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
if (idx > 0) if (idx > 0)
...@@ -3277,6 +3279,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -3277,6 +3279,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
list_del(&data->list); list_del(&data->list);
rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, rhashtable_remove_fast(&hwsim_radios_rht, &data->rht,
hwsim_rht_params); hwsim_rht_params);
hwsim_radios_generation++;
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
info); info);
...@@ -3333,17 +3336,19 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -3333,17 +3336,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, static int hwsim_dump_radio_nl(struct sk_buff *skb,
struct netlink_callback *cb) struct netlink_callback *cb)
{ {
int idx = cb->args[0]; int last_idx = cb->args[0];
struct mac80211_hwsim_data *data = NULL; struct mac80211_hwsim_data *data = NULL;
int res; int res = 0;
void *hdr;
spin_lock_bh(&hwsim_radio_lock); 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; goto done;
list_for_each_entry(data, &hwsim_radios, list) { list_for_each_entry(data, &hwsim_radios, list) {
if (data->idx < idx) if (data->idx <= last_idx)
continue; continue;
if (!net_eq(wiphy_net(data->hw->wiphy), sock_net(skb->sk))) if (!net_eq(wiphy_net(data->hw->wiphy), sock_net(skb->sk)))
...@@ -3356,14 +3361,25 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb, ...@@ -3356,14 +3361,25 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
if (res < 0) if (res < 0)
break; 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: done:
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
return skb->len; return res ?: skb->len;
} }
/* Generic Netlink operations array */ /* Generic Netlink operations array */
...@@ -3421,6 +3437,7 @@ static void destroy_radio(struct work_struct *work) ...@@ -3421,6 +3437,7 @@ static void destroy_radio(struct work_struct *work)
struct mac80211_hwsim_data *data = struct mac80211_hwsim_data *data =
container_of(work, struct mac80211_hwsim_data, destroy_work); container_of(work, struct mac80211_hwsim_data, destroy_work);
hwsim_radios_generation++;
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL); mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment