mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 22:02:02 +00:00
genetlink: push conditional locking into dumpit/done
Add helpers which take/release the genl mutex based on family->parallel_ops. Remove the separation between handling of ops in locked and parallel families. Future patches would make the duplicated code grow even more. Reviewed-by: Johannes Berg <johannes@sipsolutions.net> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Link: https://lore.kernel.org/r/20230814214723.2924989-2-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
479b322ee6
commit
84817d8c60
1 changed files with 35 additions and 55 deletions
|
@ -52,6 +52,18 @@ static void genl_unlock_all(void)
|
||||||
up_write(&cb_lock);
|
up_write(&cb_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void genl_op_lock(const struct genl_family *family)
|
||||||
|
{
|
||||||
|
if (!family->parallel_ops)
|
||||||
|
genl_lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void genl_op_unlock(const struct genl_family *family)
|
||||||
|
{
|
||||||
|
if (!family->parallel_ops)
|
||||||
|
genl_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
static DEFINE_IDR(genl_fam_idr);
|
static DEFINE_IDR(genl_fam_idr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -838,11 +850,9 @@ static int genl_start(struct netlink_callback *cb)
|
||||||
|
|
||||||
cb->data = info;
|
cb->data = info;
|
||||||
if (ops->start) {
|
if (ops->start) {
|
||||||
if (!ctx->family->parallel_ops)
|
genl_op_lock(ctx->family);
|
||||||
genl_lock();
|
|
||||||
rc = ops->start(cb);
|
rc = ops->start(cb);
|
||||||
if (!ctx->family->parallel_ops)
|
genl_op_unlock(ctx->family);
|
||||||
genl_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -853,46 +863,34 @@ static int genl_start(struct netlink_callback *cb)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
static int genl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
||||||
{
|
{
|
||||||
const struct genl_split_ops *ops = &genl_dumpit_info(cb)->op;
|
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
|
||||||
|
const struct genl_split_ops *ops = &info->op;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
genl_lock();
|
genl_op_lock(info->family);
|
||||||
rc = ops->dumpit(skb, cb);
|
rc = ops->dumpit(skb, cb);
|
||||||
genl_unlock();
|
genl_op_unlock(info->family);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int genl_lock_done(struct netlink_callback *cb)
|
static int genl_done(struct netlink_callback *cb)
|
||||||
{
|
{
|
||||||
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
|
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
|
||||||
const struct genl_split_ops *ops = &info->op;
|
const struct genl_split_ops *ops = &info->op;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (ops->done) {
|
if (ops->done) {
|
||||||
genl_lock();
|
genl_op_lock(info->family);
|
||||||
rc = ops->done(cb);
|
rc = ops->done(cb);
|
||||||
genl_unlock();
|
genl_op_unlock(info->family);
|
||||||
}
|
}
|
||||||
genl_family_rcv_msg_attrs_free(info->attrs);
|
genl_family_rcv_msg_attrs_free(info->attrs);
|
||||||
genl_dumpit_info_free(info);
|
genl_dumpit_info_free(info);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int genl_parallel_done(struct netlink_callback *cb)
|
|
||||||
{
|
|
||||||
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
|
|
||||||
const struct genl_split_ops *ops = &info->op;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (ops->done)
|
|
||||||
rc = ops->done(cb);
|
|
||||||
genl_family_rcv_msg_attrs_free(info->attrs);
|
|
||||||
genl_dumpit_info_free(info);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
|
static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct nlmsghdr *nlh,
|
struct nlmsghdr *nlh,
|
||||||
|
@ -901,6 +899,14 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
|
||||||
int hdrlen, struct net *net)
|
int hdrlen, struct net *net)
|
||||||
{
|
{
|
||||||
struct genl_start_context ctx;
|
struct genl_start_context ctx;
|
||||||
|
struct netlink_dump_control c = {
|
||||||
|
.module = family->module,
|
||||||
|
.data = &ctx,
|
||||||
|
.start = genl_start,
|
||||||
|
.dump = genl_dumpit,
|
||||||
|
.done = genl_done,
|
||||||
|
.extack = extack,
|
||||||
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
ctx.family = family;
|
ctx.family = family;
|
||||||
|
@ -909,31 +915,9 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
|
||||||
ctx.ops = ops;
|
ctx.ops = ops;
|
||||||
ctx.hdrlen = hdrlen;
|
ctx.hdrlen = hdrlen;
|
||||||
|
|
||||||
if (!family->parallel_ops) {
|
genl_op_unlock(family);
|
||||||
struct netlink_dump_control c = {
|
err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
|
||||||
.module = family->module,
|
genl_op_lock(family);
|
||||||
.data = &ctx,
|
|
||||||
.start = genl_start,
|
|
||||||
.dump = genl_lock_dumpit,
|
|
||||||
.done = genl_lock_done,
|
|
||||||
.extack = extack,
|
|
||||||
};
|
|
||||||
|
|
||||||
genl_unlock();
|
|
||||||
err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
|
|
||||||
genl_lock();
|
|
||||||
} else {
|
|
||||||
struct netlink_dump_control c = {
|
|
||||||
.module = family->module,
|
|
||||||
.data = &ctx,
|
|
||||||
.start = genl_start,
|
|
||||||
.dump = ops->dumpit,
|
|
||||||
.done = genl_parallel_done,
|
|
||||||
.extack = extack,
|
|
||||||
};
|
|
||||||
|
|
||||||
err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1065,13 +1049,9 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
if (family == NULL)
|
if (family == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
if (!family->parallel_ops)
|
genl_op_lock(family);
|
||||||
genl_lock();
|
|
||||||
|
|
||||||
err = genl_family_rcv_msg(family, skb, nlh, extack);
|
err = genl_family_rcv_msg(family, skb, nlh, extack);
|
||||||
|
genl_op_unlock(family);
|
||||||
if (!family->parallel_ops)
|
|
||||||
genl_unlock();
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue