@@ -458,10 +458,19 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
458
458
}
459
459
EXPORT_SYMBOL (genlmsg_put );
460
460
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
+
461
471
static int genl_lock_start (struct netlink_callback * cb )
462
472
{
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 ;
465
474
int rc = 0 ;
466
475
467
476
if (ops -> start ) {
@@ -474,8 +483,7 @@ static int genl_lock_start(struct netlink_callback *cb)
474
483
475
484
static int genl_lock_dumpit (struct sk_buff * skb , struct netlink_callback * cb )
476
485
{
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 ;
479
487
int rc ;
480
488
481
489
genl_lock ();
@@ -486,15 +494,28 @@ static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
486
494
487
495
static int genl_lock_done (struct netlink_callback * cb )
488
496
{
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 ;
491
499
int rc = 0 ;
492
500
493
501
if (ops -> done ) {
494
502
genl_lock ();
495
503
rc = ops -> done (cb );
496
504
genl_unlock ();
497
505
}
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 );
498
519
return rc ;
499
520
}
500
521
@@ -505,6 +526,7 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
505
526
const struct genl_ops * ops ,
506
527
int hdrlen , struct net * net )
507
528
{
529
+ struct genl_dumpit_info * info ;
508
530
int err ;
509
531
510
532
if (!ops -> dumpit )
@@ -528,11 +550,17 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
528
550
}
529
551
}
530
552
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
+
531
560
if (!family -> parallel_ops ) {
532
561
struct netlink_dump_control c = {
533
562
.module = family -> module ,
534
- /* we have const, but the netlink API doesn't */
535
- .data = (void * )ops ,
563
+ .data = info ,
536
564
.start = genl_lock_start ,
537
565
.dump = genl_lock_dumpit ,
538
566
.done = genl_lock_done ,
@@ -545,9 +573,10 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
545
573
} else {
546
574
struct netlink_dump_control c = {
547
575
.module = family -> module ,
576
+ .data = info ,
548
577
.start = ops -> start ,
549
578
.dump = ops -> dumpit ,
550
- .done = ops -> done ,
579
+ .done = genl_parallel_done ,
551
580
};
552
581
553
582
err = __netlink_dump_start (net -> genl_sock , skb , nlh , & c );
0 commit comments