From 4f7b8404aea97b6a515b2a0b0a5c8bc3533193ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz>
Date: Fri, 21 Nov 2014 10:33:36 +0100
Subject: [PATCH] journal: prevent unlimited growth on shrinking/overfill

---
 src/knot/server/journal.c |  6 +++++-
 tests/journal.c           | 30 +++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index 6b09dd3ce..200a22a3d 100644
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -547,7 +547,11 @@ int journal_write_in(journal_t *j, journal_node_t **rn, uint64_t id, size_t len)
 	            (unsigned long long)id, j->qtail, len, j->fsize);
 
 	/* Calculate remaining bytes to reach file size limit. */
-	size_t fs_remaining = j->fslimit - j->fsize;
+	size_t fs_remaining = 0;
+	if (j->fsize < j->fslimit) {
+		fs_remaining = j->fslimit - j->fsize;
+	}
+
 	int seek_ret = 0;
 
 	/* Increase free segment if on the end of file. */
diff --git a/tests/journal.c b/tests/journal.c
index 08878b44b..e8a627f15 100644
--- a/tests/journal.c
+++ b/tests/journal.c
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <limits.h>
 #include <unistd.h>
+#include <sys/stat.h>
 #include <tap/basic.h>
 
 #include "knot/server/journal.h"
@@ -36,7 +37,7 @@ static int randstr(char* dst, size_t len)
 
 int main(int argc, char *argv[])
 {
-	plan(10);
+	plan_lazy();
 
 	/* Create tmpdir */
 	int fsize = 10 * 1024 * 1024;
@@ -112,6 +113,33 @@ int main(int argc, char *argv[])
 	}
 	is_int(KNOT_EOK, ret, "journal: sustained mmap r/w");
 
+	/* Overfill */
+	ret = journal_map(journal, chk_key, &mptr, fsize, false);
+	is_int(KNOT_ESPACE, ret, "journal: overfill");
+
+	/* Fillup */
+	tskey = 0xBEEF0000;
+	size_t large_entry_len = 512 * 1024;
+	char *large_entry = malloc(512 * 1024);
+	assert(large_entry);
+	randstr(large_entry, large_entry_len);
+	for (int i = 0; i < 512; ++i) {
+		chk_key = tskey + i;
+		ret = journal_map(journal, chk_key, &mptr, large_entry_len, false);
+		if (ret != KNOT_EOK) {
+			break;
+		}
+
+		journal_unmap(journal, chk_key, mptr, 1);
+	}
+	is_int(KNOT_EBUSY, ret, "journal: fillup");
+	free(large_entry);
+
+	/* Check file size. */
+	struct stat st;
+	stat(journal->path, &st);
+	ok(st.st_size < fsize + large_entry_len, "journal: fillup file size check");
+
 	/* Close journal. */
 	journal_close(journal);
 
-- 
GitLab