Skip to content

Commit 784ee61

Browse files
committed
Merge branch 'netlink-emsgsize'
Jakub Kicinski says: ==================== netlink: handle EMSGSIZE errors in the core Ido discovered some time back that we usually force NLMSG_DONE to be delivered in a separate recv() syscall, even if it would fit into the same skb as data messages. He made nexthop try to fit DONE with data in commit 8743aef ("nexthop: Fix infinite nexthop bucket dump when using maximum nexthop ID"), and nobody has complained so far. We have since also tried to follow the same pattern in new genetlink families, but explaining to people, or even remembering the correct handling ourselves is tedious. Let the netlink socket layer consume -EMSGSIZE errors. Practically speaking most families use this error code as "dump needs more space", anyway. v2: - init err to 0 in last patch v1: https://lore.kernel.org/all/20240301012845.2951053-1-kuba@kernel.org/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents e3350ba + 87d3819 commit 784ee61

File tree

4 files changed

+19
-19
lines changed

4 files changed

+19
-19
lines changed

net/core/netdev-genl.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,7 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
152152
}
153153
rtnl_unlock();
154154

155-
if (err != -EMSGSIZE)
156-
return err;
157-
158-
return skb->len;
155+
return err;
159156
}
160157

161158
static int
@@ -287,10 +284,7 @@ int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
287284
}
288285
rtnl_unlock();
289286

290-
if (err != -EMSGSIZE)
291-
return err;
292-
293-
return skb->len;
287+
return err;
294288
}
295289

296290
static int
@@ -463,10 +457,7 @@ int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
463457
}
464458
rtnl_unlock();
465459

466-
if (err != -EMSGSIZE)
467-
return err;
468-
469-
return skb->len;
460+
return err;
470461
}
471462

472463
static int netdev_genl_netdevice_event(struct notifier_block *nb,

net/core/page_pool_user.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
102102
mutex_unlock(&page_pools_lock);
103103
rtnl_unlock();
104104

105-
if (skb->len && err == -EMSGSIZE)
106-
return skb->len;
107105
return err;
108106
}
109107

net/netlink/af_netlink.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,6 +2267,15 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
22672267
if (extra_mutex)
22682268
mutex_unlock(extra_mutex);
22692269

2270+
/* EMSGSIZE plus something already in the skb means
2271+
* that there's more to dump but current skb has filled up.
2272+
* If the callback really wants to return EMSGSIZE to user space
2273+
* it needs to do so again, on the next cb->dump() call,
2274+
* without putting data in the skb.
2275+
*/
2276+
if (nlk->dump_done_errno == -EMSGSIZE && skb->len)
2277+
nlk->dump_done_errno = skb->len;
2278+
22702279
cb->extack = NULL;
22712280
}
22722281

net/netlink/genetlink.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq,
12321232

12331233
hdr = genlmsg_put(skb, portid, seq, &genl_ctrl, flags, cmd);
12341234
if (hdr == NULL)
1235-
return -1;
1235+
return -EMSGSIZE;
12361236

12371237
if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) ||
12381238
nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id) ||
@@ -1355,6 +1355,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
13551355
struct net *net = sock_net(skb->sk);
13561356
int fams_to_skip = cb->args[0];
13571357
unsigned int id;
1358+
int err = 0;
13581359

13591360
idr_for_each_entry(&genl_fam_idr, rt, id) {
13601361
if (!rt->netnsok && !net_eq(net, &init_net))
@@ -1363,16 +1364,17 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
13631364
if (n++ < fams_to_skip)
13641365
continue;
13651366

1366-
if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
1367-
cb->nlh->nlmsg_seq, NLM_F_MULTI,
1368-
skb, CTRL_CMD_NEWFAMILY) < 0) {
1367+
err = ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
1368+
cb->nlh->nlmsg_seq, NLM_F_MULTI,
1369+
skb, CTRL_CMD_NEWFAMILY);
1370+
if (err) {
13691371
n--;
13701372
break;
13711373
}
13721374
}
13731375

13741376
cb->args[0] = n;
1375-
return skb->len;
1377+
return err;
13761378
}
13771379

13781380
static struct sk_buff *ctrl_build_family_msg(const struct genl_family *family,

0 commit comments

Comments
 (0)