diff options
| -rw-r--r-- | kernel/trace/trace_events_hist.c | 93 |
1 files changed, 75 insertions, 18 deletions
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index f3caf6e484f4..6309f4dbfb9c 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c | |||
| @@ -1292,6 +1292,17 @@ static u64 hist_field_cpu(struct hist_field *hist_field, | |||
| 1292 | return cpu; | 1292 | return cpu; |
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | /** | ||
| 1296 | * check_field_for_var_ref - Check if a VAR_REF field references a variable | ||
| 1297 | * @hist_field: The VAR_REF field to check | ||
| 1298 | * @var_data: The hist trigger that owns the variable | ||
| 1299 | * @var_idx: The trigger variable identifier | ||
| 1300 | * | ||
| 1301 | * Check the given VAR_REF field to see whether or not it references | ||
| 1302 | * the given variable associated with the given trigger. | ||
| 1303 | * | ||
| 1304 | * Return: The VAR_REF field if it does reference the variable, NULL if not | ||
| 1305 | */ | ||
| 1295 | static struct hist_field * | 1306 | static struct hist_field * |
| 1296 | check_field_for_var_ref(struct hist_field *hist_field, | 1307 | check_field_for_var_ref(struct hist_field *hist_field, |
| 1297 | struct hist_trigger_data *var_data, | 1308 | struct hist_trigger_data *var_data, |
| @@ -1306,6 +1317,18 @@ check_field_for_var_ref(struct hist_field *hist_field, | |||
| 1306 | return NULL; | 1317 | return NULL; |
| 1307 | } | 1318 | } |
| 1308 | 1319 | ||
| 1320 | /** | ||
| 1321 | * find_var_ref - Check if a trigger has a reference to a trigger variable | ||
| 1322 | * @hist_data: The hist trigger that might have a reference to the variable | ||
| 1323 | * @var_data: The hist trigger that owns the variable | ||
| 1324 | * @var_idx: The trigger variable identifier | ||
| 1325 | * | ||
| 1326 | * Check the list of var_refs[] on the first hist trigger to see | ||
| 1327 | * whether any of them are references to the variable on the second | ||
| 1328 | * trigger. | ||
| 1329 | * | ||
| 1330 | * Return: The VAR_REF field referencing the variable if so, NULL if not | ||
| 1331 | */ | ||
| 1309 | static struct hist_field *find_var_ref(struct hist_trigger_data *hist_data, | 1332 | static struct hist_field *find_var_ref(struct hist_trigger_data *hist_data, |
| 1310 | struct hist_trigger_data *var_data, | 1333 | struct hist_trigger_data *var_data, |
| 1311 | unsigned int var_idx) | 1334 | unsigned int var_idx) |
| @@ -1322,6 +1345,20 @@ static struct hist_field *find_var_ref(struct hist_trigger_data *hist_data, | |||
| 1322 | return NULL; | 1345 | return NULL; |
| 1323 | } | 1346 | } |
| 1324 | 1347 | ||
| 1348 | /** | ||
| 1349 | * find_any_var_ref - Check if there is a reference to a given trigger variable | ||
| 1350 | * @hist_data: The hist trigger | ||
| 1351 | * @var_idx: The trigger variable identifier | ||
| 1352 | * | ||
| 1353 | * Check to see whether the given variable is currently referenced by | ||
| 1354 | * any other trigger. | ||
| 1355 | * | ||
| 1356 | * The trigger the variable is defined on is explicitly excluded - the | ||
| 1357 | * assumption being that a self-reference doesn't prevent a trigger | ||
| 1358 | * from being removed. | ||
| 1359 | * | ||
| 1360 | * Return: The VAR_REF field referencing the variable if so, NULL if not | ||
| 1361 | */ | ||
| 1325 | static struct hist_field *find_any_var_ref(struct hist_trigger_data *hist_data, | 1362 | static struct hist_field *find_any_var_ref(struct hist_trigger_data *hist_data, |
| 1326 | unsigned int var_idx) | 1363 | unsigned int var_idx) |
| 1327 | { | 1364 | { |
| @@ -1340,6 +1377,19 @@ static struct hist_field *find_any_var_ref(struct hist_trigger_data *hist_data, | |||
| 1340 | return found; | 1377 | return found; |
| 1341 | } | 1378 | } |
| 1342 | 1379 | ||
| 1380 | /** | ||
| 1381 | * check_var_refs - Check if there is a reference to any of trigger's variables | ||
| 1382 | * @hist_data: The hist trigger | ||
| 1383 | * | ||
| 1384 | * A trigger can define one or more variables. If any one of them is | ||
| 1385 | * currently referenced by any other trigger, this function will | ||
| 1386 | * determine that. | ||
| 1387 | |||
| 1388 | * Typically used to determine whether or not a trigger can be removed | ||
| 1389 | * - if there are any references to a trigger's variables, it cannot. | ||
| 1390 | * | ||
| 1391 | * Return: True if there is a reference to any of trigger's variables | ||
| 1392 | */ | ||
| 1343 | static bool check_var_refs(struct hist_trigger_data *hist_data) | 1393 | static bool check_var_refs(struct hist_trigger_data *hist_data) |
| 1344 | { | 1394 | { |
| 1345 | struct hist_field *field; | 1395 | struct hist_field *field; |
| @@ -2343,7 +2393,23 @@ static int init_var_ref(struct hist_field *ref_field, | |||
| 2343 | goto out; | 2393 | goto out; |
| 2344 | } | 2394 | } |
| 2345 | 2395 | ||
| 2346 | static struct hist_field *create_var_ref(struct hist_field *var_field, | 2396 | /** |
| 2397 | * create_var_ref - Create a variable reference and attach it to trigger | ||
| 2398 | * @hist_data: The trigger that will be referencing the variable | ||
| 2399 | * @var_field: The VAR field to create a reference to | ||
| 2400 | * @system: The optional system string | ||
| 2401 | * @event_name: The optional event_name string | ||
| 2402 | * | ||
| 2403 | * Given a variable hist_field, create a VAR_REF hist_field that | ||
| 2404 | * represents a reference to it. | ||
| 2405 | * | ||
| 2406 | * This function also adds the reference to the trigger that | ||
| 2407 | * now references the variable. | ||
| 2408 | * | ||
| 2409 | * Return: The VAR_REF field if successful, NULL if not | ||
| 2410 | */ | ||
| 2411 | static struct hist_field *create_var_ref(struct hist_trigger_data *hist_data, | ||
| 2412 | struct hist_field *var_field, | ||
| 2347 | char *system, char *event_name) | 2413 | char *system, char *event_name) |
| 2348 | { | 2414 | { |
| 2349 | unsigned long flags = HIST_FIELD_FL_VAR_REF; | 2415 | unsigned long flags = HIST_FIELD_FL_VAR_REF; |
| @@ -2355,6 +2421,9 @@ static struct hist_field *create_var_ref(struct hist_field *var_field, | |||
| 2355 | destroy_hist_field(ref_field, 0); | 2421 | destroy_hist_field(ref_field, 0); |
| 2356 | return NULL; | 2422 | return NULL; |
| 2357 | } | 2423 | } |
| 2424 | |||
| 2425 | hist_data->var_refs[hist_data->n_var_refs] = ref_field; | ||
| 2426 | ref_field->var_ref_idx = hist_data->n_var_refs++; | ||
| 2358 | } | 2427 | } |
| 2359 | 2428 | ||
| 2360 | return ref_field; | 2429 | return ref_field; |
| @@ -2428,7 +2497,8 @@ static struct hist_field *parse_var_ref(struct hist_trigger_data *hist_data, | |||
| 2428 | 2497 | ||
| 2429 | var_field = find_event_var(hist_data, system, event_name, var_name); | 2498 | var_field = find_event_var(hist_data, system, event_name, var_name); |
| 2430 | if (var_field) | 2499 | if (var_field) |
| 2431 | ref_field = create_var_ref(var_field, system, event_name); | 2500 | ref_field = create_var_ref(hist_data, var_field, |
| 2501 | system, event_name); | ||
| 2432 | 2502 | ||
| 2433 | if (!ref_field) | 2503 | if (!ref_field) |
| 2434 | hist_err_event("Couldn't find variable: $", | 2504 | hist_err_event("Couldn't find variable: $", |
| @@ -2546,8 +2616,6 @@ static struct hist_field *parse_atom(struct hist_trigger_data *hist_data, | |||
| 2546 | if (!s) { | 2616 | if (!s) { |
| 2547 | hist_field = parse_var_ref(hist_data, ref_system, ref_event, ref_var); | 2617 | hist_field = parse_var_ref(hist_data, ref_system, ref_event, ref_var); |
| 2548 | if (hist_field) { | 2618 | if (hist_field) { |
| 2549 | hist_data->var_refs[hist_data->n_var_refs] = hist_field; | ||
| 2550 | hist_field->var_ref_idx = hist_data->n_var_refs++; | ||
| 2551 | if (var_name) { | 2619 | if (var_name) { |
| 2552 | hist_field = create_alias(hist_data, hist_field, var_name); | 2620 | hist_field = create_alias(hist_data, hist_field, var_name); |
| 2553 | if (!hist_field) { | 2621 | if (!hist_field) { |
| @@ -3321,7 +3389,6 @@ static int onmax_create(struct hist_trigger_data *hist_data, | |||
| 3321 | unsigned int var_ref_idx = hist_data->n_var_refs; | 3389 | unsigned int var_ref_idx = hist_data->n_var_refs; |
| 3322 | struct field_var *field_var; | 3390 | struct field_var *field_var; |
| 3323 | char *onmax_var_str, *param; | 3391 | char *onmax_var_str, *param; |
| 3324 | unsigned long flags; | ||
| 3325 | unsigned int i; | 3392 | unsigned int i; |
| 3326 | int ret = 0; | 3393 | int ret = 0; |
| 3327 | 3394 | ||
| @@ -3338,18 +3405,10 @@ static int onmax_create(struct hist_trigger_data *hist_data, | |||
| 3338 | return -EINVAL; | 3405 | return -EINVAL; |
| 3339 | } | 3406 | } |
| 3340 | 3407 | ||
| 3341 | flags = HIST_FIELD_FL_VAR_REF; | 3408 | ref_field = create_var_ref(hist_data, var_field, NULL, NULL); |
| 3342 | ref_field = create_hist_field(hist_data, NULL, flags, NULL); | ||
| 3343 | if (!ref_field) | 3409 | if (!ref_field) |
| 3344 | return -ENOMEM; | 3410 | return -ENOMEM; |
| 3345 | 3411 | ||
| 3346 | if (init_var_ref(ref_field, var_field, NULL, NULL)) { | ||
| 3347 | destroy_hist_field(ref_field, 0); | ||
| 3348 | ret = -ENOMEM; | ||
| 3349 | goto out; | ||
| 3350 | } | ||
| 3351 | hist_data->var_refs[hist_data->n_var_refs] = ref_field; | ||
| 3352 | ref_field->var_ref_idx = hist_data->n_var_refs++; | ||
| 3353 | data->onmax.var = ref_field; | 3412 | data->onmax.var = ref_field; |
| 3354 | 3413 | ||
| 3355 | data->fn = onmax_save; | 3414 | data->fn = onmax_save; |
| @@ -3538,9 +3597,6 @@ static void save_synth_var_ref(struct hist_trigger_data *hist_data, | |||
| 3538 | struct hist_field *var_ref) | 3597 | struct hist_field *var_ref) |
| 3539 | { | 3598 | { |
| 3540 | hist_data->synth_var_refs[hist_data->n_synth_var_refs++] = var_ref; | 3599 | hist_data->synth_var_refs[hist_data->n_synth_var_refs++] = var_ref; |
| 3541 | |||
| 3542 | hist_data->var_refs[hist_data->n_var_refs] = var_ref; | ||
| 3543 | var_ref->var_ref_idx = hist_data->n_var_refs++; | ||
| 3544 | } | 3600 | } |
| 3545 | 3601 | ||
| 3546 | static int check_synth_field(struct synth_event *event, | 3602 | static int check_synth_field(struct synth_event *event, |
| @@ -3694,7 +3750,8 @@ static int onmatch_create(struct hist_trigger_data *hist_data, | |||
| 3694 | } | 3750 | } |
| 3695 | 3751 | ||
| 3696 | if (check_synth_field(event, hist_field, field_pos) == 0) { | 3752 | if (check_synth_field(event, hist_field, field_pos) == 0) { |
| 3697 | var_ref = create_var_ref(hist_field, system, event_name); | 3753 | var_ref = create_var_ref(hist_data, hist_field, |
| 3754 | system, event_name); | ||
| 3698 | if (!var_ref) { | 3755 | if (!var_ref) { |
| 3699 | kfree(p); | 3756 | kfree(p); |
| 3700 | ret = -ENOMEM; | 3757 | ret = -ENOMEM; |
