Skip to content

Commit 1927f41

Browse files
jpirkodavem330
authored andcommitted
net: genetlink: introduce dump info struct to be available during dumpit op
Currently the cb->data is taken by ops during non-parallel dumping. Introduce a new structure genl_dumpit_info and store the ops there. Distribute the info to both non-parallel and parallel dumping. Also add a helper genl_dumpit_info() to easily get the info structure in the dumpit callback from cb. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent be064de commit 1927f41

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

include/net/genetlink.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,20 @@ enum genl_validate_flags {
127127
GENL_DONT_VALIDATE_DUMP_STRICT = BIT(2),
128128
};
129129

130+
/**
131+
* struct genl_info - info that is available during dumpit op call
132+
* @ops: generic netlink ops - for internal genl code usage
133+
*/
134+
struct genl_dumpit_info {
135+
const struct genl_ops *ops;
136+
};
137+
138+
static inline const struct genl_dumpit_info *
139+
genl_dumpit_info(struct netlink_callback *cb)
140+
{
141+
return cb->data;
142+
}
143+
130144
/**
131145
* struct genl_ops - generic netlink operations
132146
* @cmd: command identifier

net/netlink/genetlink.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,10 +458,19 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
458458
}
459459
EXPORT_SYMBOL(genlmsg_put);
460460

461+
static struct genl_dumpit_info *genl_dumpit_info_alloc(void)
462+
{
463+
return kmalloc(sizeof(struct genl_dumpit_info), GFP_KERNEL);
464+
}
465+
466+
static void genl_dumpit_info_free(const struct genl_dumpit_info *info)
467+
{
468+
kfree(info);
469+
}
470+
461471
static int genl_lock_start(struct netlink_callback *cb)
462472
{
463-
/* our ops are always const - netlink API doesn't propagate that */
464-
const struct genl_ops *ops = cb->data;
473+
const struct genl_ops *ops = genl_dumpit_info(cb)->ops;
465474
int rc = 0;
466475

467476
if (ops->start) {
@@ -474,8 +483,7 @@ static int genl_lock_start(struct netlink_callback *cb)
474483

475484
static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
476485
{
477-
/* our ops are always const - netlink API doesn't propagate that */
478-
const struct genl_ops *ops = cb->data;
486+
const struct genl_ops *ops = genl_dumpit_info(cb)->ops;
479487
int rc;
480488

481489
genl_lock();
@@ -486,15 +494,28 @@ static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
486494

487495
static int genl_lock_done(struct netlink_callback *cb)
488496
{
489-
/* our ops are always const - netlink API doesn't propagate that */
490-
const struct genl_ops *ops = cb->data;
497+
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
498+
const struct genl_ops *ops = info->ops;
491499
int rc = 0;
492500

493501
if (ops->done) {
494502
genl_lock();
495503
rc = ops->done(cb);
496504
genl_unlock();
497505
}
506+
genl_dumpit_info_free(info);
507+
return rc;
508+
}
509+
510+
static int genl_parallel_done(struct netlink_callback *cb)
511+
{
512+
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
513+
const struct genl_ops *ops = info->ops;
514+
int rc = 0;
515+
516+
if (ops->done)
517+
rc = ops->done(cb);
518+
genl_dumpit_info_free(info);
498519
return rc;
499520
}
500521

@@ -505,6 +526,7 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
505526
const struct genl_ops *ops,
506527
int hdrlen, struct net *net)
507528
{
529+
struct genl_dumpit_info *info;
508530
int err;
509531

510532
if (!ops->dumpit)
@@ -528,11 +550,17 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
528550
}
529551
}
530552

553+
/* Allocate dumpit info. It is going to be freed by done() callback. */
554+
info = genl_dumpit_info_alloc();
555+
if (!info)
556+
return -ENOMEM;
557+
558+
info->ops = ops;
559+
531560
if (!family->parallel_ops) {
532561
struct netlink_dump_control c = {
533562
.module = family->module,
534-
/* we have const, but the netlink API doesn't */
535-
.data = (void *)ops,
563+
.data = info,
536564
.start = genl_lock_start,
537565
.dump = genl_lock_dumpit,
538566
.done = genl_lock_done,
@@ -545,9 +573,10 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
545573
} else {
546574
struct netlink_dump_control c = {
547575
.module = family->module,
576+
.data = info,
548577
.start = ops->start,
549578
.dump = ops->dumpit,
550-
.done = ops->done,
579+
.done = genl_parallel_done,
551580
};
552581

553582
err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);

0 commit comments

Comments
 (0)