perf tools: Introduce perf_target__strerror()

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>
This commit is contained in:
Namhyung Kim 2012-05-07 14:09:02 +09:00 committed by Arnaldo Carvalho de Melo
parent dfe78adaac
commit 16ad2ffb82
5 changed files with 87 additions and 5 deletions

View File

@ -831,6 +831,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
struct perf_evsel *pos; struct perf_evsel *pos;
struct perf_evlist *evsel_list; struct perf_evlist *evsel_list;
struct perf_record *rec = &record; struct perf_record *rec = &record;
char errbuf[BUFSIZ];
perf_header__set_cmdline(argc, argv); 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; 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);
}
if (perf_target__parse_uid(&rec->opts.target) < 0) err = perf_target__parse_uid(&rec->opts.target);
if (err) {
int saved_errno = errno;
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
ui__warning("%s", errbuf);
err = -saved_errno;
goto out_free_fd; goto out_free_fd;
}
err = -ENOMEM;
if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
usage_with_options(record_usage, record_options); usage_with_options(record_usage, record_options);

View File

@ -1150,7 +1150,8 @@ static const char * const top_usage[] = {
int cmd_top(int argc, const char **argv, const char *prefix __used) int cmd_top(int argc, const char **argv, const char *prefix __used)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
int status = -ENOMEM; int status;
char errbuf[BUFSIZ];
struct perf_top top = { struct perf_top top = {
.count_filter = 5, .count_filter = 5,
.delay_secs = 2, .delay_secs = 2,
@ -1252,10 +1253,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
setup_browser(false); 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);
}
if (perf_target__parse_uid(&top.target) < 0) status = perf_target__parse_uid(&top.target);
if (status) {
int saved_errno = errno;
perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
ui__warning("%s", errbuf);
status = -saved_errno;
goto out_delete_evlist; goto out_delete_evlist;
}
if (top.target.tid == 0 && top.target.pid == 0 && if (top.target.tid == 0 && top.target.pid == 0 &&
top.target.uid_str == NULL) top.target.uid_str == NULL)

View File

@ -11,6 +11,7 @@
#include "event.h" #include "event.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "target.h"
int verbose; int verbose;
bool dump_trace = false, quiet = false; bool dump_trace = false, quiet = false;

View File

@ -10,6 +10,7 @@
#include "debug.h" #include "debug.h"
#include <pwd.h> #include <pwd.h>
#include <string.h>
enum perf_target_errno perf_target__validate(struct perf_target *target) 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; target->uid = result->pw_uid;
return PERF_ERRNO_TARGET__SUCCESS; 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;
}

View 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__validate(struct perf_target *target);
enum perf_target_errno perf_target__parse_uid(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 */ #endif /* _PERF_TARGET_H */