Skip to content

Commit

Permalink
record: make all info in text format
Browse files Browse the repository at this point in the history
All header info was written by binary format.
But this commit changes all info to uftrace.data/info.txt
in text format.

To support backward compatibility with previous versions,
if uftrace.data/info.txt doesn't exist, then find uftrace.data/info
written by binary format.

Fixed: #1408.

Signed-off-by: Sangwon Hong <[email protected]>
  • Loading branch information
qpakzk committed Jun 19, 2022
1 parent 7c0f8a6 commit 70407f5
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 28 deletions.
85 changes: 82 additions & 3 deletions cmds/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,82 @@ static int read_uftrace_version(void *arg)
return 0;
}

void write_header(int fd, struct uftrace_file_header *hdr)
{
dprintf(fd, "magic:%s\n", hdr->magic);
dprintf(fd, "version:%u\n", hdr->version);
dprintf(fd, "header_size:%u\n", hdr->header_size);
dprintf(fd, "endian:%u\n", hdr->endian);
dprintf(fd, "elf_class:%u\n", hdr->elf_class);
dprintf(fd, "feat_mask:%"PRIu64"\n", hdr->feat_mask);
dprintf(fd, "info_mask:%"PRIu64"\n", hdr->info_mask);
dprintf(fd, "max_stack:%u\n", hdr->max_stack);
}

static char *read_header_field(FILE *fp, struct uftrace_file_header *hdr,
const char *field, char *buf)
{
int len = strlen(field);

if (fgets(buf, PATH_MAX, fp) == NULL)
return NULL;
if (strncmp(buf, field, len))
return NULL;
return &buf[len];
}

int read_header(struct uftrace_file_header *hdr, FILE *fp, bool is_info_txt)
{
char buf[PATH_MAX];
char *data;

if (is_info_txt) {
data = read_header_field(fp, hdr, "magic:", buf);
if (!data)
return -1;
memcpy(hdr->magic, copy_info_str(data), UFTRACE_MAGIC_LEN - 1);

data = read_header_field(fp, hdr, "version:", buf);
if (!data)
return -1;
sscanf(data, "%u", &hdr->version);

data = read_header_field(fp, hdr, "header_size:", buf);
if (!data)
return -1;
sscanf(data, "%hu", &hdr->header_size);

data = read_header_field(fp, hdr, "endian:", buf);
if (!data)
return -1;
sscanf(data, "%hhu", &hdr->endian);

data = read_header_field(fp, hdr, "elf_class:", buf);
if (!data)
return -1;
sscanf(data, "%hhu", &hdr->elf_class);

data = read_header_field(fp, hdr, "feat_mask:", buf);
if (!data)
return -1;
sscanf(data, "%"PRIu64, &hdr->feat_mask);

data = read_header_field(fp, hdr, "info_mask:", buf);
if (!data)
return -1;
sscanf(data, "%"PRIu64, &hdr->info_mask);

data = read_header_field(fp, hdr, "max_stack:", buf);
if (!data)
return -1;
sscanf(data, "%hu", &hdr->max_stack);
}
else if (fread(hdr, sizeof(hdr), 1, fp) != 1)
return -1;
return 0;
}


