[master] 7f0e41c92 Add vcldir_deref() and call it from VRT_DelDirector() also

Nils Goroll nils.goroll at uplex.de
Mon Mar 6 15:19:07 UTC 2023


commit 7f0e41c92981257687e26f443d7674559f313cec
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Mon Feb 27 22:05:13 2023 +0100

    Add vcldir_deref() and call it from VRT_DelDirector() also
    
    The last reference to a director might go away with VRT_DelDirector
    _or_ VRT_Asssign_Backend, which the former needs to account for.
    
    We assert for the VDIR_FLG_NOREFCNT case that there was only one
    reference such that a single deref yields no reference left.
    
    Part one of the fix for #3895

diff --git a/bin/varnishd/cache/cache_vrt_vcl.c b/bin/varnishd/cache/cache_vrt_vcl.c
index ec7cb9cde..01c660220 100644
--- a/bin/varnishd/cache/cache_vrt_vcl.c
+++ b/bin/varnishd/cache/cache_vrt_vcl.c
@@ -260,6 +260,24 @@ vcldir_retire(struct vcldir *vdir)
 	vcldir_free(vdir);
 }
 
+static int
+vcldir_deref(struct vcldir *vdir)
+{
+	int busy;
+
+	CHECK_OBJ_NOTNULL(vdir, VCLDIR_MAGIC);
+	AZ(vdir->flags & VDIR_FLG_NOREFCNT);
+
+	Lck_Lock(&vdir->dlck);
+	assert(vdir->refcnt > 0);
+	busy = --vdir->refcnt;
+	Lck_Unlock(&vdir->dlck);
+
+	if (!busy)
+		vcldir_retire(vdir);
+	return (busy);
+}
+
 void
 VRT_DelDirector(VCL_BACKEND *dirp)
 {
@@ -270,18 +288,19 @@ VRT_DelDirector(VCL_BACKEND *dirp)
 
 	vdir = dir->vdir;
 	CHECK_OBJ_NOTNULL(vdir, VCLDIR_MAGIC);
-	Lck_Lock(&vdir->dlck);
-	assert(vdir->refcnt == 1);
-	vdir->refcnt = 0;
-	Lck_Unlock(&vdir->dlck);
-	vcldir_retire(vdir);
+
+	if (vdir->flags & VDIR_FLG_NOREFCNT) {
+		vdir->flags &= ~VDIR_FLG_NOREFCNT;
+		AZ(vcldir_deref(vdir));
+	} else {
+		(void) vcldir_deref(vdir);
+	}
 }
 
 void
 VRT_Assign_Backend(VCL_BACKEND *dst, VCL_BACKEND src)
 {
 	struct vcldir *vdir;
-	int busy;
 
 	AN(dst);
 	CHECK_OBJ_ORNULL((*dst), DIRECTOR_MAGIC);
@@ -289,14 +308,8 @@ VRT_Assign_Backend(VCL_BACKEND *dst, VCL_BACKEND src)
 	if (*dst != NULL) {
 		vdir = (*dst)->vdir;
 		CHECK_OBJ_NOTNULL(vdir, VCLDIR_MAGIC);
-		if (!(vdir->flags & VDIR_FLG_NOREFCNT)) {
-			Lck_Lock(&vdir->dlck);
-			assert(vdir->refcnt > 0);
-			busy = --vdir->refcnt;
-			Lck_Unlock(&vdir->dlck);
-			if (!busy)
-				vcldir_retire(vdir);
-		}
+		if (!(vdir->flags & VDIR_FLG_NOREFCNT))
+			vcldir_deref(vdir);
 	}
 	if (src != NULL) {
 		vdir = src->vdir;


More information about the varnish-commit mailing list