perf tools: Introduce perf_target__strerror()
authorNamhyung Kim <namhyung.kim@lge.com>
Mon, 7 May 2012 05:09:02 +0000 (14:09 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 7 May 2012 20:30:21 +0000 (17:30 -0300)
The perf_target__strerror() sets @buf to a string that describes the
(perf_target-specific) error condition that is passed via @errnum.

This is similar to strerror_r() and does same thing if @errnum has a
standard errno value.

Signed-off-by: Namhyung Kim <namhyung.kim@lge.com>
Suggested-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Reviewed-by: David Ahern <dsahern@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1336367344-28071-6-git-send-email-namhyung.kim@lge.com
[ committer note: No need to use PERF_ERRNO_TARGET__SUCCESS, use shorter idiom ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-record.c
tools/perf/builtin-top.c
tools/perf/util/debug.c
tools/perf/util/target.c
tools/perf/util/target.h

index d26a279..c8bf6ea 100644 (file)
@@ -831,6 +831,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
        struct perf_evsel *pos;
        struct perf_evlist *evsel_list;
        struct perf_record *rec = &record;
+       char errbuf[BUFSIZ];
 
        perf_header__set_cmdline(argc, argv);
 
@@ -884,11 +885,24 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
                goto out_symbol_exit;
        }
 
-       perf_target__validate(&rec->opts.target);
+       err = perf_target__validate(&rec->opts.target);
+       if (err) {
+               perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
+               ui__warning("%s", errbuf);
+       }
+
+       err = perf_target__parse_uid(&rec->opts.target);
+       if (err) {
+               int saved_errno = errno;
 
-       if (perf_target__parse_uid(&rec->opts.target) < 0)
+               perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
+               ui__warning("%s", errbuf);
+
+               err = -saved_errno;
                goto out_free_fd;
+       }
 
+       err = -ENOMEM;
        if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
                usage_with_options(record_usage, record_options);
 
index c9137ba..7ba0f03 100644 (file)
@@ -1150,7 +1150,8 @@ static const char * const top_usage[] = {
 int cmd_top(int argc, const char **argv, const char *prefix __used)
 {
        struct perf_evsel *pos;
-       int status = -ENOMEM;
+       int status;
+       char errbuf[BUFSIZ];
        struct perf_top top = {
                .count_filter        = 5,
                .delay_secs          = 2,
@@ -1252,10 +1253,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 
        setup_browser(false);
 
-       perf_target__validate(&top.target);
+       status = perf_target__validate(&top.target);
+       if (status) {
+               perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+               ui__warning("%s", errbuf);
+       }
+
+       status = perf_target__parse_uid(&top.target);
+       if (status) {
+               int saved_errno = errno;
 
-       if (perf_target__parse_uid(&top.target) < 0)
+               perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+               ui__warning("%s", errbuf);
+
+               status = -saved_errno;
                goto out_delete_evlist;
+       }
 
        if (top.target.tid == 0 && top.target.pid == 0 &&
            top.target.uid_str == NULL)
index 26817da..efb1fce 100644 (file)
@@ -11,6 +11,7 @@
 #include "event.h"
 #include "debug.h"
 #include "util.h"
+#include "target.h"
 
 int verbose;
 bool dump_trace = false, quiet = false;
index 02a6bed..1064d5b 100644 (file)
@@ -10,6 +10,7 @@
 #include "debug.h"
 
 #include <pwd.h>
+#include <string.h>
 
 
 enum perf_target_errno perf_target__validate(struct perf_target *target)
@@ -89,3 +90,53 @@ enum perf_target_errno perf_target__parse_uid(struct perf_target *target)
        target->uid = result->pw_uid;
        return PERF_ERRNO_TARGET__SUCCESS;
 }
+
+/*
+ * This must have a same ordering as the enum perf_target_errno.
+ */
+static const char *perf_target__error_str[] = {
+       "PID/TID switch overriding CPU",
+       "PID/TID switch overriding UID",
+       "UID switch overriding CPU",
+       "PID/TID switch overriding SYSTEM",
+       "UID switch overriding SYSTEM",
+       "Invalid User: %s",
+       "Problems obtaining information for user %s",
+};
+
+int perf_target__strerror(struct perf_target *target, int errnum,
+                         char *buf, size_t buflen)
+{
+       int idx;
+       const char *msg;
+
+       if (errnum >= 0) {
+               strerror_r(errnum, buf, buflen);
+               return 0;
+       }
+
+       if (errnum <  __PERF_ERRNO_TARGET__START ||
+           errnum >= __PERF_ERRNO_TARGET__END)
+               return -1;
+
+       idx = errnum - __PERF_ERRNO_TARGET__START;
+       msg = perf_target__error_str[idx];
+
+       switch (errnum) {
+       case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU
+        ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM:
+               snprintf(buf, buflen, "%s", msg);
+               break;
+
+       case PERF_ERRNO_TARGET__INVALID_UID:
+       case PERF_ERRNO_TARGET__USER_NOT_FOUND:
+               snprintf(buf, buflen, msg, target->uid_str);
+               break;
+
+       default:
+               /* cannot reach here */
+               break;
+       }
+
+       return 0;
+}
index d4aabda..6fcd01c 100644 (file)
@@ -43,4 +43,7 @@ enum perf_target_errno {
 enum perf_target_errno perf_target__validate(struct perf_target *target);
 enum perf_target_errno perf_target__parse_uid(struct perf_target *target);
 
+int perf_target__strerror(struct perf_target *target, int errnum, char *buf,
+                         size_t buflen);
+
 #endif /* _PERF_TARGET_H */