aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-08-23 15:45:04 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-28 17:19:17 -0400
commit33c6b1f6b154894321f5734e50c66621e9134e7e (patch)
treeb064251e8081c3dba7115b44ea6db15d240e1204
parent9b96309c5b0b9e466773c07a5bc8b7b68fcf010a (diff)
genl: Hold reference on correct module while netlink-dump.
netlink dump operations take module as parameter to hold reference for entire netlink dump duration. Currently it holds ref only on genl module which is not correct when we use ops registered to genl from another module. Following patch adds module pointer to genl_ops so that netlink can hold ref count on it. 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>
-rw-r--r--include/net/genetlink.h20
-rw-r--r--net/netlink/genetlink.c20
2 files changed, 29 insertions, 11 deletions
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 93024a47e0e2..8e0b6c856a13 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -61,6 +61,7 @@ struct genl_family {
61 struct list_head ops_list; /* private */ 61 struct list_head ops_list; /* private */
62 struct list_head family_list; /* private */ 62 struct list_head family_list; /* private */
63 struct list_head mcast_groups; /* private */ 63 struct list_head mcast_groups; /* private */
64 struct module *module;
64}; 65};
65 66
66/** 67/**
@@ -121,9 +122,24 @@ struct genl_ops {
121 struct list_head ops_list; 122 struct list_head ops_list;
122}; 123};
123 124
124extern int genl_register_family(struct genl_family *family); 125extern int __genl_register_family(struct genl_family *family);
125extern int genl_register_family_with_ops(struct genl_family *family, 126
127static inline int genl_register_family(struct genl_family *family)
128{
129 family->module = THIS_MODULE;
130 return __genl_register_family(family);
131}
132
133extern int __genl_register_family_with_ops(struct genl_family *family,
126 struct genl_ops *ops, size_t n_ops); 134 struct genl_ops *ops, size_t n_ops);
135
136static inline int genl_register_family_with_ops(struct genl_family *family,
137 struct genl_ops *ops, size_t n_ops)
138{
139 family->module = THIS_MODULE;
140 return __genl_register_family_with_ops(family, ops, n_ops);
141}
142
127extern int genl_unregister_family(struct genl_family *family); 143extern int genl_unregister_family(struct genl_family *family);
128extern int genl_register_ops(struct genl_family *, struct genl_ops *ops); 144extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
129extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops); 145extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 7e0f4d199ade..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)
364EXPORT_SYMBOL(genl_unregister_ops); 364EXPORT_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 */
377int genl_register_family(struct genl_family *family) 377int __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:
430errout: 430errout:
431 return err; 431 return err;
432} 432}
433EXPORT_SYMBOL(genl_register_family); 433EXPORT_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 */
460int genl_register_family_with_ops(struct genl_family *family, 460int __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}
479EXPORT_SYMBOL(genl_register_family_with_ops); 479EXPORT_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
@@ -603,22 +603,24 @@ static int genl_family_rcv_msg(struct genl_family *family,
603 603
604 if (!family->parallel_ops) { 604 if (!family->parallel_ops) {
605 struct netlink_dump_control c = { 605 struct netlink_dump_control c = {
606 .module = family->module,
606 .data = ops, 607 .data = ops,
607 .dump = genl_lock_dumpit, 608 .dump = genl_lock_dumpit,
608 .done = genl_lock_done, 609 .done = genl_lock_done,
609 }; 610 };
610 611
611 genl_unlock(); 612 genl_unlock();
612 rc = netlink_dump_start(net->genl_sock, skb, nlh, &c); 613 rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
613 genl_lock(); 614 genl_lock();
614 615
615 } else { 616 } else {
616 struct netlink_dump_control c = { 617 struct netlink_dump_control c = {
618 .module = family->module,
617 .dump = ops->dumpit, 619 .dump = ops->dumpit,
618 .done = ops->done, 620 .done = ops->done,
619 }; 621 };
620 622
621 rc = netlink_dump_start(net->genl_sock, skb, nlh, &c); 623 rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
622 } 624 }
623 625
624 return rc; 626 return rc;