log_trim: Rotate log instead of truncate
When the log buffer file's size exceeds, the log_trim() was using
moving the file's content and truncate it to a specific size.
This results in a behavior that the log file is always changing its
whole content when log_trim() is called.
It could be better to change the behavior like logrotate, that move the
original file to a new one, and create a new log file for log buffer.
This way it makes sure that the log file is always appended with new
content and thus is friendly to rsyslog.
Tested: Verify rsyslog could use imfile module to handle this log file
normally. Before this change, rsyslog will handle it incorrectly
when log_trim() is called.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I7647b8e21747ea98f68e4bc7c5bbf1339354bd75
diff --git a/log-handler.c b/log-handler.c
index 275cc81..2e0df6e 100644
--- a/log-handler.c
+++ b/log-handler.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define _GNU_SOURCE
#include <endian.h>
#include <err.h>
#include <fcntl.h>
@@ -37,6 +38,8 @@
size_t size;
size_t maxsize;
int pagesize;
+ char *log_filename;
+ char *rotate_filename;
};
@@ -50,32 +53,25 @@
static int log_trim(struct log_handler *lh, size_t space)
{
- int rc, n_shift_pages, shift_len, shift_start;
- off_t pos;
- void *buf;
+ int rc;
- pos = lseek(lh->fd, 0, SEEK_CUR);
+ /* Move the log buffer file to the rotate file */
+ close(lh->fd);
+ rc = rename(lh->log_filename, lh->rotate_filename);
+ if (rc) {
+ warn("Failed to rename %s to %s", lh->log_filename, lh->rotate_filename);
+ /* don't return, as we need to re-open the logfile */
+ }
- n_shift_pages = (space + lh->pagesize - 1) / lh->pagesize;
- shift_start = n_shift_pages * lh->pagesize;
- shift_len = pos - (n_shift_pages * lh->pagesize);
-
- buf = mmap(NULL, pos, PROT_READ | PROT_WRITE, MAP_SHARED, lh->fd, 0);
- if (buf == MAP_FAILED)
+ lh->fd = open(lh->log_filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
+ if (lh->fd < 0) {
+ warn("Can't open log buffer file %s", lh->log_filename);
return -1;
+ }
- memmove(buf, buf + shift_start, shift_len);
-
- munmap(buf, pos);
-
- lh->size = shift_len;
- rc = ftruncate(lh->fd, lh->size);
- if (rc)
- warn("failed to truncate file");
- lseek(lh->fd, 0, SEEK_END);
+ lh->size = 0;
return 0;
-
}
static int log_data(struct log_handler *lh, uint8_t *buf, size_t len)
@@ -138,6 +134,8 @@
lh->console = console;
lh->pagesize = 4096;
lh->size = 0;
+ lh->log_filename = NULL;
+ lh->rotate_filename = NULL;
logsize_str = config_get_value(config, "logsize");
rc = config_parse_logsize(logsize_str, &logsize);
@@ -152,15 +150,17 @@
if (!filename)
filename = default_filename;
- lh->fd = open(filename, O_RDWR | O_CREAT, 0644);
+ lh->fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (lh->fd < 0) {
warn("Can't open log buffer file %s", filename);
return -1;
}
- rc = ftruncate(lh->fd, 0);
- if (rc) {
- warn("Can't truncate file %s", filename);
- close(lh->fd);
+
+ lh->log_filename = strdup(filename);
+
+ rc = asprintf(&lh->rotate_filename, "%s.1", filename);
+ if (rc < 0) {
+ warn("Failed to construct rotate filename");
return -1;
}
@@ -175,6 +175,8 @@
struct log_handler *lh = to_log_handler(handler);
ringbuffer_consumer_unregister(lh->rbc);
close(lh->fd);
+ free(lh->log_filename);
+ free(lh->rotate_filename);
}
static struct log_handler log_handler = {