[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