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