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: Benjamin Beichler <benjamin.beichler@uni-rostock.de> [compress ternary operator] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
301b04040c
commit
6335698e24
@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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 @@ out_err:
|
|||||||
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,
|
|||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user