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
parent 94aad8c3
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment