typedef struct OutputFilestoreLogThread_ {
OutputFilestoreCtx *ctx;
- uint32_t file_cnt;
uint16_t counter_max_hits;
+ uint16_t fs_error_counter;
} OutputFilestoreLogThread;
+/* For WARN_ONCE, a record of warnings that have already been
+ * issued. */
+static __thread bool once_errs[SC_ERR_MAX];
+
+#define WARN_ONCE(err_code, ...) do { \
+ if (!once_errs[err_code]) { \
+ once_errs[err_code] = true; \
+ SCLogWarning(err_code, __VA_ARGS__); \
+ } \
+ } while (0)
+
static uint64_t OutputFilestoreOpenFilesCounter(void)
{
return SC_ATOMIC_GET(filestore_open_file_cnt);
}
}
-static void OutputFilestoreFinalizeFiles(const OutputFilestoreCtx *ctx,
+static void OutputFilestoreFinalizeFiles(ThreadVars *tv,
+ const OutputFilestoreLogThread *oft, const OutputFilestoreCtx *ctx,
const Packet *p, File *ff) {
/* Stringify the SHA256 which will be used in the final
* filename. */
if (SCPathExists(final_filename)) {
OutputFilestoreUpdateFileTime(tmp_filename, final_filename);
if (unlink(tmp_filename) != 0) {
- SCLogWarning(SC_WARN_REMOVE_FILE,
+ StatsIncr(tv, oft->fs_error_counter);
+ WARN_ONCE(SC_WARN_REMOVE_FILE,
"Failed to remove temporary file %s: %s", tmp_filename,
strerror(errno));
}
} else if (rename(tmp_filename, final_filename) != 0) {
- SCLogWarning(SC_WARN_RENAMING_FILE, "Failed to rename %s to %s: %s",
+ StatsIncr(tv, oft->fs_error_counter);
+ WARN_ONCE(SC_WARN_RENAMING_FILE, "Failed to rename %s to %s: %s",
tmp_filename, final_filename, strerror(errno));
if (unlink(tmp_filename) != 0) {
- SCLogWarning(SC_WARN_REMOVE_FILE,
- "Failed to remove temporary file %s: %s", tmp_filename,
- strerror(errno));
+ /* Just increment, don't log as has_fs_errors would
+ * already be set above. */
+ StatsIncr(tv, oft->fs_error_counter);
}
return;
}
snprintf(filename, sizeof(filename), "%s", base_filename);
if (flags & OUTPUT_FILEDATA_FLAG_OPEN) {
- aft->file_cnt++;
+ file_fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY,
+ 0644);
+ if (file_fd == -1) {
+ StatsIncr(tv, aft->fs_error_counter);
+ SCLogWarning(SC_ERR_OPENING_FILE,
+ "Filestore (v2) failed to create %s: %s", filename,
+ strerror(errno));
+ return -1;
+ }
if (SC_ATOMIC_GET(filestore_open_file_cnt) < FileGetMaxOpenFiles()) {
SC_ATOMIC_ADD(filestore_open_file_cnt, 1);
- ff->fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
- if (ff->fd == -1) {
- SCLogNotice("failed to create file");
- return -1;
- }
- file_fd = ff->fd;
+ ff->fd = file_fd;
} else {
- file_fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
- if (file_fd == -1) {
- SCLogNotice("failed to create file");
- return -1;
- }
if (FileGetMaxOpenFiles() > 0) {
StatsIncr(tv, aft->counter_max_hits);
}
if (ff->fd == -1) {
file_fd = open(filename, O_APPEND | O_NOFOLLOW | O_WRONLY);
if (file_fd == -1) {
- SCLogNotice("failed to open file %s: %s", filename, strerror(errno));
+ StatsIncr(tv, aft->fs_error_counter);
+ WARN_ONCE(SC_ERR_OPENING_FILE,
+ "Filestore (v2) failed to open file %s: %s",
+ filename, strerror(errno));
return -1;
}
} else {
if (file_fd != -1) {
ssize_t r = write(file_fd, (const void *)data, (size_t)data_len);
if (r == -1) {
- SCLogDebug("write failed: %s", strerror(errno));
+ StatsIncr(tv, aft->fs_error_counter);
+ WARN_ONCE(SC_ERR_FWRITE,
+ "Filestore (v2) failed to write to %s: %s",
+ filename, strerror(errno));
if (ff->fd != -1) {
SC_ATOMIC_SUB(filestore_open_file_cnt, 1);
}
ff->fd = -1;
SC_ATOMIC_SUB(filestore_open_file_cnt, 1);
}
- OutputFilestoreFinalizeFiles(ctx, p, ff);
+ OutputFilestoreFinalizeFiles(tv, aft, ctx, p, ff);
}
return 0;
aft->counter_max_hits =
StatsRegisterCounter("file_store.open_files_max_hit", t);
+ /* File system type errors (open, write, rename) will only be
+ * logged once. But this stat will be incremented for every
+ * occurence. */
+ aft->fs_error_counter = StatsRegisterCounter("file_store.fs_errors", t);
+
*data = (void *)aft;
return TM_ECODE_OK;
}
return TM_ECODE_OK;
}
-static void OutputFilestoreLogExitPrintStats(ThreadVars *tv, void *data)
-{
- OutputFilestoreLogThread *aft = (OutputFilestoreLogThread *)data;
- if (aft == NULL) {
- return;
- }
-
- SCLogInfo("(%s) Files extracted %" PRIu32 "", tv->name, aft->file_cnt);
-}
-
static void OutputFilestoreLogDeInitCtx(OutputCtx *output_ctx)
{
OutputFilestoreCtx *ctx = (OutputFilestoreCtx *)output_ctx->data;
OutputRegisterFiledataModule(LOGGER_FILE_STORE, MODULE_NAME, "file-store",
OutputFilestoreLogInitCtx, OutputFilestoreLogger,
OutputFilestoreLogThreadInit, OutputFilestoreLogThreadDeinit,
- OutputFilestoreLogExitPrintStats);
+ NULL);
SC_ATOMIC_INIT(filestore_open_file_cnt);
SC_ATOMIC_SET(filestore_open_file_cnt, 0);
- SCLogDebug("registered");
#endif
}