Commit 8a7cd77d authored by David S. Miller's avatar David S. Miller

[PKT_SCHED]: Proper module refcounting for packet classifiers.

parent 9a16a6f2
...@@ -39,6 +39,8 @@ struct tcf_walker ...@@ -39,6 +39,8 @@ struct tcf_walker
int (*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *); int (*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *);
}; };
struct module;
struct tcf_proto_ops struct tcf_proto_ops
{ {
struct tcf_proto_ops *next; struct tcf_proto_ops *next;
...@@ -56,6 +58,8 @@ struct tcf_proto_ops ...@@ -56,6 +58,8 @@ struct tcf_proto_ops
/* rtnetlink specific */ /* rtnetlink specific */
int (*dump)(struct tcf_proto*, unsigned long, struct sk_buff *skb, struct tcmsg*); int (*dump)(struct tcf_proto*, unsigned long, struct sk_buff *skb, struct tcmsg*);
struct module *owner;
}; };
/* Main classifier routine: scans classifier chain attached /* Main classifier routine: scans classifier chain attached
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -223,8 +224,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -223,8 +224,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
tp->q = q; tp->q = q;
tp->classify = tp_ops->classify; tp->classify = tp_ops->classify;
tp->classid = parent; tp->classid = parent;
err = tp_ops->init(tp); err = -EBUSY;
if (err) { if (!try_module_get(tp_ops->owner) ||
(err = tp_ops->init(tp)) != 0) {
kfree(tp); kfree(tp);
goto errout; goto errout;
} }
...@@ -248,6 +250,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -248,6 +250,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
write_unlock(&qdisc_tree_lock); write_unlock(&qdisc_tree_lock);
tp->ops->destroy(tp); tp->ops->destroy(tp);
module_put(tp->ops->owner);
kfree(tp); kfree(tp);
err = 0; err = 0;
goto errout; goto errout;
......
...@@ -117,7 +117,6 @@ static void fw_put(struct tcf_proto *tp, unsigned long f) ...@@ -117,7 +117,6 @@ static void fw_put(struct tcf_proto *tp, unsigned long f)
static int fw_init(struct tcf_proto *tp) static int fw_init(struct tcf_proto *tp)
{ {
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -127,10 +126,8 @@ static void fw_destroy(struct tcf_proto *tp) ...@@ -127,10 +126,8 @@ static void fw_destroy(struct tcf_proto *tp)
struct fw_filter *f; struct fw_filter *f;
int h; int h;
if (head == NULL) { if (head == NULL)
MOD_DEC_USE_COUNT;
return; return;
}
for (h=0; h<256; h++) { for (h=0; h<256; h++) {
while ((f=head->ht[h]) != NULL) { while ((f=head->ht[h]) != NULL) {
...@@ -146,7 +143,6 @@ static void fw_destroy(struct tcf_proto *tp) ...@@ -146,7 +143,6 @@ static void fw_destroy(struct tcf_proto *tp)
} }
} }
kfree(head); kfree(head);
MOD_DEC_USE_COUNT;
} }
static int fw_delete(struct tcf_proto *tp, unsigned long arg) static int fw_delete(struct tcf_proto *tp, unsigned long arg)
...@@ -351,18 +347,18 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -351,18 +347,18 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
} }
struct tcf_proto_ops cls_fw_ops = { struct tcf_proto_ops cls_fw_ops = {
NULL, .next = NULL,
"fw", .kind = "fw",
fw_classify, .classify = fw_classify,
fw_init, .init = fw_init,
fw_destroy, .destroy = fw_destroy,
.get = fw_get,
fw_get, .put = fw_put,
fw_put, .change = fw_change,
fw_change, .delete = fw_delete,
fw_delete, .walk = fw_walk,
fw_walk, .dump = fw_dump,
fw_dump .owner = THIS_MODULE,
}; };
#ifdef MODULE #ifdef MODULE
......
...@@ -272,7 +272,6 @@ static void route4_put(struct tcf_proto *tp, unsigned long f) ...@@ -272,7 +272,6 @@ static void route4_put(struct tcf_proto *tp, unsigned long f)
static int route4_init(struct tcf_proto *tp) static int route4_init(struct tcf_proto *tp)
{ {
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -281,10 +280,8 @@ static void route4_destroy(struct tcf_proto *tp) ...@@ -281,10 +280,8 @@ static void route4_destroy(struct tcf_proto *tp)
struct route4_head *head = xchg(&tp->root, NULL); struct route4_head *head = xchg(&tp->root, NULL);
int h1, h2; int h1, h2;
if (head == NULL) { if (head == NULL)
MOD_DEC_USE_COUNT;
return; return;
}
for (h1=0; h1<=256; h1++) { for (h1=0; h1<=256; h1++) {
struct route4_bucket *b; struct route4_bucket *b;
...@@ -309,7 +306,6 @@ static void route4_destroy(struct tcf_proto *tp) ...@@ -309,7 +306,6 @@ static void route4_destroy(struct tcf_proto *tp)
} }
} }
kfree(head); kfree(head);
MOD_DEC_USE_COUNT;
} }
static int route4_delete(struct tcf_proto *tp, unsigned long arg) static int route4_delete(struct tcf_proto *tp, unsigned long arg)
...@@ -607,18 +603,18 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -607,18 +603,18 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
} }
struct tcf_proto_ops cls_route4_ops = { struct tcf_proto_ops cls_route4_ops = {
NULL, .next = NULL,
"route", .kind = "route",
route4_classify, .classify = route4_classify,
route4_init, .init = route4_init,
route4_destroy, .destroy = route4_destroy,
.get = route4_get,
route4_get, .put = route4_put,
route4_put, .change = route4_change,
route4_change, .delete = route4_delete,
route4_delete, .walk = route4_walk,
route4_walk, .dump = route4_dump,
route4_dump .owner = THIS_MODULE,
}; };
#ifdef MODULE #ifdef MODULE
......
...@@ -242,14 +242,12 @@ static int rsvp_init(struct tcf_proto *tp) ...@@ -242,14 +242,12 @@ static int rsvp_init(struct tcf_proto *tp)
{ {
struct rsvp_head *data; struct rsvp_head *data;
MOD_INC_USE_COUNT;
data = kmalloc(sizeof(struct rsvp_head), GFP_KERNEL); data = kmalloc(sizeof(struct rsvp_head), GFP_KERNEL);
if (data) { if (data) {
memset(data, 0, sizeof(struct rsvp_head)); memset(data, 0, sizeof(struct rsvp_head));
tp->root = data; tp->root = data;
return 0; return 0;
} }
MOD_DEC_USE_COUNT;
return -ENOBUFS; return -ENOBUFS;
} }
...@@ -289,7 +287,6 @@ static void rsvp_destroy(struct tcf_proto *tp) ...@@ -289,7 +287,6 @@ static void rsvp_destroy(struct tcf_proto *tp)
} }
} }
kfree(data); kfree(data);
MOD_DEC_USE_COUNT;
} }
static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
...@@ -668,18 +665,18 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -668,18 +665,18 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
} }
struct tcf_proto_ops RSVP_OPS = { struct tcf_proto_ops RSVP_OPS = {
NULL, .next = NULL,
RSVP_ID, .kind = RSVP_ID,
rsvp_classify, .classify = rsvp_classify,
rsvp_init, .init = rsvp_init,
rsvp_destroy, .destroy = rsvp_destroy,
.get = rsvp_get,
rsvp_get, .put = rsvp_put,
rsvp_put, .change = rsvp_change,
rsvp_change, .delete = rsvp_delete,
rsvp_delete, .walk = rsvp_walk,
rsvp_walk, .dump = rsvp_dump,
rsvp_dump .owner = THIS_MODULE,
}; };
#ifdef MODULE #ifdef MODULE
......
...@@ -144,12 +144,10 @@ static int tcindex_init(struct tcf_proto *tp) ...@@ -144,12 +144,10 @@ static int tcindex_init(struct tcf_proto *tp)
struct tcindex_data *p; struct tcindex_data *p;
DPRINTK("tcindex_init(tp %p)\n",tp); DPRINTK("tcindex_init(tp %p)\n",tp);
MOD_INC_USE_COUNT;
p = kmalloc(sizeof(struct tcindex_data),GFP_KERNEL); p = kmalloc(sizeof(struct tcindex_data),GFP_KERNEL);
if (!p) { if (!p)
MOD_DEC_USE_COUNT;
return -ENOMEM; return -ENOMEM;
}
tp->root = p; tp->root = p;
p->perfect = NULL; p->perfect = NULL;
p->h = NULL; p->h = NULL;
...@@ -417,7 +415,6 @@ static void tcindex_destroy(struct tcf_proto *tp) ...@@ -417,7 +415,6 @@ static void tcindex_destroy(struct tcf_proto *tp)
kfree(p->h); kfree(p->h);
kfree(p); kfree(p);
tp->root = NULL; tp->root = NULL;
MOD_DEC_USE_COUNT;
} }
...@@ -480,18 +477,18 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -480,18 +477,18 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
} }
struct tcf_proto_ops cls_tcindex_ops = { struct tcf_proto_ops cls_tcindex_ops = {
NULL, .next = NULL,
"tcindex", .kind = "tcindex",
tcindex_classify, .classify = tcindex_classify,
tcindex_init, .init = tcindex_init,
tcindex_destroy, .destroy = tcindex_destroy,
.get = tcindex_get,
tcindex_get, .put = tcindex_put,
tcindex_put, .change = tcindex_change,
tcindex_change, .delete = tcindex_delete,
tcindex_delete, .walk = tcindex_walk,
tcindex_walk, .dump = tcindex_dump,
tcindex_dump .owner = THIS_MODULE,
}; };
......
...@@ -257,17 +257,14 @@ static int u32_init(struct tcf_proto *tp) ...@@ -257,17 +257,14 @@ static int u32_init(struct tcf_proto *tp)
struct tc_u_hnode *root_ht; struct tc_u_hnode *root_ht;
struct tc_u_common *tp_c; struct tc_u_common *tp_c;
MOD_INC_USE_COUNT;
for (tp_c = u32_list; tp_c; tp_c = tp_c->next) for (tp_c = u32_list; tp_c; tp_c = tp_c->next)
if (tp_c->q == tp->q) if (tp_c->q == tp->q)
break; break;
root_ht = kmalloc(sizeof(*root_ht), GFP_KERNEL); root_ht = kmalloc(sizeof(*root_ht), GFP_KERNEL);
if (root_ht == NULL) { if (root_ht == NULL)
MOD_DEC_USE_COUNT;
return -ENOBUFS; return -ENOBUFS;
}
memset(root_ht, 0, sizeof(*root_ht)); memset(root_ht, 0, sizeof(*root_ht));
root_ht->divisor = 0; root_ht->divisor = 0;
root_ht->refcnt++; root_ht->refcnt++;
...@@ -277,7 +274,6 @@ static int u32_init(struct tcf_proto *tp) ...@@ -277,7 +274,6 @@ static int u32_init(struct tcf_proto *tp)
tp_c = kmalloc(sizeof(*tp_c), GFP_KERNEL); tp_c = kmalloc(sizeof(*tp_c), GFP_KERNEL);
if (tp_c == NULL) { if (tp_c == NULL) {
kfree(root_ht); kfree(root_ht);
MOD_DEC_USE_COUNT;
return -ENOBUFS; return -ENOBUFS;
} }
memset(tp_c, 0, sizeof(*tp_c)); memset(tp_c, 0, sizeof(*tp_c));
...@@ -402,7 +398,6 @@ static void u32_destroy(struct tcf_proto *tp) ...@@ -402,7 +398,6 @@ static void u32_destroy(struct tcf_proto *tp)
kfree(tp_c); kfree(tp_c);
} }
MOD_DEC_USE_COUNT;
tp->data = NULL; tp->data = NULL;
} }
...@@ -690,18 +685,18 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -690,18 +685,18 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
} }
struct tcf_proto_ops cls_u32_ops = { struct tcf_proto_ops cls_u32_ops = {
NULL, .next = NULL,
"u32", .kind = "u32",
u32_classify, .classify = u32_classify,
u32_init, .init = u32_init,
u32_destroy, .destroy = u32_destroy,
.get = u32_get,
u32_get, .put = u32_put,
u32_put, .change = u32_change,
u32_change, .delete = u32_delete,
u32_delete, .walk = u32_walk,
u32_walk, .dump = u32_dump,
u32_dump .owner = THIS_MODULE,
}; };
#ifdef MODULE #ifdef MODULE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment