diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/trace_events_hist.c | 11 | ||||
| -rw-r--r-- | kernel/trace/tracing_map.c | 83 | ||||
| -rw-r--r-- | kernel/trace/tracing_map.h | 7 |
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 | ||
| 343 | static 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 | |||
| 353 | static void hist_trigger_elt_comm_init(struct tracing_map_elt *elt) | 343 | static 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 | ||
| 361 | static const struct tracing_map_ops hist_trigger_elt_comm_ops = { | 351 | static 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 | ||
| 850 | static struct tracing_map_elt *copy_elt(struct tracing_map_elt *elt) | 850 | static 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 | |||
| 874 | static 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 | |||
| 902 | static 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 | ||
| 945 | static bool is_key(struct tracing_map *map, unsigned int field_idx) | 877 | static 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 | */ |
| 234 | struct tracing_map_ops { | 229 | struct 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); |
