aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-08-23 15:44:55 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-28 17:19:17 -0400
commit9b96309c5b0b9e466773c07a5bc8b7b68fcf010a (patch)
treeb41719289b4aaaf7a176f1d94924e2d1e8528cfe /net/netlink/genetlink.c
parenta3097bda78c7fb41fd3091ffb70bf7bd946e6997 (diff)
genl: Fix genl dumpit() locking.
In case of genl-family with parallel ops off, dumpif() callback is expected to run under genl_lock, But commit def3117493eafd9df (genl: Allow concurrent genl callbacks.) changed this behaviour where only first dumpit() op was called under genl-lock. For subsequent dump, only nlk->cb_lock was taken. Following patch fixes it by defining locked dumpit() and done() callback which takes care of genl-locking. CC: Jesse Gross <jesse@nicira.com> CC: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 512718adb0d5..7e0f4d199ade 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -544,6 +544,30 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
544} 544}
545EXPORT_SYMBOL(genlmsg_put); 545EXPORT_SYMBOL(genlmsg_put);
546 546
547static 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
558static 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
547static int genl_family_rcv_msg(struct genl_family *family, 571static 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,32 @@ 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 .data = ops,
607 .dump = genl_lock_dumpit,
608 .done = genl_lock_done,
609 };
610
611 genl_unlock();
612 rc = netlink_dump_start(net->genl_sock, skb, nlh, &c);
613 genl_lock();
614
615 } else {
616 struct netlink_dump_control c = {
617 .dump = ops->dumpit,
618 .done = ops->done,
619 };
620
621 rc = netlink_dump_start(net->genl_sock, skb, nlh, &c);
622 }
623
624 return rc;
584 } 625 }
585 626
586 if (ops->doit == NULL) 627 if (ops->doit == NULL)