Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tracing: Dynamically allocate the per-elt hist_elt_data array

Setting the hist_elt_data.field_var_str[] array unconditionally to a
size of SYNTH_FIELD_MAX elements wastes space unnecessarily. The
actual number of elements needed can be calculated at run-time
instead.

In most cases, this will save a lot of space since it's a per-elt
array which isn't normally close to being full. It also allows us to
increase SYNTH_FIELD_MAX without worrying about even more wastage when
we do that.

Link: https://lkml.kernel.org/r/d52ae0ad5e1b59af7c4f54faf3fc098461fd82b3.camel@kernel.org

Signed-off-by: Tom Zanussi <zanussi@kernel.org>
Tested-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Tom Zanussi and committed by
Steven Rostedt (VMware)
c910db94 0be083ce

+12 -2
+12 -2
kernel/trace/trace_events_hist.c
··· 508 508 struct hist_elt_data { 509 509 char *comm; 510 510 u64 *var_ref_vals; 511 - char *field_var_str[SYNTH_FIELDS_MAX]; 511 + char **field_var_str; 512 + int n_field_var_str; 512 513 }; 513 514 514 515 struct snapshot_context { ··· 1402 1401 { 1403 1402 unsigned int i; 1404 1403 1405 - for (i = 0; i < SYNTH_FIELDS_MAX; i++) 1404 + for (i = 0; i < elt_data->n_field_var_str; i++) 1406 1405 kfree(elt_data->field_var_str[i]); 1406 + 1407 + kfree(elt_data->field_var_str); 1407 1408 1408 1409 kfree(elt_data->comm); 1409 1410 kfree(elt_data); ··· 1453 1450 BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1)); 1454 1451 1455 1452 size = STR_VAR_LEN_MAX; 1453 + 1454 + elt_data->field_var_str = kcalloc(n_str, sizeof(char *), GFP_KERNEL); 1455 + if (!elt_data->field_var_str) { 1456 + hist_elt_data_free(elt_data); 1457 + return -EINVAL; 1458 + } 1459 + elt_data->n_field_var_str = n_str; 1456 1460 1457 1461 for (i = 0; i < n_str; i++) { 1458 1462 elt_data->field_var_str[i] = kzalloc(size, GFP_KERNEL);