mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 13:37:10 +00:00
tools: acrn-crashlog: replace debugfs with api
Replace debugfs with api in loop.c. There is no functional change. Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com> Acked-by: Chen Gang <gang.c.chen@intel.com>
This commit is contained in:
parent
ea8cb410c5
commit
a4aed4535a
@ -24,7 +24,12 @@
|
|||||||
#define ANDROID_DATA_PAR_NAME "data"
|
#define ANDROID_DATA_PAR_NAME "data"
|
||||||
#define ANDROID_EVT_KEY_LEN 20
|
#define ANDROID_EVT_KEY_LEN 20
|
||||||
|
|
||||||
|
/* TODO: hardcoding the img path here means that only one Android Guest OS
|
||||||
|
* is supoorted at this moment. To support multiple Android Guest OS, this
|
||||||
|
* path should be moved to structure vm_t and configurable.
|
||||||
|
*/
|
||||||
static const char *android_img = "/data/android/android.img";
|
static const char *android_img = "/data/android/android.img";
|
||||||
|
static const char *android_histpath = "logs/history_event";
|
||||||
char *loop_dev;
|
char *loop_dev;
|
||||||
|
|
||||||
/* Find the head of str, caller must guarantee that 'str' is not in
|
/* Find the head of str, caller must guarantee that 'str' is not in
|
||||||
@ -211,43 +216,41 @@ static int refresh_key_synced_stage2(const struct mm_file_t *m_vm_records,
|
|||||||
static int get_vm_history(struct vm_t *vm, const struct sender_t *sender,
|
static int get_vm_history(struct vm_t *vm, const struct sender_t *sender,
|
||||||
void **data)
|
void **data)
|
||||||
{
|
{
|
||||||
char vm_history[PATH_MAX];
|
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
int ret;
|
int ret;
|
||||||
int sid;
|
int sid;
|
||||||
|
|
||||||
if (!vm || !sender)
|
if (!vm || !sender || !data)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sid = sender_id(sender);
|
sid = sender_id(sender);
|
||||||
if (sid == -1)
|
if (sid == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
snprintf(vm_history, sizeof(vm_history), "/tmp/%s_%s",
|
ret = e2fs_read_file_by_fpath(vm->datafs, android_histpath,
|
||||||
"vm_hist", vm->name);
|
data, &size);
|
||||||
|
if (ret == -1) {
|
||||||
|
LOGE("failed to get vm_history from (%s).\n", vm->name);
|
||||||
|
*data = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!size) {
|
||||||
|
LOGE("empty vm_history from (%s).\n", vm->name);
|
||||||
|
*data = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (get_file_size(vm_history) == (int)vm->history_size[sid])
|
if (size == vm->history_size[sid])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (*data)
|
|
||||||
free(*data);
|
|
||||||
ret = read_full_binary_file(vm_history, &size, data);
|
|
||||||
if (ret) {
|
|
||||||
LOGE("read (%s) with error (%s)\n", vm_history,
|
|
||||||
strerror(errno));
|
|
||||||
*data = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = strcnt(*data, '\n');
|
ret = strcnt(*data, '\n');
|
||||||
if (ret > VM_WARNING_LINES) {
|
if (ret > VM_WARNING_LINES)
|
||||||
LOGW("File too large, (%d) lines in (%s)\n",
|
LOGW("File too large, (%d) lines in (%s) of (%s)\n",
|
||||||
ret, vm_history);
|
ret, android_histpath, vm->name);
|
||||||
}
|
|
||||||
|
|
||||||
vm->history_size[sid] = size;
|
vm->history_size[sid] = size;
|
||||||
|
|
||||||
return size;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sync_lines_stage1(const struct sender_t *sender, const void *data[])
|
static void sync_lines_stage1(const struct sender_t *sender, const void *data[])
|
||||||
@ -269,9 +272,6 @@ static void sync_lines_stage1(const struct sender_t *sender, const void *data[])
|
|||||||
if (!vm)
|
if (!vm)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!vm->online)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (vm->last_synced_line_key[sid][0]) {
|
if (vm->last_synced_line_key[sid][0]) {
|
||||||
start = strstr(data[id],
|
start = strstr(data[id],
|
||||||
vm->last_synced_line_key[sid]);
|
vm->last_synced_line_key[sid]);
|
||||||
@ -358,9 +358,6 @@ static void sync_lines_stage2(const struct sender_t *sender, const void *data[],
|
|||||||
if (!vm)
|
if (!vm)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!vm->online)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strcmp(vm->name, vm_name))
|
if (strcmp(vm->name, vm_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -416,9 +413,6 @@ static void get_last_line_synced(const struct sender_t *sender)
|
|||||||
if (!vm)
|
if (!vm)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!vm->online)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* generally only exec for each vm once */
|
/* generally only exec for each vm once */
|
||||||
if (vm->last_synced_line_key[sid][0])
|
if (vm->last_synced_line_key[sid][0])
|
||||||
continue;
|
continue;
|
||||||
@ -501,58 +495,6 @@ static char *setup_loop_dev(void)
|
|||||||
return loop_dev;
|
return loop_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ping_vm_fs(char *loop_dev)
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
int res;
|
|
||||||
int count = 0;
|
|
||||||
struct vm_t *vm;
|
|
||||||
struct mm_file_t *vm_hist;
|
|
||||||
char vm_history[PATH_MAX];
|
|
||||||
char cmd[512];
|
|
||||||
const char prefix[] = "#V1.0 CURRENTUPTIME";
|
|
||||||
|
|
||||||
/* ensure history_event in uos available */
|
|
||||||
for_each_vm(id, vm, conf) {
|
|
||||||
if (!vm)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
snprintf(vm_history, sizeof(vm_history), "/tmp/%s_%s",
|
|
||||||
"vm_hist", vm->name);
|
|
||||||
snprintf(cmd, sizeof(cmd),
|
|
||||||
"dump logs/history_event %s", vm_history);
|
|
||||||
|
|
||||||
res = remove(vm_history);
|
|
||||||
if (res == -1 && errno != ENOENT)
|
|
||||||
LOGE("remove %s failed\n", vm_history);
|
|
||||||
|
|
||||||
res = debugfs_cmd(loop_dev, cmd, NULL);
|
|
||||||
if (res) {
|
|
||||||
vm->online = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm_hist = mmap_file(vm_history);
|
|
||||||
if (vm_hist == NULL) {
|
|
||||||
vm->online = 0;
|
|
||||||
LOGE("%s(%s) unavailable\n", vm->name, vm_history);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vm_hist->size &&
|
|
||||||
!strncmp(vm_hist->begin, prefix, strlen(prefix))) {
|
|
||||||
vm->online = 1;
|
|
||||||
count++;
|
|
||||||
} else {
|
|
||||||
vm->online = 0;
|
|
||||||
LOGE("%s(%s) unavailable\n", vm->name, vm_history);
|
|
||||||
}
|
|
||||||
|
|
||||||
unmap_file(vm_hist);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function searches all android vms' new events and call the fn for
|
/* This function searches all android vms' new events and call the fn for
|
||||||
* each event.
|
* each event.
|
||||||
*
|
*
|
||||||
@ -562,10 +504,10 @@ static int ping_vm_fs(char *loop_dev)
|
|||||||
void refresh_vm_history(const struct sender_t *sender,
|
void refresh_vm_history(const struct sender_t *sender,
|
||||||
int (*fn)(const char*, const struct vm_t *))
|
int (*fn)(const char*, const struct vm_t *))
|
||||||
{
|
{
|
||||||
int ret;
|
int res;
|
||||||
int id;
|
int id;
|
||||||
struct vm_t *vm;
|
struct vm_t *vm;
|
||||||
static void *data[VM_MAX];
|
void *data[VM_MAX];
|
||||||
|
|
||||||
if (!loop_dev) {
|
if (!loop_dev) {
|
||||||
loop_dev = setup_loop_dev();
|
loop_dev = setup_loop_dev();
|
||||||
@ -574,24 +516,31 @@ void refresh_vm_history(const struct sender_t *sender,
|
|||||||
LOGI("setup loop dev successful\n");
|
LOGI("setup loop dev successful\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sender_id(sender) == 0) {
|
|
||||||
ret = ping_vm_fs(loop_dev);
|
|
||||||
if (!ret)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_last_line_synced(sender);
|
get_last_line_synced(sender);
|
||||||
|
|
||||||
for_each_vm(id, vm, conf) {
|
for_each_vm(id, vm, conf) {
|
||||||
if (!vm)
|
if (!vm)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!vm->online)
|
data[id] = 0;
|
||||||
|
res = e2fs_open(loop_dev, &vm->datafs);
|
||||||
|
if (res == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
get_vm_history(vm, sender, &data[id]);
|
get_vm_history(vm, sender, (void *)&vm->history_data);
|
||||||
|
data[id] = vm->history_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_lines_stage2(sender, (const void **)data, fn);
|
sync_lines_stage2(sender, (const void **)data, fn);
|
||||||
sync_lines_stage1(sender, (const void **)data);
|
sync_lines_stage1(sender, (const void **)data);
|
||||||
|
for_each_vm(id, vm, conf) {
|
||||||
|
if (!vm)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
e2fs_close(vm->datafs);
|
||||||
|
|
||||||
|
if (data[id])
|
||||||
|
free(data[id]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,8 @@ static struct crash_t *crash_find_matched_child(const struct crash_t *crash,
|
|||||||
trfiles[i], strerror(errno));
|
trfiles[i], strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!size)
|
||||||
|
continue;
|
||||||
if (crash_match_content(child, content)) {
|
if (crash_match_content(child, content)) {
|
||||||
free(content);
|
free(content);
|
||||||
matched_child = child;
|
matched_child = child;
|
||||||
@ -316,6 +318,8 @@ static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash,
|
|||||||
trfiles[count - 1], strerror(errno));
|
trfiles[count - 1], strerror(errno));
|
||||||
goto free_files;
|
goto free_files;
|
||||||
}
|
}
|
||||||
|
if (!size)
|
||||||
|
goto free_files;
|
||||||
|
|
||||||
res = get_data(content, ret_crash, data0, data1, data2);
|
res = get_data(content, ret_crash, data0, data1, data2);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include <ext2fs/ext2fs.h>
|
||||||
#include "event_queue.h"
|
#include "event_queue.h"
|
||||||
|
|
||||||
#define CONTENT_MAX 10
|
#define CONTENT_MAX 10
|
||||||
@ -34,8 +35,9 @@ struct vm_t {
|
|||||||
char *interval;
|
char *interval;
|
||||||
char *syncevent[VM_EVENT_TYPE_MAX];
|
char *syncevent[VM_EVENT_TYPE_MAX];
|
||||||
|
|
||||||
int online;
|
ext2_filsys datafs;
|
||||||
unsigned long history_size[SENDER_MAX];
|
unsigned long history_size[SENDER_MAX];
|
||||||
|
char *history_data;
|
||||||
char last_synced_line_key[SENDER_MAX][SHA_DIGEST_LENGTH + 1];
|
char last_synced_line_key[SENDER_MAX][SHA_DIGEST_LENGTH + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -469,14 +469,14 @@ int is_boot_id_changed(void)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
res = read_file(BOOTID_NODE, &size, &boot_id);
|
res = read_file(BOOTID_NODE, &size, &boot_id);
|
||||||
if (res == -1)
|
if (res == -1 || !size)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
snprintf(logged_boot_id_path, sizeof(logged_boot_id_path), "%s/%s",
|
snprintf(logged_boot_id_path, sizeof(logged_boot_id_path), "%s/%s",
|
||||||
crashlog->outdir, BOOTID_LOG);
|
crashlog->outdir, BOOTID_LOG);
|
||||||
if (file_exists(logged_boot_id_path)) {
|
if (file_exists(logged_boot_id_path)) {
|
||||||
res = read_file(logged_boot_id_path, &size, &logged_boot_id);
|
res = read_file(logged_boot_id_path, &size, &logged_boot_id);
|
||||||
if (res == -1)
|
if (res == -1 || !size)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!strcmp((char *)logged_boot_id, (char *)boot_id))
|
if (!strcmp((char *)logged_boot_id, (char *)boot_id))
|
||||||
|
@ -86,6 +86,7 @@ static int get_buildversion(struct sender_t *sender)
|
|||||||
|
|
||||||
ret = file_read_string(logbuildid, lastbuild, VERSION_SIZE);
|
ret = file_read_string(logbuildid, lastbuild, VERSION_SIZE);
|
||||||
if (ret == -ENOENT ||
|
if (ret == -ENOENT ||
|
||||||
|
!ret ||
|
||||||
(ret > 0 && strcmp(currentbuild, lastbuild))) {
|
(ret > 0 && strcmp(currentbuild, lastbuild))) {
|
||||||
/* build changed or file not found, overwrite it */
|
/* build changed or file not found, overwrite it */
|
||||||
ret = overwrite_file(logbuildid, gbuildversion);
|
ret = overwrite_file(logbuildid, gbuildversion);
|
||||||
@ -97,7 +98,7 @@ static int get_buildversion(struct sender_t *sender)
|
|||||||
|
|
||||||
sender->sw_updated = 1;
|
sender->sw_updated = 1;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (ret <= 0) {
|
} else if (ret < 0) {
|
||||||
LOGE("Cannot read %s, error (%s)\n",
|
LOGE("Cannot read %s, error (%s)\n",
|
||||||
logbuildid, strerror(errno));
|
logbuildid, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "property.h"
|
#include "property.h"
|
||||||
#include "startupreason.h"
|
#include "startupreason.h"
|
||||||
#include "log_sys.h"
|
#include "log_sys.h"
|
||||||
|
#include "loop.h"
|
||||||
|
|
||||||
#ifdef HAVE_TELEMETRICS_CLIENT
|
#ifdef HAVE_TELEMETRICS_CLIENT
|
||||||
#include "telemetry.h"
|
#include "telemetry.h"
|
||||||
@ -899,10 +900,10 @@ static int crashlog_new_vmevent(const char *line_to_sync,
|
|||||||
char *vmlogpath = NULL;
|
char *vmlogpath = NULL;
|
||||||
char *key;
|
char *key;
|
||||||
char *log;
|
char *log;
|
||||||
char *cmd;
|
|
||||||
int ret = VMEVT_HANDLED;
|
int ret = VMEVT_HANDLED;
|
||||||
int res;
|
int res;
|
||||||
int quota;
|
int quota;
|
||||||
|
int cnt;
|
||||||
char *dir;
|
char *dir;
|
||||||
|
|
||||||
/* VM events in history_event like this:
|
/* VM events in history_event like this:
|
||||||
@ -951,35 +952,23 @@ static int crashlog_new_vmevent(const char *line_to_sync,
|
|||||||
*/
|
*/
|
||||||
log = strstr(rest, "/logs/");
|
log = strstr(rest, "/logs/");
|
||||||
if (log) {
|
if (log) {
|
||||||
res = asprintf(&vmlogpath, "%s", log + 1);
|
vmlogpath = log + 1;
|
||||||
if (res < 0) {
|
res = e2fs_dump_dir_by_dpath(vm->datafs, vmlogpath, dir, &cnt);
|
||||||
LOGE("compute string failed, out of memory\n");
|
if (res == -1) {
|
||||||
remove(dir);
|
if (cnt) {
|
||||||
|
LOGE("dump (%s) abort at (%d)\n", vmlogpath,
|
||||||
|
cnt);
|
||||||
ret = VMEVT_DEFER;
|
ret = VMEVT_DEFER;
|
||||||
goto free_dir;
|
} else {
|
||||||
|
LOGW("(%s) is missing\n", vmlogpath);
|
||||||
|
ret = VMEVT_HANDLED; /* missing logdir */
|
||||||
}
|
}
|
||||||
|
|
||||||
res = asprintf(&cmd, "rdump %s %s", vmlogpath, dir);
|
|
||||||
if (res < 0) {
|
|
||||||
LOGE("compute string failed, out of memory\n");
|
|
||||||
free(vmlogpath);
|
|
||||||
remove(dir);
|
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
goto free_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = debugfs_cmd(loop_dev, cmd, NULL);
|
|
||||||
if (res) {
|
|
||||||
LOGE("debugfs cmd %s failed (%d)\n", cmd, res);
|
|
||||||
res = remove(dir);
|
res = remove(dir);
|
||||||
if (res == -1 && errno != ENOENT)
|
if (res == -1 && errno != ENOENT)
|
||||||
LOGE("remove %s faield (%d)\n", dir, -errno);
|
LOGE("remove %s faield (%d)\n", dir, -errno);
|
||||||
ret = VMEVT_DEFER;
|
|
||||||
goto free_dir;
|
goto free_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cmd);
|
|
||||||
free(vmlogpath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_crashfile(dir, event, key, type, vm->name,
|
generate_crashfile(dir, event, key, type, vm->name,
|
||||||
|
@ -44,6 +44,10 @@ static int get_cmdline_bootreason(char *bootreason, const size_t limit)
|
|||||||
CURRENT_KERNEL_CMDLINE, strerror(errno));
|
CURRENT_KERNEL_CMDLINE, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!size) {
|
||||||
|
LOGW("empty file (%s)\n", CURRENT_KERNEL_CMDLINE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
start = strstr(cmdline, key);
|
start = strstr(cmdline, key);
|
||||||
if (!start) {
|
if (!start) {
|
||||||
|
@ -103,15 +103,6 @@ int execv_out2file(char * const argv[], const char *outfile)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int debugfs_cmd(const char *loop_dev, const char *cmd, const char *outfile)
|
|
||||||
{
|
|
||||||
const char *argv[5] = {"debugfs", "-R", NULL, NULL, 0};
|
|
||||||
|
|
||||||
argv[2] = cmd;
|
|
||||||
argv[3] = loop_dev;
|
|
||||||
return execv_out2file((char * const *)argv, outfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a command described in format string, and redirect the output
|
* Execute a command described in format string, and redirect the output
|
||||||
* to specified file. The file will be created/truncated if it
|
* to specified file. The file will be created/truncated if it
|
||||||
|
@ -4,6 +4,5 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int execv_out2file(char * const argv[], const char *outfile);
|
int execv_out2file(char * const argv[], const char *outfile);
|
||||||
int debugfs_cmd(const char *loop_dev, const char *cmd, const char *outfile);
|
|
||||||
int exec_out2file(const char *outfile, const char *fmt, ...);
|
int exec_out2file(const char *outfile, const char *fmt, ...);
|
||||||
char *exec_out2mem(const char *fmt, ...);
|
char *exec_out2mem(const char *fmt, ...);
|
||||||
|
Loading…
Reference in New Issue
Block a user