Skip to content

Commit ca19c70

Browse files
TaeheeYoodavem330
authored andcommitted
hsr: add restart routine into hsr_get_node_list()
The hsr_get_node_list() is to send node addresses to the userspace. If there are so many nodes, it could fail because of buffer size. In order to avoid this failure, the restart routine is added. Fixes: f421436 ("net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)") Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 173756b commit ca19c70

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

net/hsr/hsr_netlink.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,14 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
360360
*/
361361
static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
362362
{
363-
/* For receiving */
364-
struct nlattr *na;
363+
unsigned char addr[ETH_ALEN];
365364
struct net_device *hsr_dev;
366-
367-
/* For sending */
368365
struct sk_buff *skb_out;
369-
void *msg_head;
370366
struct hsr_priv *hsr;
371-
void *pos;
372-
unsigned char addr[ETH_ALEN];
367+
bool restart = false;
368+
struct nlattr *na;
369+
void *pos = NULL;
370+
void *msg_head;
373371
int res;
374372

375373
if (!info)
@@ -387,8 +385,9 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
387385
if (!is_hsr_master(hsr_dev))
388386
goto rcu_unlock;
389387

388+
restart:
390389
/* Send reply */
391-
skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
390+
skb_out = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
392391
if (!skb_out) {
393392
res = -ENOMEM;
394393
goto fail;
@@ -402,17 +401,28 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
402401
goto nla_put_failure;
403402
}
404403

405-
res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
406-
if (res < 0)
407-
goto nla_put_failure;
404+
if (!restart) {
405+
res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
406+
if (res < 0)
407+
goto nla_put_failure;
408+
}
408409

409410
hsr = netdev_priv(hsr_dev);
410411

411-
pos = hsr_get_next_node(hsr, NULL, addr);
412+
if (!pos)
413+
pos = hsr_get_next_node(hsr, NULL, addr);
412414
while (pos) {
413415
res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr);
414-
if (res < 0)
416+
if (res < 0) {
417+
if (res == -EMSGSIZE) {
418+
genlmsg_end(skb_out, msg_head);
419+
genlmsg_unicast(genl_info_net(info), skb_out,
420+
info->snd_portid);
421+
restart = true;
422+
goto restart;
423+
}
415424
goto nla_put_failure;
425+
}
416426
pos = hsr_get_next_node(hsr, pos, addr);
417427
}
418428
rcu_read_unlock();
@@ -429,7 +439,7 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
429439
return 0;
430440

431441
nla_put_failure:
432-
kfree_skb(skb_out);
442+
nlmsg_free(skb_out);
433443
/* Fall through */
434444

435445
fail:

0 commit comments

Comments
 (0)