diff options
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r-- | net/netlink/genetlink.c | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 512718adb0d5..0c741cec4d0d 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -364,7 +364,7 @@ int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops) | |||
364 | EXPORT_SYMBOL(genl_unregister_ops); | 364 | EXPORT_SYMBOL(genl_unregister_ops); |
365 | 365 | ||
366 | /** | 366 | /** |
367 | * genl_register_family - register a generic netlink family | 367 | * __genl_register_family - register a generic netlink family |
368 | * @family: generic netlink family | 368 | * @family: generic netlink family |
369 | * | 369 | * |
370 | * Registers the specified family after validating it first. Only one | 370 | * Registers the specified family after validating it first. Only one |
@@ -374,7 +374,7 @@ EXPORT_SYMBOL(genl_unregister_ops); | |||
374 | * | 374 | * |
375 | * Return 0 on success or a negative error code. | 375 | * Return 0 on success or a negative error code. |
376 | */ | 376 | */ |
377 | int genl_register_family(struct genl_family *family) | 377 | int __genl_register_family(struct genl_family *family) |
378 | { | 378 | { |
379 | int err = -EINVAL; | 379 | int err = -EINVAL; |
380 | 380 | ||
@@ -430,10 +430,10 @@ errout_locked: | |||
430 | errout: | 430 | errout: |
431 | return err; | 431 | return err; |
432 | } | 432 | } |
433 | EXPORT_SYMBOL(genl_register_family); | 433 | EXPORT_SYMBOL(__genl_register_family); |
434 | 434 | ||
435 | /** | 435 | /** |
436 | * genl_register_family_with_ops - register a generic netlink family | 436 | * __genl_register_family_with_ops - register a generic netlink family |
437 | * @family: generic netlink family | 437 | * @family: generic netlink family |
438 | * @ops: operations to be registered | 438 | * @ops: operations to be registered |
439 | * @n_ops: number of elements to register | 439 | * @n_ops: number of elements to register |
@@ -457,12 +457,12 @@ EXPORT_SYMBOL(genl_register_family); | |||
457 | * | 457 | * |
458 | * Return 0 on success or a negative error code. | 458 | * Return 0 on success or a negative error code. |
459 | */ | 459 | */ |
460 | int genl_register_family_with_ops(struct genl_family *family, | 460 | int __genl_register_family_with_ops(struct genl_family *family, |
461 | struct genl_ops *ops, size_t n_ops) | 461 | struct genl_ops *ops, size_t n_ops) |
462 | { | 462 | { |
463 | int err, i; | 463 | int err, i; |
464 | 464 | ||
465 | err = genl_register_family(family); | 465 | err = __genl_register_family(family); |
466 | if (err) | 466 | if (err) |
467 | return err; | 467 | return err; |
468 | 468 | ||
@@ -476,7 +476,7 @@ err_out: | |||
476 | genl_unregister_family(family); | 476 | genl_unregister_family(family); |
477 | return err; | 477 | return err; |
478 | } | 478 | } |
479 | EXPORT_SYMBOL(genl_register_family_with_ops); | 479 | EXPORT_SYMBOL(__genl_register_family_with_ops); |
480 | 480 | ||
481 | /** | 481 | /** |
482 | * genl_unregister_family - unregister generic netlink family | 482 | * genl_unregister_family - unregister generic netlink family |
@@ -544,6 +544,30 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, | |||
544 | } | 544 | } |
545 | EXPORT_SYMBOL(genlmsg_put); | 545 | EXPORT_SYMBOL(genlmsg_put); |
546 | 546 | ||
547 | static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | ||
548 | { | ||
549 | struct genl_ops *ops = cb->data; | ||
550 | int rc; | ||
551 | |||
552 | genl_lock(); | ||
553 | rc = ops->dumpit(skb, cb); | ||
554 | genl_unlock(); | ||
555 | return rc; | ||
556 | } | ||
557 | |||
558 | static int genl_lock_done(struct netlink_callback *cb) | ||
559 | { | ||
560 | struct genl_ops *ops = cb->data; | ||
561 | int rc = 0; | ||
562 | |||
563 | if (ops->done) { | ||
564 | genl_lock(); | ||
565 | rc = ops->done(cb); | ||
566 | genl_unlock(); | ||
567 | } | ||
568 | return rc; | ||
569 | } | ||
570 | |||
547 | static int genl_family_rcv_msg(struct genl_family *family, | 571 | static int genl_family_rcv_msg(struct genl_family *family, |
548 | struct sk_buff *skb, | 572 | struct sk_buff *skb, |
549 | struct nlmsghdr *nlh) | 573 | struct nlmsghdr *nlh) |
@@ -572,15 +596,34 @@ static int genl_family_rcv_msg(struct genl_family *family, | |||
572 | return -EPERM; | 596 | return -EPERM; |
573 | 597 | ||
574 | if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) { | 598 | if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) { |
575 | struct netlink_dump_control c = { | 599 | int rc; |
576 | .dump = ops->dumpit, | ||
577 | .done = ops->done, | ||
578 | }; | ||
579 | 600 | ||
580 | if (ops->dumpit == NULL) | 601 | if (ops->dumpit == NULL) |
581 | return -EOPNOTSUPP; | 602 | return -EOPNOTSUPP; |
582 | 603 | ||
583 | return netlink_dump_start(net->genl_sock, skb, nlh, &c); | 604 | if (!family->parallel_ops) { |
605 | struct netlink_dump_control c = { | ||
606 | .module = family->module, | ||
607 | .data = ops, | ||
608 | .dump = genl_lock_dumpit, | ||
609 | .done = genl_lock_done, | ||
610 | }; | ||
611 | |||
612 | genl_unlock(); | ||
613 | rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c); | ||
614 | genl_lock(); | ||
615 | |||
616 | } else { | ||
617 | struct netlink_dump_control c = { | ||
618 | .module = family->module, | ||
619 | .dump = ops->dumpit, | ||
620 | .done = ops->done, | ||
621 | }; | ||
622 | |||
623 | rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c); | ||
624 | } | ||
625 | |||
626 | return rc; | ||
584 | } | 627 | } |
585 | 628 | ||
586 | if (ops->doit == NULL) | 629 | if (ops->doit == NULL) |