[master] 1cc722bfb Ensure PRIV_TASK and PRIV_TOP allocations never fail

Nils Goroll nils.goroll at uplex.de
Fri Mar 1 16:11:06 UTC 2024


commit 1cc722bfb1bca30c966475948314b04c59fc8065
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Wed Feb 28 10:16:45 2024 +0100

    Ensure PRIV_TASK and PRIV_TOP allocations never fail
    
    this is in preparation of a follow up commit

diff --git a/bin/varnishd/cache/cache_vrt_priv.c b/bin/varnishd/cache/cache_vrt_priv.c
index 5ebce43b4..616f7c55f 100644
--- a/bin/varnishd/cache/cache_vrt_priv.c
+++ b/bin/varnishd/cache/cache_vrt_priv.c
@@ -40,9 +40,15 @@
 #include "vcl.h"
 #include "vcc_interface.h"
 
+enum vrt_priv_storage_e {
+	VRT_PRIV_ST_WS = 1,
+	VRT_PRIV_ST_HEAP
+};
+
 struct vrt_priv {
 	unsigned			magic;
 #define VRT_PRIV_MAGIC			0x24157a52
+	enum vrt_priv_storage_e		storage;
 	VRBT_ENTRY(vrt_priv)		entry;
 	struct vmod_priv		priv[1];
 	uintptr_t			vmod_id;
@@ -138,23 +144,37 @@ vrt_priv_dynamic_get(const struct vrt_privs *privs, uintptr_t vmod_id)
 static struct vmod_priv *
 vrt_priv_dynamic(struct ws *ws, struct vrt_privs *privs, uintptr_t vmod_id)
 {
+	//lint --e{593} vp allocated, vp->priv returned
 	struct vrt_priv *vp, *ovp;
+	enum vrt_priv_storage_e storage;
 
 	AN(vmod_id);
 
-	/* even if ws is full, return any existing priv */
-	if (WS_ReserveSize(ws, sizeof *vp) == 0)
-		return (vrt_priv_dynamic_get(privs, vmod_id));
+	if (LIKELY(WS_ReserveSize(ws, sizeof *vp) != 0)) {
+		vp = WS_Reservation(ws);
+		storage = VRT_PRIV_ST_WS;
+	}
+	else {
+		vp = malloc(sizeof *vp);
+		storage = VRT_PRIV_ST_HEAP;
+	}
+	AN(vp);
 
-	vp = WS_Reservation(ws);
 	INIT_OBJ(vp, VRT_PRIV_MAGIC);
+	vp->storage = storage;
 	vp->vmod_id = vmod_id;
 	ovp = VRBT_INSERT(vrt_privs, privs, vp);
 	if (ovp == NULL) {
-		WS_Release(ws, sizeof *vp);
+		if (storage == VRT_PRIV_ST_WS)
+			WS_Release(ws, sizeof *vp);
 		return (vp->priv);
 	}
-	WS_Release(ws, 0);
+	if (storage == VRT_PRIV_ST_WS)
+		WS_Release(ws, 0);
+	else if (storage == VRT_PRIV_ST_HEAP)
+		free(vp);
+	else
+		WRONG("priv storage");
 	return (ovp->priv);
 }
 
@@ -310,6 +330,8 @@ VCL_TaskLeave(VRT_CTX, struct vrt_privs *privs)
 	VRBT_FOREACH_SAFE(vp, vrt_privs, privs, vp1) {
 		CHECK_OBJ(vp, VRT_PRIV_MAGIC);
 		VRT_priv_fini(ctx, vp->priv);
+		if (vp->storage == VRT_PRIV_ST_HEAP)
+			free(vp);
 	}
 	ZERO_OBJ(privs, sizeof *privs);
 }


More information about the varnish-commit mailing list