struct uftrace_info_handler {
enum uftrace_info_bits bit;
int (*handler)(void *arg);
Expand Down Expand Up @@ -987,10 +1063,13 @@ void process_uftrace_info(struct uftrace_data *handle, struct opts *opts,
if (info_mask == 0)
return;

snprintf(buf, sizeof(buf), "%s/info", opts->dirname);
snprintf(buf, sizeof(buf), "%s/info.txt", opts->dirname);

if (stat(buf, &statbuf) < 0)
return;
if (stat(buf, &statbuf) < 0) {
snprintf(buf, sizeof(buf), "%s/info", opts->dirname);
if (stat(buf, &statbuf) < 0)
return;
}

process(data, "# system information\n");
process(data, "# ==================\n");
Expand Down
34 changes: 17 additions & 17 deletions cmds/record.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,12 @@ static int fill_file_header(struct opts *opts, int status, struct rusage *rusage
char *filename = NULL;
struct uftrace_file_header hdr;
char elf_ident[EI_NIDENT];
char buf[PATH_MAX];

xasprintf(&filename, "%s/info", opts->dirname);
xasprintf(&filename, "%s/info.txt", opts->dirname);
pr_dbg3("fill header (metadata) info in %s\n", filename);

fd = open(filename, O_WRONLY | O_CREAT| O_TRUNC, 0644);
fd = open(filename, O_RDWR | O_CREAT| O_TRUNC, 0644);
if (fd < 0)
pr_err("cannot open info file");

Expand All @@ -447,26 +448,21 @@ static int fill_file_header(struct opts *opts, int status, struct rusage *rusage
hdr.unused1 = 0;
hdr.unused2 = 0;

if (write(fd, &hdr, sizeof(hdr)) != (int)sizeof(hdr))
pr_err("writing header info failed");

fill_uftrace_info(&hdr.info_mask, fd, opts, status,
rusage, elapsed_time);

try_write:
ret = pwrite(fd, &hdr, sizeof(hdr), 0);
if (ret != (int)sizeof(hdr)) {
static int retry = 0;

if (ret > 0 && retry++ < 3)
goto try_write;
memset(buf, 0, PATH_MAX);
lseek(fd, 0, SEEK_SET);
if (read(fd, buf, PATH_MAX) < 0)
goto close_efd;

lseek(fd, 0, SEEK_SET);
write_header(fd, &hdr);
if (write(fd, buf, strlen(buf)) < 0) {
pr_dbg("writing header info failed.\n");
goto close_efd;
}

ret = 0;

close_efd:
close(efd);
close_fd:
Expand Down Expand Up @@ -1373,10 +1369,14 @@ static void send_info_file(int sock, const char *dirname)
void *info;
int len;

xasprintf(&filename, "%s/info", dirname);
xasprintf(&filename, "%s/info.txt", dirname);
fd = open(filename, O_RDONLY);
if (fd < 0)
pr_err("open info failed");
if (fd < 0) {
xasprintf(&filename, "%s/info", dirname);
fd = open(filename, O_RDONLY);
if (fd < 0)
pr_err("open info failed");
}

if (fstat(fd, &stbuf) < 0)
pr_err("stat info failed");
Expand Down
3 changes: 3 additions & 0 deletions uftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,9 @@ static inline bool has_event_data(struct uftrace_data *handle)

struct rusage;


void write_header(int fd, struct uftrace_file_header *hdr);
int read_header(struct uftrace_file_header *hdr, FILE *fp, bool is_info_txt);
void fill_uftrace_info(uint64_t *info_mask, int fd, struct opts *opts, int status,
struct rusage *rusage, char *elapsed_time);
int read_uftrace_info(uint64_t info_mask, struct uftrace_data *handle);
Expand Down
42 changes: 34 additions & 8 deletions utils/data-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,18 +413,28 @@ bool data_is_lp64(struct uftrace_data *handle)
int open_info_file(struct opts *opts, struct uftrace_data *handle)
{
FILE *fp;
char buf[PATH_MAX];
char info_txt[PATH_MAX];
char info_bin[PATH_MAX];
bool is_info_txt = true;
int saved_errno = 0;
struct stat stbuf;

memset(handle, 0, sizeof(*handle));

snprintf(buf, sizeof(buf), "%s/info", opts->dirname);
snprintf(info_txt, sizeof(info_txt), "%s/info.txt", opts->dirname);

fp = fopen(buf, "rb");
fp = fopen(info_txt, "r");
if (fp != NULL)
goto ok;

snprintf(info_bin, sizeof(info_bin), "%s/info", opts->dirname);

fp = fopen(info_bin, "rb");
if (fp != NULL) {
is_info_txt = false;
goto ok;
}

saved_errno = errno;
/* provide a better error code for empty/invalid directories */
if (stat(opts->dirname, &stbuf) == 0)
Expand All @@ -433,28 +443,44 @@ int open_info_file(struct opts *opts, struct uftrace_data *handle)
/* if default dirname is failed */
if (!strcmp(opts->dirname, UFTRACE_DIR_NAME)) {
/* try again inside the current directory */
fp = fopen("./info.txt", "r");
if (fp != NULL) {
opts->dirname = "./";
goto ok;
}

fp = fopen("./info", "rb");
if (fp != NULL) {
opts->dirname = "./";
is_info_txt = false;
goto ok;
}

/* retry with old default dirname */
snprintf(buf, sizeof(buf), "%s/info", UFTRACE_DIR_OLD_NAME);
fp = fopen(buf, "rb");
snprintf(info_txt, sizeof(info_txt), "%s/info.txt", UFTRACE_DIR_OLD_NAME);
fp = fopen(info_txt, "r");
if (fp != NULL) {
opts->dirname = UFTRACE_DIR_OLD_NAME;
goto ok;
}

snprintf(info_bin, sizeof(info_bin), "%s/info", UFTRACE_DIR_OLD_NAME);
fp = fopen(info_bin, "rb");
if (fp != NULL) {
opts->dirname = UFTRACE_DIR_OLD_NAME;
is_info_txt = false;
goto ok;
}

saved_errno = errno;

/* restore original file name for error reporting */
snprintf(buf, sizeof(buf), "%s/info", opts->dirname);
snprintf(info_txt, sizeof(info_txt), "%s/info.txt", opts->dirname);
snprintf(info_bin, sizeof(info_bin), "%s/info", opts->dirname);
}

/* data file loading is failed */
pr_dbg("cannot open %s file\n", buf);
pr_dbg("cannot open %s or %s file\n", info_txt, info_bin);

return -saved_errno;
ok:
Expand All @@ -469,7 +495,7 @@ int open_info_file(struct opts *opts, struct uftrace_data *handle)
handle->last_perf_idx = -1;
INIT_LIST_HEAD(&handle->events);

if (fread(&handle->hdr, sizeof(handle->hdr), 1, fp) != 1)
if (read_header(&handle->hdr, fp, is_info_txt) < 0)
pr_err("cannot read header data");

if (memcmp(handle->hdr.magic, UFTRACE_MAGIC_STR, UFTRACE_MAGIC_LEN))
Expand Down

0 comments on commit 70407f5

Please sign in to comment.