Skip to content

Commit c04949d

Browse files
mgcaoacrnsi
authored andcommitted
DM: add disk-logger to write log into file system
disk-logger used to save persistent log as file in disk. log path: /var/log/acrn-dm/ each log file size is 2MB; default 8 log files; the log files' suffix will be increased; when file count more than 8, the last one added, the first one is removed, like form 1-8 to 2-9 to 3-10 ... Tracked-On: #3012 Signed-off-by: Minggui Cao <minggui.cao@intel.com> Reviewed-by: Yin Fengwei <fengwei.yin@intel.com>
1 parent 6fa41ee commit c04949d

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed

devicemodel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ SRCS += arch/x86/pm.c
153153
# log
154154
SRCS += log/log.c
155155
SRCS += log/kmsg_logger.c
156+
SRCS += log/disk_logger.c
156157

157158
OBJS := $(patsubst %.c,$(DM_OBJDIR)/%.o,$(SRCS))
158159

devicemodel/log/disk_logger.c

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
* Copyright (C) 2018 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <sys/param.h>
8+
#include <sys/stat.h>
9+
#include <errno.h>
10+
#include <paths.h>
11+
#include <stdarg.h>
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
#include <string.h>
15+
#include <unistd.h>
16+
#include <stdbool.h>
17+
#include <fcntl.h>
18+
#include <dirent.h>
19+
#include <time.h>
20+
21+
#include "dm.h"
22+
#include "log.h"
23+
24+
#define DISK_PREFIX "disk_log: "
25+
26+
#define LOG_PATH_NODE "/var/log/acrn-dm/"
27+
#define LOG_NAME_PREFIX "%s_log_"
28+
#define LOG_NAME_FMT "%s%s_log_%d" /* %s-->vm1/vm2..., %d-->1/2/3/4... */
29+
#define LOG_DELIMITER "\n\n----------------new vm instance------------------\n\n\0"
30+
31+
#define FILE_NAME_LENGTH 96
32+
33+
#define LOG_SIZE_LIMIT 0x200000 /* one log file size limit */
34+
#define LOG_FILES_COUNT 8
35+
36+
static int disk_fd = -1;
37+
static uint32_t cur_log_size;
38+
static uint16_t cur_file_index;
39+
40+
static uint8_t disk_log_level = LOG_DEBUG;
41+
static bool disk_log_enabled = false;
42+
43+
#define DISK_LOG_MAX_LEN (MAX_ONE_LOG_SIZE + 32)
44+
#define INDEX_AFTER(a, b) ((short int)b - (short int)a < 0)
45+
46+
static bool is_disk_log_enabled(void)
47+
{
48+
return disk_log_enabled;
49+
}
50+
51+
static uint8_t get_disk_log_level(void)
52+
{
53+
return disk_log_level;
54+
}
55+
56+
static int probe_disk_log_file(void)
57+
{
58+
char file_name[FILE_NAME_LENGTH];
59+
struct dirent *pdir;
60+
struct stat st;
61+
int length;
62+
uint16_t index = 0, tmp;
63+
bool is_first_file = true;
64+
DIR *dir;
65+
66+
if (stat(LOG_PATH_NODE, &st)) {
67+
if (mkdir(LOG_PATH_NODE, 0644)) {
68+
printf(DISK_PREFIX"create path: %s failed! Error: %s\n",
69+
LOG_PATH_NODE, strerror(errno));
70+
return -1;
71+
}
72+
}
73+
74+
dir = opendir(LOG_PATH_NODE);
75+
if (!dir) {
76+
printf(DISK_PREFIX" open %s failed! Error: %s\n",
77+
LOG_PATH_NODE, strerror(errno));
78+
return -1;
79+
}
80+
81+
snprintf(file_name, FILE_NAME_LENGTH - 1, LOG_NAME_PREFIX, vmname);
82+
length = strlen(file_name);
83+
84+
while ((pdir = readdir(dir)) != NULL) {
85+
if (!(pdir->d_type & DT_REG))
86+
continue;
87+
88+
if (strncmp(pdir->d_name, file_name, length) != 0)
89+
continue;
90+
91+
tmp = (uint16_t)atoi(pdir->d_name + length);
92+
if (is_first_file) {
93+
is_first_file = false;
94+
index = tmp;
95+
} else if (INDEX_AFTER(tmp, index)) {
96+
index = tmp;
97+
}
98+
}
99+
100+
snprintf(file_name, FILE_NAME_LENGTH - 1, LOG_NAME_FMT, LOG_PATH_NODE, vmname, index);
101+
disk_fd = open(file_name, O_RDWR | O_CREAT | O_APPEND, 0644);
102+
if (disk_fd < 0) {
103+
printf(DISK_PREFIX" open %s failed! Error: %s\n", file_name, strerror(errno));
104+
return -1;
105+
}
106+
107+
if (write(disk_fd, LOG_DELIMITER, strlen(LOG_DELIMITER)) < 0) {
108+
printf(DISK_PREFIX" write %s failed! Error: %s\n", file_name, strerror(errno));
109+
return -1;
110+
}
111+
112+
fstat(disk_fd, &st);
113+
cur_log_size = st.st_size;
114+
cur_file_index = index;
115+
116+
return 0;
117+
}
118+
119+
static int init_disk_logger(bool enable, uint8_t log_level)
120+
{
121+
disk_log_enabled = enable;
122+
disk_log_level = log_level;
123+
124+
return 1;
125+
}
126+
127+
static void deinit_disk_logger(void)
128+
{
129+
if (disk_fd > 0) {
130+
disk_log_enabled = false;
131+
132+
fsync(disk_fd);
133+
close(disk_fd);
134+
disk_fd = -1;
135+
}
136+
}
137+
138+
static void write_to_disk(const char *fmt, va_list args)
139+
{
140+
char buffer[DISK_LOG_MAX_LEN];
141+
char *file_name = buffer;
142+
int len1, len2;
143+
int write_cnt;
144+
struct timespec times = {0, 0};
145+
146+
if ((disk_fd < 0) && disk_log_enabled) {
147+
/**
148+
* usually this probe just be called once in DM whole life; but we need use vmname in
149+
* probe_disk_log_file, it can't be called in init_disk_logger for vmname not inited then,
150+
* so call it here.
151+
*/
152+
if (probe_disk_log_file() < 0) {
153+
disk_log_enabled = false;
154+
return;
155+
}
156+
}
157+
158+
clock_gettime(CLOCK_MONOTONIC, &times);
159+
len1 = sprintf(buffer, "[%5lu.%06lu] ", times.tv_sec, times.tv_nsec / 1000);
160+
len2 = vsnprintf(buffer + len1, MAX_ONE_LOG_SIZE, fmt, args);
161+
162+
write_cnt = write(disk_fd, buffer, len1 + len2);
163+
if (write_cnt < 0) {
164+
perror(DISK_PREFIX"write disk failed");
165+
close(disk_fd);
166+
disk_fd = -1;
167+
return;
168+
}
169+
170+
cur_log_size += write_cnt;
171+
if (cur_log_size > LOG_SIZE_LIMIT) {
172+
173+
cur_file_index++;
174+
175+
/* remove the first old log file, to add a new one */
176+
snprintf(file_name, FILE_NAME_LENGTH - 1, LOG_NAME_FMT,
177+
LOG_PATH_NODE, vmname, (uint16_t)(cur_file_index - LOG_FILES_COUNT));
178+
remove(file_name);
179+
180+
snprintf(file_name, FILE_NAME_LENGTH - 1, LOG_NAME_FMT,
181+
LOG_PATH_NODE, vmname, cur_file_index);
182+
183+
close(disk_fd);
184+
disk_fd = open(file_name, O_RDWR | O_CREAT, 0644);
185+
if (disk_fd < 0) {
186+
printf(DISK_PREFIX" open %s failed! Error: %s\n", file_name, strerror(errno));
187+
return;
188+
}
189+
cur_log_size = 0;
190+
}
191+
}
192+
193+
static struct logger_ops logger_disk = {
194+
.name = "disk",
195+
.is_enabled = is_disk_log_enabled,
196+
.get_log_level = get_disk_log_level,
197+
.init = init_disk_logger,
198+
.deinit = deinit_disk_logger,
199+
.output = write_to_disk,
200+
};
201+
202+
DEFINE_LOGGER_DEVICE(logger_disk);

0 commit comments

Comments
 (0)