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