On Wed, Oct 20, 2021 at 8:48 AM Steven Rostedt <rostedt@xxxxxxxxxxx> wrote: > > On Tue, 19 Oct 2021 18:31:40 -0700 > Kalesh Singh <kaleshsingh@xxxxxxxxxx> wrote: > > > @@ -2391,60 +2460,61 @@ static int check_expr_operands(struct trace_array *tr, > > static struct hist_field *parse_expr(struct hist_trigger_data *hist_data, > > struct trace_event_file *file, > > char *str, unsigned long flags, > > - char *var_name, unsigned int level) > > + char *var_name, unsigned int *n_subexprs) > > { > > struct hist_field *operand1 = NULL, *operand2 = NULL, *expr = NULL; > > unsigned long operand_flags; > > int field_op, ret = -EINVAL; > > char *sep, *operand1_str; > > > > - if (level > 3) { > > + if (*n_subexprs > 3) { > > Why limit the sub expressions, and not just keep the limit of the level of > recursion. We allow 3 levels of recursion, but we could have more than 3 > sub expressions. The main reason for this is that it's predictable behavior form the user's perspective. Before this patch the recursion always walked down a single branch so limiting by level worked out the same as limiting by sub expressions and is in line with the error the user would see ("Too many sub-expressions (3 max)"). Now that we take multiple paths in the recursion, using the level to reflect the number of sub-expressions would lead to only seeing the error in some of the cases (Sometimes we allow 4, 5, 6 sub-expressions depending on how balanced the tree is, and sometimes we error out on 4 - when the tree is list-like). Limiting by sub-expression keeps this consistent (always error out if we have more than 3 sub-expressions) and is in line with the previous behavior. - Kalesh > > > If we have: a * b + c / d - e * f / h > > It would break down into: > - > + / > * / * h > a b c d e f > > > Which I believe is 6 "sub expressions", but never goes more than three deep > in recursion: > > "a * b + c / d - e * f / h" > > Step 1: > > op = "-" > operand1 = "a * b + c / d" > operand2 = "e * f / h" > > Process operand1: (recursion level 1) > > op = "+" > operand1a = "a * b" > operand2a = "c / d" > > Process operand1a: (recursion level 2) > > op = "*" > operand1b = "a" > operand2b = "b" > > return; > > Process operand1b: (recursion level 2) > > op = "/" > operand1b = "c" > operand2b = "d" > > return; > > return; > > Process operand2: (recursion level 1) > > op = "/" > operand1c = "e * f" > operand2c = "h" > > Process operand1c: (recursion level 2) > > op = "*" > operand1c = "e" > operand2c = "f" > > return; > > return; > > > > > + > > + /* LHS of string is an expression e.g. a+b in a+b+c */ > > + operand1 = parse_expr(hist_data, file, operand1_str, operand_flags, NULL, n_subexprs); > > if (IS_ERR(operand1)) { > > ret = PTR_ERR(operand1); > > operand1 = NULL; > > I wonder if we should look for optimizations, in case of operand1 and > operand2 are both constants? > > Just perform the function, and convert it into a constant as well. > > -- Steve