diff --git a/tools/acrn-crashlog/acrnprobe/include/vmrecord.h b/tools/acrn-crashlog/acrnprobe/include/vmrecord.h new file mode 100644 index 000000000..3900ed794 --- /dev/null +++ b/tools/acrn-crashlog/acrnprobe/include/vmrecord.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __VMRECORD_H__ +#define __VMRECORD_H__ +#include "pthread.h" + +#define VMRECORD_HEAD_LINES 10 +#define VMRECORD_TAG_LEN 9 +#define VMRECORD_TAG_WAITING_SYNC " <==" +#define VMRECORD_TAG_NOT_FOUND "NOT_FOUND" +#define VMRECORD_TAG_MISS_LOG "MISS_LOGS" +#define VMRECORD_TAG_ON_GOING " ON_GOING" +#define VMRECORD_TAG_SUCCESS " " + +enum vmrecord_mark_t { + SUCCESS, + NOT_FOUND, + WAITING_SYNC, + ON_GOING, + MISS_LOG +}; + +struct vmrecord_t { + char *path; + pthread_mutex_t mtx; + struct mm_file_t *recos; +}; + +int vmrecord_last(struct vmrecord_t *vmrecord, const char *vm_name, + size_t nlen, char *vmkey, size_t ksize); +int vmrecord_mark(struct vmrecord_t *vmrecord, const char *vmkey, + size_t klen, enum vmrecord_mark_t type); +int vmrecord_open_mark(struct vmrecord_t *vmrecord, const char *vmkey, + size_t klen, enum vmrecord_mark_t type); +int vmrecord_gen_ifnot_exists(struct vmrecord_t *vmrecord); +int vmrecord_new(struct vmrecord_t *vmrecord, const char *vm_name, + const char *key); + + +#endif diff --git a/tools/acrn-crashlog/acrnprobe/vmrecord.c b/tools/acrn-crashlog/acrnprobe/vmrecord.c new file mode 100644 index 000000000..19692d745 --- /dev/null +++ b/tools/acrn-crashlog/acrnprobe/vmrecord.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2018 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "log_sys.h" +#include "fsutils.h" +#include "strutils.h" +#include "vmrecord.h" +#include + +int vmrecord_last(struct vmrecord_t *vmrecord, const char *vm_name, + size_t nlen, char *vmkey, size_t ksize) +{ + int res; + char *p; + char *key; + + if (!vmrecord || !vm_name || !nlen || !vmkey || !ksize) + return -1; + + key = malloc(nlen + 2); + if (!key) + return -1; + + memcpy(key, vm_name, nlen); + key[nlen] = ' '; + key[nlen + 1] = '\0'; + + pthread_mutex_lock(&vmrecord->mtx); + res = file_read_key_value_r(vmkey, ksize, vmrecord->path, key, + nlen + 1); + pthread_mutex_unlock(&vmrecord->mtx); + free(key); + if (res < 0) { + LOGE("failed to search %s, %s\n", vmrecord->path, + strerror(errno)); + return -1; + } + p = strchr(vmkey, ' '); + if (p) + *p = 0; + + return 0; +} + +/* This function must be called with holding vmrecord mutex */ +int vmrecord_mark(struct vmrecord_t *vmrecord, const char *vmkey, + size_t klen, enum vmrecord_mark_t type) +{ + size_t len; + char *line; + char *tag; + + if (!vmrecord || !vmrecord->recos || !vmkey || !klen) + return -1; + + line = get_line(vmkey, klen, vmrecord->recos->begin, + vmrecord->recos->size, vmrecord->recos->begin, &len); + if (!line) + return -1; + + tag = line + len - VMRECORD_TAG_LEN; + + if (type == SUCCESS) + memcpy(tag, VMRECORD_TAG_SUCCESS, VMRECORD_TAG_LEN); + else if (type == NOT_FOUND) + memcpy(tag, VMRECORD_TAG_NOT_FOUND, VMRECORD_TAG_LEN); + else if (type == MISS_LOG) + memcpy(tag, VMRECORD_TAG_MISS_LOG, VMRECORD_TAG_LEN); + else if (type == WAITING_SYNC) + memcpy(tag, VMRECORD_TAG_WAITING_SYNC, VMRECORD_TAG_LEN); + else if (type == ON_GOING) + memcpy(tag, VMRECORD_TAG_ON_GOING, VMRECORD_TAG_LEN); + else + return -1; + + return 0; + +} + +int vmrecord_open_mark(struct vmrecord_t *vmrecord, const char *vmkey, + size_t klen, enum vmrecord_mark_t type) +{ + int ret; + + if (!vmrecord || !vmkey || !klen) + return -1; + + pthread_mutex_lock(&vmrecord->mtx); + vmrecord->recos = mmap_file(vmrecord->path); + if (!vmrecord->recos) { + LOGE("failed to mmap %s, %s\n", vmrecord->path, + strerror(errno)); + ret = -1; + goto unlock; + } + if (!vmrecord->recos->size || + mm_count_lines(vmrecord->recos) < VMRECORD_HEAD_LINES) { + LOGE("(%s) invalid\n", vmrecord->path); + ret = -1; + goto out; + } + + ret = vmrecord_mark(vmrecord, vmkey, klen, type); +out: + unmap_file(vmrecord->recos); +unlock: + pthread_mutex_unlock(&vmrecord->mtx); + return ret; +} + +int vmrecord_gen_ifnot_exists(struct vmrecord_t *vmrecord) +{ + const char * const head = + "/* DONT EDIT!\n" + " * This file records VM id synced or about to be synched,\n" + " * the tag:\n" + " * \"<==\" indicates event waiting to sync.\n" + " * \"NOT_FOUND\" indicates event not found in UOS.\n" + " * \"MISS_LOGS\" indicates event miss logs in UOS.\n" + " * \"ON_GOING\" indicates event is under syncing.\n" + " * \"NO_RESORC\" indicates no enough resources in SOS.\n" + " */\n\n"; + + if (!vmrecord) { + LOGE("vmrecord was not initialized\n"); + return -1; + } + + pthread_mutex_lock(&vmrecord->mtx); + if (!file_exists(vmrecord->path)) { + if (overwrite_file(vmrecord->path, head) < 0) { + pthread_mutex_unlock(&vmrecord->mtx); + LOGE("failed to create file (%s), %s\n", + vmrecord->path, strerror(errno)); + return -1; + } + } + pthread_mutex_unlock(&vmrecord->mtx); + return 0; +} + +int vmrecord_new(struct vmrecord_t *vmrecord, const char *vm_name, + const char *key) +{ + char log_new[64]; + int nlen; + + if (!vmrecord || !vm_name || !key) + return -1; + + nlen = snprintf(log_new, sizeof(log_new), "%s %s %s\n", + vm_name, key, VMRECORD_TAG_WAITING_SYNC); + if (s_not_expect(nlen, sizeof(log_new))) { + LOGE("failed to construct record, key (%s)\n", key); + return -1; + } + + pthread_mutex_lock(&vmrecord->mtx); + if (append_file(vmrecord->path, log_new, strnlen(log_new, 64)) < 0) { + pthread_mutex_unlock(&vmrecord->mtx); + LOGE("failed to append file (%s), %s\n", vmrecord->path, + strerror(errno)); + return -1; + } + pthread_mutex_unlock(&vmrecord->mtx); + return 0; +}