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 27, 2022
1 parent 7c0f8a6 commit ab895eb
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 34 deletions.
9 changes: 6 additions & 3 deletions cmds/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,9 +1013,12 @@ static void dump_chrome_footer(struct uftrace_dump_ops *ops,
struct uftrace_chrome_dump *chrome = container_of(ops, typeof(*chrome), ops);

/* read recorded date and time */
snprintf(buf, sizeof(buf), "%s/info", opts->dirname);
if (stat(buf, &statbuf) < 0)
return;
snprintf(buf, sizeof(buf), "%s/info.txt", opts->dirname);
if (stat(buf, &statbuf) < 0) {
snprintf(buf, sizeof(buf), "%s/info", opts->dirname);
if (stat(buf, &statbuf) < 0)
return;
}

ctime_r(&statbuf.st_mtime, buf);
buf[strlen(buf) - 1] = '\0';
Expand Down
89 changes: 85 additions & 4 deletions cmds/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,85 @@ 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) {
if (fread(hdr, sizeof(*hdr), 1, fp) != 1)
return -1;
return 0;
}

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);

return 0;
}


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

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

if (stat(buf, &statbuf) < 0)
return;
snprintf(buf, sizeof(buf), "%s/info.txt", opts->dirname);
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
29 changes: 11 additions & 18 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 @@ -1367,14 +1363,12 @@ static void send_dbg_files(int sock, const char *dirname)
static void send_info_file(int sock, const char *dirname)
{
int fd;
char *filename = NULL;
struct uftrace_file_header hdr;
struct stat stbuf;
void *info;
int len;

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

Expand All @@ -1394,7 +1388,6 @@ static void send_info_file(int sock, const char *dirname)

close(fd);
free(info);
free(filename);
}

static void send_kernel_metadata(int sock, const char *dirname)
Expand Down
2 changes: 1 addition & 1 deletion cmds/recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ static void recv_trace_info(int sock, int len)
if (read_all(sock, info, len) < 0)
pr_err("recv info failed");

write_client_file(client, "info", 2, &hdr, sizeof(hdr), info, len);
write_client_file(client, "info.txt", 2, &hdr, sizeof(hdr), info, len);

free(info);
}
Expand Down
4 changes: 4 additions & 0 deletions uftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ int command_tui(int argc, char *argv[], struct opts *opts);
extern volatile bool uftrace_done;

int open_data_file(struct opts *opts, struct uftrace_data *handle);
int open_correct_info_file(const char *dirname, int flags, ...);
int open_info_file(struct opts *opts, struct uftrace_data *handle);
void __close_data_file(struct opts *opts, struct uftrace_data *handle,
bool unload_modules);
Expand Down Expand Up @@ -553,6 +554,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
67 changes: 59 additions & 8 deletions utils/data-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,21 +410,56 @@ bool data_is_lp64(struct uftrace_data *handle)
return handle->hdr.elf_class == ELFCLASS64;
}

int open_correct_info_file(const char *dirname, int flags, ...)
{
char buf[PATH_MAX];
struct stat statbuf;

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

if (flags & O_CREAT) {
va_list ap;
mode_t mode;

va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);

return open(buf, flags, mode);
}
return open(buf, flags);
}

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 +468,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 +520,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 ab895eb

Please sign in to comment.