net: sched: push ops lookup bits into tcf_proto_lookup_ops()

Push all bits that take care of ops lookup, including module loading
outside tcf_proto_create() function, into tcf_proto_lookup_ops()

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jiri Pirko 2018-07-23 09:23:04 +02:00 committed by David S. Miller
parent d3585edf87
commit f34e8bff58

View File

@ -39,7 +39,7 @@ static DEFINE_RWLOCK(cls_mod_lock);
/* Find classifier type by string name */ /* Find classifier type by string name */
static const struct tcf_proto_ops *tcf_proto_lookup_ops(const char *kind) static const struct tcf_proto_ops *__tcf_proto_lookup_ops(const char *kind)
{ {
const struct tcf_proto_ops *t, *res = NULL; const struct tcf_proto_ops *t, *res = NULL;
@ -57,6 +57,33 @@ static const struct tcf_proto_ops *tcf_proto_lookup_ops(const char *kind)
return res; return res;
} }
static const struct tcf_proto_ops *
tcf_proto_lookup_ops(const char *kind, struct netlink_ext_ack *extack)
{
const struct tcf_proto_ops *ops;
ops = __tcf_proto_lookup_ops(kind);
if (ops)
return ops;
#ifdef CONFIG_MODULES
rtnl_unlock();
request_module("cls_%s", kind);
rtnl_lock();
ops = __tcf_proto_lookup_ops(kind);
/* We dropped the RTNL semaphore in order to perform
* the module load. So, even if we succeeded in loading
* the module we have to replay the request. We indicate
* this using -EAGAIN.
*/
if (ops) {
module_put(ops->owner);
return ERR_PTR(-EAGAIN);
}
#endif
NL_SET_ERR_MSG(extack, "TC classifier not found");
return ERR_PTR(-ENOENT);
}
/* Register(unregister) new classifier type */ /* Register(unregister) new classifier type */
int register_tcf_proto_ops(struct tcf_proto_ops *ops) int register_tcf_proto_ops(struct tcf_proto_ops *ops)
@ -133,27 +160,9 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
if (!tp) if (!tp)
return ERR_PTR(-ENOBUFS); return ERR_PTR(-ENOBUFS);
err = -ENOENT; tp->ops = tcf_proto_lookup_ops(kind, extack);
tp->ops = tcf_proto_lookup_ops(kind); if (IS_ERR(tp->ops)) {
if (!tp->ops) { err = PTR_ERR(tp->ops);
#ifdef CONFIG_MODULES
rtnl_unlock();
request_module("cls_%s", kind);
rtnl_lock();
tp->ops = tcf_proto_lookup_ops(kind);
/* We dropped the RTNL semaphore in order to perform
* the module load. So, even if we succeeded in loading
* the module we have to replay the request. We indicate
* this using -EAGAIN.
*/
if (tp->ops) {
module_put(tp->ops->owner);
err = -EAGAIN;
} else {
NL_SET_ERR_MSG(extack, "TC classifier not found");
err = -ENOENT;
}
#endif
goto errout; goto errout;
} }
tp->classify = tp->ops->classify; tp->classify = tp->ops->classify;