diff --git a/tools/acrn-crashlog/acrnprobe/event_handler.c b/tools/acrn-crashlog/acrnprobe/event_handler.c
index bc710bb5b..4aa9d54da 100644
--- a/tools/acrn-crashlog/acrnprobe/event_handler.c
+++ b/tools/acrn-crashlog/acrnprobe/event_handler.c
@@ -124,6 +124,38 @@ static void watchdog_init(int timeout)
}
}
+static int check_folder_space(struct sender_t *sender)
+{
+ size_t dsize;
+ int cfg_size;
+
+ if (dir_size(sender->outdir, sender->outdir_len, &dsize) == -1) {
+ LOGE("failed to check outdir size, drop ev\n");
+ return -1;
+ }
+
+ if (cfg_atoi(sender->foldersize, sender->foldersize_len,
+ &cfg_size) == -1)
+ return -1;
+
+ if (dsize/MB >= (size_t)cfg_size) {
+ if (sender->suspending)
+ return -1;
+
+ LOGW("suspend (%s), since (%s: %ldM) meets quota (%dM)\n",
+ sender->name, sender->outdir, dsize/MB, cfg_size);
+ sender->suspending = 1;
+ return -1;
+ }
+
+ if (!sender->suspending)
+ return 0;
+
+ LOGW("resume (%s), %s: left space %ldM for storage\n",
+ sender->name, sender->outdir, cfg_size - dsize/MB);
+ return 0;
+}
+
/**
* Process each event in event queue.
* Note that currently event handler is single threaded.
@@ -157,6 +189,9 @@ static void *event_handle(void *unused __attribute__((unused)))
if (!sender)
continue;
+ if (check_folder_space(sender) == -1)
+ continue;
+
if (sender->send)
sender->send(e);
}
diff --git a/tools/acrn-crashlog/acrnprobe/include/load_conf.h b/tools/acrn-crashlog/acrnprobe/include/load_conf.h
index f9e00d3c8..881bba276 100644
--- a/tools/acrn-crashlog/acrnprobe/include/load_conf.h
+++ b/tools/acrn-crashlog/acrnprobe/include/load_conf.h
@@ -123,11 +123,14 @@ struct sender_t {
size_t maxlines_len;
const char *spacequota;
size_t spacequota_len;
+ const char *foldersize;
+ size_t foldersize_len;
struct uptime_t *uptime;
void (*send)(struct event_t *);
char *log_vmrecordid;
int sw_updated; /* each sender has their own record */
+ int suspending; /* drop all events while suspending */
};
struct conf_t {
diff --git a/tools/acrn-crashlog/acrnprobe/load_conf.c b/tools/acrn-crashlog/acrnprobe/load_conf.c
index d26d756c2..4e8c6e003 100644
--- a/tools/acrn-crashlog/acrnprobe/load_conf.c
+++ b/tools/acrn-crashlog/acrnprobe/load_conf.c
@@ -36,6 +36,7 @@ static void print(void)
print_id_item(maxcrashdirs, sender, id);
print_id_item(maxlines, sender, id);
print_id_item(spacequota, sender, id);
+ print_id_item(foldersize, sender, id);
if (sender->uptime) {
print_id_item(uptime->name, sender, id);
@@ -678,6 +679,8 @@ static int parse_sender(xmlNodePtr cur, struct sender_t *sender)
res = load_cur_content(cur, sender, maxlines);
else if (name_is(cur, "spacequota"))
res = load_cur_content(cur, sender, spacequota);
+ else if (name_is(cur, "foldersize"))
+ res = load_cur_content(cur, sender, foldersize);
else if (name_is(cur, "uptime"))
res = parse_uptime(cur, sender);
diff --git a/tools/acrn-crashlog/common/fsutils.c b/tools/acrn-crashlog/common/fsutils.c
index c2317dd36..397d1150e 100644
--- a/tools/acrn-crashlog/common/fsutils.c
+++ b/tools/acrn-crashlog/common/fsutils.c
@@ -906,36 +906,33 @@ free_list:
return count;
}
-/**
- * Find target file in specified dir.
- *
- * @param dir Where to start search.
- * @param dlen Length of dir.
- * @param target_file Target file to search.
- * @param tflen The length of target_file.
- * @param depth Descend at most depth of directories below the starting dir.
- * @param path[out] Searched file path in given dir.
- * @param limit The number of files uplayer want to get.
- *
- * @return the count of searched files on success, or -1 on error.
- */
-int find_file(const char *dir, size_t dlen, const char *target_file,
- size_t tflen, int depth, char *path[], int limit)
+#define DIR_SUCCESS (0)
+#define DIR_ABORT (-1)
+#define DIR_ERROR (-2)
+static int dir_recursive(const char *path, size_t plen, int depth,
+ int fn(const char *pdir, struct dirent *, void *arg),
+ void *arg)
{
int wdepth = 0;
- int found = 0;
+ int ret = DIR_SUCCESS;
char wdir[PATH_MAX];
DIR **dp;
- if (!dir || !target_file || !tflen || !path || limit <= 0)
- return -1;
- if (dlen >= PATH_MAX)
- return -1;
- *(char *)mempcpy(wdir, dir, dlen) = '\0';
+ if (!path)
+ return DIR_ERROR;
+ if (plen >= PATH_MAX)
+ return DIR_ERROR;
+ if (depth < -1)
+ return DIR_ERROR;
+
+ if (depth == -1)
+ depth = 1024;
+
+ *(char *)mempcpy(wdir, path, plen) = '\0';
dp = calloc(depth + 1, sizeof(DIR *));
if (!dp) {
LOGE("out of memory\n");
- return -1;
+ return DIR_ERROR;
}
while (wdepth >= 0) {
@@ -947,6 +944,7 @@ int find_file(const char *dir, size_t dlen, const char *target_file,
if (!dp[wdepth]) {
LOGE("failed to opendir (%s), error (%s)\n",
wdir, strerror(errno));
+ ret = DIR_ERROR;
goto fail_open;
}
}
@@ -956,15 +954,11 @@ int find_file(const char *dir, size_t dlen, const char *target_file,
!strcmp(dirp->d_name, ".."))
continue;
- if (!strcmp(dirp->d_name, target_file)) {
- if (asprintf(&path[found], "%s/%s", wdir,
- dirp->d_name) == -1) {
- LOGE("out of memory\n");
- goto fail_read;
- }
- if (++found == limit)
- goto end;
- }
+ ret = fn(wdir, dirp, arg);
+ if (ret == DIR_ABORT)
+ goto end;
+ if (ret == DIR_ERROR)
+ goto fail_read;
if (dirp->d_type == DT_DIR && wdepth < depth) {
/* search in subdir */
@@ -990,6 +984,7 @@ int find_file(const char *dir, size_t dlen, const char *target_file,
} else {
LOGE("failed to readdir, (%s)\n",
strerror(errno));
+ ret = DIR_ERROR;
goto fail_read;
}
}
@@ -998,7 +993,7 @@ end:
while (wdepth >= 0)
closedir(dp[wdepth--]);
free(dp);
- return found;
+ return ret;
fail_read:
LOGE("failed to search in dir %s\n", wdir);
@@ -1006,12 +1001,112 @@ fail_read:
fail_open:
while (wdepth)
closedir(dp[--wdepth]);
- while (found)
- free(path[--found]);
free(dp);
+ return ret;
+
+}
+
+struct find_file_data {
+ const char *target;
+ size_t tlen;
+ int limit;
+ char **path;
+ int found;
+};
+
+static int _get_file_path(const char *pdir, struct dirent *dirp, void *arg)
+{
+ struct find_file_data *d = (struct find_file_data *)arg;
+
+ if (!strcmp(dirp->d_name, d->target)) {
+ if (asprintf(&d->path[d->found], "%s/%s", pdir,
+ dirp->d_name) == -1) {
+ LOGE("out of memory\n");
+ return DIR_ERROR;
+ }
+ if (++(d->found) == d->limit)
+ return DIR_ABORT;
+ }
+
+ return DIR_SUCCESS;
+}
+
+/**
+ * Find target file in specified dir.
+ *
+ * @param dir Where to start search.
+ * @param dlen Length of dir.
+ * @param target_file Target file to search.
+ * @param tflen The length of target_file.
+ * @param depth Descend at most depth of directories below the starting dir.
+ * @param path[out] Searched file path in given dir.
+ * @param limit The number of files uplayer want to get.
+ *
+ * @return the count of searched files on success, or -1 on error.
+ */
+int find_file(const char *dir, size_t dlen, const char *target_file,
+ size_t tflen, int depth, char *path[], int limit)
+{
+ int res;
+ struct find_file_data data = {
+ .target = target_file,
+ .tlen = tflen,
+ .limit = limit,
+ .path = path,
+ .found = 0,
+ };
+
+ if (!dir || !target_file || !tflen || !path || limit <= 0)
+ return -1;
+
+ res = dir_recursive(dir, dlen, depth, _get_file_path, (void *)&data);
+ if (res == DIR_ABORT || res == DIR_SUCCESS)
+ return data.found;
+
+ if (res == DIR_ERROR) {
+ while (data.found)
+ free(path[--data.found]);
+ }
return -1;
}
+static int _count_file_size(const char *pdir, struct dirent *dirp, void *arg)
+{
+ char file[PATH_MAX];
+ int res;
+ ssize_t fsize;
+
+ if (dirp->d_type != DT_REG && dirp->d_type != DT_DIR)
+ return DIR_SUCCESS;
+
+ res = snprintf(file, sizeof(file), "%s/%s", pdir, dirp->d_name);
+ if (s_not_expect(res, sizeof(file)))
+ return DIR_ERROR;
+
+ fsize = get_file_size(file);
+ if (fsize < 0)
+ return DIR_ERROR;
+
+ *(size_t *)arg += fsize;
+
+ return DIR_SUCCESS;
+}
+
+int dir_size(const char *dir, size_t dlen, size_t *size)
+{
+ if (!dir || !dlen || !size)
+ return -1;
+
+ *size = 0;
+ if (dir_recursive(dir, dlen, -1, _count_file_size,
+ (void *)size) != DIR_SUCCESS) {
+ LOGE("failed to recursive dir (%s)\n", dir);
+ return -1;
+ }
+
+ return 0;
+}
+
int read_file(const char *path, unsigned long *size, void **data)
{
char tmp[1024];
diff --git a/tools/acrn-crashlog/common/include/fsutils.h b/tools/acrn-crashlog/common/include/fsutils.h
index 65e7b056a..8fde72058 100644
--- a/tools/acrn-crashlog/common/include/fsutils.h
+++ b/tools/acrn-crashlog/common/include/fsutils.h
@@ -40,7 +40,7 @@ struct mm_file_t {
char *path;
int fd;
char *begin;
- int size;
+ ssize_t size;
};
struct ac_filter_data {
@@ -62,7 +62,7 @@ static inline int directory_exists(const char *path)
return (stat(path, &info) == 0 && S_ISDIR(info.st_mode));
}
-static inline int get_file_size(const char *filepath)
+static inline ssize_t get_file_size(const char *filepath)
{
struct stat info;
@@ -114,6 +114,7 @@ int dir_contains(const char *dir, const char *filename, size_t flen, int exact);
int lsdir(const char *dir, char *fullname[], int limit);
int find_file(const char *dir, size_t dlen, const char *target_file,
size_t tflen, int depth, char *path[], int limit);
+int dir_size(const char *dir, size_t dlen, size_t *size);
int read_file(const char *path, unsigned long *size, void **data);
int is_ac_filefmt(const char *file_fmt);
int config_fmt_to_files(const char *file_fmt, char ***out);
diff --git a/tools/acrn-crashlog/data/acrnprobe.xml b/tools/acrn-crashlog/data/acrnprobe.xml
index 7f0532534..9e02bef58 100644
--- a/tools/acrn-crashlog/data/acrnprobe.xml
+++ b/tools/acrn-crashlog/data/acrnprobe.xml
@@ -7,6 +7,7 @@
1000
5000
90
+ 200
UPTIME
5
@@ -16,6 +17,7 @@
telemd
/var/log/acrnprobe
+ 10
UPTIME
5
@@ -56,10 +58,9 @@
VM1
polling
60
- CRASH/TOMBSTONE
- CRASH/UIWDT
- CRASH/IPANIC
- REBOOT
+ CRASH/UIWDT
+ CRASH/IPANIC
+ REBOOT