union devlink_param_value grows when U64 array params are added to devlink. This increase the size of union devlink_param_value from 32 bytes to over 264 bytes. devlink_nl_param_value_fill_one(), devlink_nl_param_value_put() take multiple copies of this union by value. Passing two of these unions by value consumes over 528 bytes of stack space, and combined in a call chain this pushes nearly 800 bytes of arguments onto the stack. There is higher chance of hitting CONFIG_FRAME_WARN limits deep in deep functions. Change signatures of the internal functions and exported APIs be updated to pass the unions by pointer instead. Signed-off-by: Ratheesh Kannoth --- net/devlink/param.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/devlink/param.c b/net/devlink/param.c index cf95268da5b0..4595fffbd825 100644 --- a/net/devlink/param.c +++ b/net/devlink/param.c @@ -216,39 +216,39 @@ static int devlink_param_reset_default(struct devlink *devlink, static int devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type, - int nla_type, union devlink_param_value val, + int nla_type, union devlink_param_value *val, bool flag_as_u8) { switch (type) { case DEVLINK_PARAM_TYPE_U8: - if (nla_put_u8(msg, nla_type, val.vu8)) + if (nla_put_u8(msg, nla_type, val->vu8)) return -EMSGSIZE; break; case DEVLINK_PARAM_TYPE_U16: - if (nla_put_u16(msg, nla_type, val.vu16)) + if (nla_put_u16(msg, nla_type, val->vu16)) return -EMSGSIZE; break; case DEVLINK_PARAM_TYPE_U32: - if (nla_put_u32(msg, nla_type, val.vu32)) + if (nla_put_u32(msg, nla_type, val->vu32)) return -EMSGSIZE; break; case DEVLINK_PARAM_TYPE_U64: - if (devlink_nl_put_u64(msg, nla_type, val.vu64)) + if (devlink_nl_put_u64(msg, nla_type, val->vu64)) return -EMSGSIZE; break; case DEVLINK_PARAM_TYPE_STRING: - if (nla_put_string(msg, nla_type, val.vstr)) + if (nla_put_string(msg, nla_type, val->vstr)) return -EMSGSIZE; break; case DEVLINK_PARAM_TYPE_BOOL: - /* default values of type bool are encoded with u8, so that + /* default val->es of type bool are encoded with u8, so that * false can be distinguished from not present */ if (flag_as_u8) { - if (nla_put_u8(msg, nla_type, val.vbool)) + if (nla_put_u8(msg, nla_type, val->vbool)) return -EMSGSIZE; } else { - if (val.vbool && nla_put_flag(msg, nla_type)) + if (val->vbool && nla_put_flag(msg, nla_type)) return -EMSGSIZE; } break; @@ -260,8 +260,8 @@ static int devlink_nl_param_value_fill_one(struct sk_buff *msg, enum devlink_param_type type, enum devlink_param_cmode cmode, - union devlink_param_value val, - union devlink_param_value default_val, + union devlink_param_value *val, + union devlink_param_value *default_val, bool has_default) { struct nlattr *param_value_attr; @@ -383,8 +383,8 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, if (!param_value_set[i]) continue; err = devlink_nl_param_value_fill_one(msg, param->type, - i, param_value[i], - default_value[i], + i, ¶m_value[i], + &default_value[i], default_value_set[i]); if (err) goto values_list_nest_cancel; -- 2.43.0