aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_events_hist.c11
-rw-r--r--kernel/trace/tracing_map.c83
-rw-r--r--kernel/trace/tracing_map.h7
3 files changed, 6 insertions, 95 deletions
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 1e1558c99d56..712260e72be5 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -340,16 +340,6 @@ static int hist_trigger_elt_comm_alloc(struct tracing_map_elt *elt)
340 return 0; 340 return 0;
341} 341}
342 342
343static void hist_trigger_elt_comm_copy(struct tracing_map_elt *to,
344 struct tracing_map_elt *from)
345{
346 char *comm_from = from->private_data;
347 char *comm_to = to->private_data;
348
349 if (comm_from)
350 memcpy(comm_to, comm_from, TASK_COMM_LEN + 1);
351}
352
353static void hist_trigger_elt_comm_init(struct tracing_map_elt *elt) 343static void hist_trigger_elt_comm_init(struct tracing_map_elt *elt)
354{ 344{
355 char *comm = elt->private_data; 345 char *comm = elt->private_data;
@@ -360,7 +350,6 @@ static void hist_trigger_elt_comm_init(struct tracing_map_elt *elt)
360 350
361static const struct tracing_map_ops hist_trigger_elt_comm_ops = { 351static const struct tracing_map_ops hist_trigger_elt_comm_ops = {
362 .elt_alloc = hist_trigger_elt_comm_alloc, 352 .elt_alloc = hist_trigger_elt_comm_alloc,
363 .elt_copy = hist_trigger_elt_comm_copy,
364 .elt_free = hist_trigger_elt_comm_free, 353 .elt_free = hist_trigger_elt_comm_free,
365 .elt_init = hist_trigger_elt_comm_init, 354 .elt_init = hist_trigger_elt_comm_init,
366}; 355};
diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c
index b30f3439f27f..f47a4d54bcf0 100644
--- a/kernel/trace/tracing_map.c
+++ b/kernel/trace/tracing_map.c
@@ -847,67 +847,15 @@ create_sort_entry(void *key, struct tracing_map_elt *elt)
847 return sort_entry; 847 return sort_entry;
848} 848}
849 849
850static struct tracing_map_elt *copy_elt(struct tracing_map_elt *elt) 850static void detect_dups(struct tracing_map_sort_entry **sort_entries,
851{
852 struct tracing_map_elt *dup_elt;
853 unsigned int i;
854
855 dup_elt = tracing_map_elt_alloc(elt->map);
856 if (IS_ERR(dup_elt))
857 return NULL;
858
859 if (elt->map->ops && elt->map->ops->elt_copy)
860 elt->map->ops->elt_copy(dup_elt, elt);
861
862 dup_elt->private_data = elt->private_data;
863 memcpy(dup_elt->key, elt->key, elt->map->key_size);
864
865 for (i = 0; i < elt->map->n_fields; i++) {
866 atomic64_set(&dup_elt->fields[i].sum,
867 atomic64_read(&elt->fields[i].sum));
868 dup_elt->fields[i].cmp_fn = elt->fields[i].cmp_fn;
869 }
870
871 return dup_elt;
872}
873
874static int merge_dup(struct tracing_map_sort_entry **sort_entries,
875 unsigned int target, unsigned int dup)
876{
877 struct tracing_map_elt *target_elt, *elt;
878 bool first_dup = (target - dup) == 1;
879 int i;
880
881 if (first_dup) {
882 elt = sort_entries[target]->elt;
883 target_elt = copy_elt(elt);
884 if (!target_elt)
885 return -ENOMEM;
886 sort_entries[target]->elt = target_elt;
887 sort_entries[target]->elt_copied = true;
888 } else
889 target_elt = sort_entries[target]->elt;
890
891 elt = sort_entries[dup]->elt;
892
893 for (i = 0; i < elt->map->n_fields; i++)
894 atomic64_add(atomic64_read(&elt->fields[i].sum),
895 &target_elt->fields[i].sum);
896
897 sort_entries[dup]->dup = true;
898
899 return 0;
900}
901
902static int merge_dups(struct tracing_map_sort_entry **sort_entries,
903 int n_entries, unsigned int key_size) 851 int n_entries, unsigned int key_size)
904{ 852{
905 unsigned int dups = 0, total_dups = 0; 853 unsigned int dups = 0, total_dups = 0;
906 int err, i, j; 854 int i;
907 void *key; 855 void *key;
908 856
909 if (n_entries < 2) 857 if (n_entries < 2)
910 return total_dups; 858 return;
911 859
912 sort(sort_entries, n_entries, sizeof(struct tracing_map_sort_entry *), 860 sort(sort_entries, n_entries, sizeof(struct tracing_map_sort_entry *),
913 (int (*)(const void *, const void *))cmp_entries_dup, NULL); 861 (int (*)(const void *, const void *))cmp_entries_dup, NULL);
@@ -916,30 +864,14 @@ static int merge_dups(struct tracing_map_sort_entry **sort_entries,
916 for (i = 1; i < n_entries; i++) { 864 for (i = 1; i < n_entries; i++) {
917 if (!memcmp(sort_entries[i]->key, key, key_size)) { 865 if (!memcmp(sort_entries[i]->key, key, key_size)) {
918 dups++; total_dups++; 866 dups++; total_dups++;
919 err = merge_dup(sort_entries, i - dups, i);
920 if (err)
921 return err;
922 continue; 867 continue;
923 } 868 }
924 key = sort_entries[i]->key; 869 key = sort_entries[i]->key;
925 dups = 0; 870 dups = 0;
926 } 871 }
927 872
928 if (!total_dups) 873 WARN_ONCE(total_dups > 0,
929 return total_dups; 874 "Duplicates detected: %d\n", total_dups);
930
931 for (i = 0, j = 0; i < n_entries; i++) {
932 if (!sort_entries[i]->dup) {
933 sort_entries[j] = sort_entries[i];
934 if (j++ != i)
935 sort_entries[i] = NULL;
936 } else {
937 destroy_sort_entry(sort_entries[i]);
938 sort_entries[i] = NULL;
939 }
940 }
941
942 return total_dups;
943} 875}
944 876
945static bool is_key(struct tracing_map *map, unsigned int field_idx) 877static bool is_key(struct tracing_map *map, unsigned int field_idx)
@@ -1065,10 +997,7 @@ int tracing_map_sort_entries(struct tracing_map *map,
1065 return 1; 997 return 1;
1066 } 998 }
1067 999
1068 ret = merge_dups(entries, n_entries, map->key_size); 1000 detect_dups(entries, n_entries, map->key_size);
1069 if (ret < 0)
1070 goto free;
1071 n_entries -= ret;
1072 1001
1073 if (is_key(map, sort_keys[0].field_idx)) 1002 if (is_key(map, sort_keys[0].field_idx))
1074 cmp_entries_fn = cmp_entries_key; 1003 cmp_entries_fn = cmp_entries_key;
diff --git a/kernel/trace/tracing_map.h b/kernel/trace/tracing_map.h
index 5b5bbf8ae550..de57887c0670 100644
--- a/kernel/trace/tracing_map.h
+++ b/kernel/trace/tracing_map.h
@@ -215,11 +215,6 @@ struct tracing_map {
215 * Element allocation occurs before tracing begins, when the 215 * Element allocation occurs before tracing begins, when the
216 * tracing_map_init() call is made by client code. 216 * tracing_map_init() call is made by client code.
217 * 217 *
218 * @elt_copy: At certain points in the lifetime of an element, it may
219 * need to be copied. The copy should include a copy of the
220 * client-allocated data, which can be copied into the 'to'
221 * element from the 'from' element.
222 *
223 * @elt_free: When a tracing_map_elt is freed, this function is called 218 * @elt_free: When a tracing_map_elt is freed, this function is called
224 * and allows client-allocated per-element data to be freed. 219 * and allows client-allocated per-element data to be freed.
225 * 220 *
@@ -233,8 +228,6 @@ struct tracing_map {
233 */ 228 */
234struct tracing_map_ops { 229struct tracing_map_ops {
235 int (*elt_alloc)(struct tracing_map_elt *elt); 230 int (*elt_alloc)(struct tracing_map_elt *elt);
236 void (*elt_copy)(struct tracing_map_elt *to,
237 struct tracing_map_elt *from);
238 void (*elt_free)(struct tracing_map_elt *elt); 231 void (*elt_free)(struct tracing_map_elt *elt);
239 void (*elt_clear)(struct tracing_map_elt *elt); 232 void (*elt_clear)(struct tracing_map_elt *elt);
240 void (*elt_init)(struct tracing_map_elt *elt); 233 void (*elt_init)(struct tracing_map_elt *elt);