|
@@ -765,6 +765,41 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
|
|
|
[PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
|
|
|
};
|
|
|
|
|
|
+static bool config_term_shrinked;
|
|
|
+
|
|
|
+static bool
|
|
|
+config_term_avail(int term_type, struct parse_events_error *err)
|
|
|
+{
|
|
|
+ if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) {
|
|
|
+ err->str = strdup("Invalid term_type");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!config_term_shrinked)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ switch (term_type) {
|
|
|
+ case PARSE_EVENTS__TERM_TYPE_CONFIG:
|
|
|
+ case PARSE_EVENTS__TERM_TYPE_CONFIG1:
|
|
|
+ case PARSE_EVENTS__TERM_TYPE_CONFIG2:
|
|
|
+ case PARSE_EVENTS__TERM_TYPE_NAME:
|
|
|
+ return true;
|
|
|
+ default:
|
|
|
+ if (!err)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* term_type is validated so indexing is safe */
|
|
|
+ if (asprintf(&err->str, "'%s' is not usable in 'perf stat'",
|
|
|
+ config_term_names[term_type]) < 0)
|
|
|
+ err->str = NULL;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void parse_events__shrink_config_terms(void)
|
|
|
+{
|
|
|
+ config_term_shrinked = true;
|
|
|
+}
|
|
|
+
|
|
|
typedef int config_term_func_t(struct perf_event_attr *attr,
|
|
|
struct parse_events_term *term,
|
|
|
struct parse_events_error *err);
|
|
@@ -834,6 +869,17 @@ do { \
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Check term availbility after basic checking so
|
|
|
+ * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered.
|
|
|
+ *
|
|
|
+ * If check availbility at the entry of this function,
|
|
|
+ * user will see "'<sysfs term>' is not usable in 'perf stat'"
|
|
|
+ * if an invalid config term is provided for legacy events
|
|
|
+ * (for example, instructions/badterm/...), which is confusing.
|
|
|
+ */
|
|
|
+ if (!config_term_avail(term->type_term, err))
|
|
|
+ return -EINVAL;
|
|
|
return 0;
|
|
|
#undef CHECK_TYPE_VAL
|
|
|
}
|
|
@@ -2125,6 +2171,8 @@ static void config_terms_list(char *buf, size_t buf_sz)
|
|
|
for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
|
|
|
const char *name = config_term_names[i];
|
|
|
|
|
|
+ if (!config_term_avail(i, NULL))
|
|
|
+ continue;
|
|
|
if (!name)
|
|
|
continue;
|
|
|
if (name[0] == '<')
|