[master] 916473552 debug stoage: Add support for maxsize=<BYTES>

Nils Goroll nils.goroll at uplex.de
Fri Apr 11 10:52:09 UTC 2025


commit 9164735521989e54d8a8599828498797bc271107
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Fri Apr 11 12:45:21 2025 +0200

    debug stoage: Add support for maxsize=<BYTES>
    
    If the maximum is reached, allocations fail.

diff --git a/bin/varnishd/storage/storage_debug.c b/bin/varnishd/storage/storage_debug.c
index bf4a01a43..e144f9648 100644
--- a/bin/varnishd/storage/storage_debug.c
+++ b/bin/varnishd/storage/storage_debug.c
@@ -52,6 +52,7 @@
  */
 static vtim_dur dopen = 0.0;
 static unsigned count = 0;
+static ssize_t max_size = 0;
 
 /* returns one byte less than requested */
 static int v_matchproto_(objgetspace_f)
@@ -64,10 +65,61 @@ smd_lsp_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
 	return (SML_methods.objgetspace(wrk, oc, sz, ptr));
 }
 
+/*
+ * returns max_size at most, then fails
+ *
+ * relies on the actual storage implementation to not use priv2
+ */
+static int v_matchproto_(objgetspace_f)
+smd_max_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
+    uint8_t **ptr)
+{
+	ssize_t used;
+	int r;
+
+	AN(sz);
+	used = (ssize_t)oc->stobj->priv2;
+
+	VSLb(wrk->vsl, SLT_Debug, "-sdebug: %zd/%zd", used, max_size);
+
+	if (used >= max_size) {
+		VSLb(wrk->vsl, SLT_Storage, "-sdebug: max_size=%zd reached", max_size);
+		return (0);
+	}
+
+	assert(used < max_size);
+	*sz = vmin_t(ssize_t, *sz, max_size - used);
+
+	r = SML_methods.objgetspace(wrk, oc, sz, ptr);
+	if (r != 0)
+		oc->stobj->priv2 = (uint64_t)(used + *sz);
+	return (r);
+}
+
 #define dur_arg(a, s, d)					\
 	(! strncmp((a), (s), strlen(s))				\
 	 && (d = VNUM_duration(a + strlen(s))) != nan(""))
 
+static int
+bytes_arg(char *a, const char *s, ssize_t *sz)
+{
+	const char *err;
+	uintmax_t bytes;
+
+	AN(sz);
+	if (strncmp(a, s, strlen(s)))
+		return (0);
+	a += strlen(s);
+	err = VNUM_2bytes(a, &bytes, 0);
+	if (err != NULL)
+		ARGV_ERR("%s\n", err);
+	assert(bytes <= SSIZE_MAX);
+	*sz = (ssize_t)bytes;
+
+	return (1);
+}
+
+
 static void smd_open(struct stevedore *stv)
 {
 	sma_stevedore.open(stv);
@@ -80,6 +132,7 @@ static void v_matchproto_(storage_init_f)
 smd_init(struct stevedore *parent, int aac, char * const *aav)
 {
 	struct obj_methods *methods;
+	objgetspace_f *getspace = NULL;
 	const char *ident;
 	int i, ac = 0;
 	size_t nac;
@@ -109,7 +162,19 @@ smd_init(struct stevedore *parent, int aac, char * const *aav)
 		a = aav[i];
 		if (a != NULL) {
 			if (! strcmp(a, "lessspace")) {
-				methods->objgetspace = smd_lsp_getspace;
+				if (getspace != NULL) {
+					ARGV_ERR("-s%s conflicting options\n",
+					    smd_stevedore.name);
+				}
+				getspace = smd_lsp_getspace;
+				continue;
+			}
+			if (bytes_arg(a, "maxspace=", &max_size)) {
+				if (getspace != NULL) {
+					ARGV_ERR("-s%s conflicting options\n",
+					    smd_stevedore.name);
+				}
+				getspace = smd_max_getspace;
 				continue;
 			}
 			if (dur_arg(a, "dinit=", d)) {
@@ -128,6 +193,9 @@ smd_init(struct stevedore *parent, int aac, char * const *aav)
 	assert(ac < (int)nac);
 	AZ(av[ac]);
 
+	if (getspace != NULL)
+		methods->objgetspace = getspace;
+
 	sma_stevedore.init(parent, ac, av);
 	free(av);
 	fprintf(stderr, "-sdebug init delay %fs\n", dinit);
diff --git a/bin/varnishtest/tests/c00030.vtc b/bin/varnishtest/tests/c00030.vtc
index 912337dbf..b0eb4945a 100644
--- a/bin/varnishtest/tests/c00030.vtc
+++ b/bin/varnishtest/tests/c00030.vtc
@@ -2,3 +2,50 @@ varnishtest "debug storage"
 
 shell -err -expect {Error: Only one -sdebug instance supported} \
 	"varnishd -b none -a ${tmpdir}/vtc.sock -sdebug -sdebug"
+
+shell -err -expect {Error: -sdebug conflicting options} \
+	"varnishd -b none -a ${tmpdir}/vtc.sock -sdebug,lessspace,maxspace=1KB"
+
+shell -err -expect {Error: Unknown BYTES} \
+	"varnishd -b none -a ${tmpdir}/vtc.sock -sdebug,maxspace=1DJT"
+
+# lessspace is implicitly tested in b00017.vtc
+
+server s1 {
+	rxreq
+	txresp -bodylen 1024
+
+	rxreq
+	txresp -bodylen 1025
+} -start
+
+
+varnish v1 -arg "-sTransient=debug,maxspace=1KB" -vcl+backend {
+	sub vcl_recv {
+		return(pass);
+	}
+} -start
+
+logexpect l1 -v v1 -q "BerespHeader:Content-Length eq 1025" {
+	fail add *	End
+	expect * * Storage	{^-sdebug: max_size=1024 reached}
+	expect 0 = FetchError	{^Could not get storage}
+	expect 0 = BackendClose	{close RX_BODY}
+	fail clear
+} -start
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.bodylen == 1024
+
+	txreq
+	rxresphdrs
+	expect resp.status == 200
+	expect resp.http.Content-Length == 1025
+	rxrespbody -max 1024
+	expect_close
+	expect resp.bodylen == 1024
+} -run
+
+logexpect l1 -wait


More information about the varnish-commit mailing list