On Mon, Dec 05, 2022 at 11:26:21AM +0100, Alexandr Nedvedicky wrote:
> Hello,
> On Mon, Dec 05, 2022 at 11:46:07AM +1000, David Gwynne wrote:
> > 
> > yes, you're right. the diff below includes the simple fix to that.
> > 
> > this demonstrates how subtle the reference counting around the trees
> > is though. maybe it would be more obvious to take another refcnt
> > before giving the pf_state_key to the tree(s), and then give the
> > pf_state_key_attach callers reference to the pf_state struct. at
> > the moment we give the callers reference to the tree while holding
> > the PF_LOCK, and borrow it to give another one to the state while
> > the lock is still held.
> 
>     Either way is fine in my opinion. 
> 
> </snip>
> > @@ -766,44 +777,53 @@ pf_state_key_attach(struct pf_state_key 
> >                                     /* remove late or sks can go away */
> >                                     olds = si->s;
> >                             } else {
> > -                                   pool_put(&pf_state_key_pl, sk);
> > -                                   return (-1);    /* collision! */
> > +                                   pf_state_key_unref(sk);
> > +                                   return (NULL);  /* collision! */
> >                             }
> >                     }
> > -           pool_put(&pf_state_key_pl, sk);
> > -           s->key[idx] = cur;
> > -   } else
> > -           s->key[idx] = sk;
> > +           }
> > +
> > +           /* reuse the existing state key */
> > +           pf_state_key_unref(sk);
> > +           sk = cur;
> > +   }
> >  
> >     if ((si = pool_get(&pf_state_item_pl, PR_NOWAIT)) == NULL) {
> > -           pf_state_key_detach(s, idx);
> > -           return (-1);
> > +           if (TAILQ_EMPTY(&sk->states)) {
> > +                   KASSERT(cur == NULL);
> > +                   RB_REMOVE(pf_state_tree, &pf_statetbl, sk);
> > +                   sk->removed = 1;
> > +                   pf_state_key_unref(sk);
> > +           }
> > +
> > +           return (NULL);
> >     }
> 
>     I like your fix above.
> 
> I also wonder if pf_state_insert() should be always setting *skwp, *sksp to
> NULL. Just to indicate to caller the 'reference ownership got transferred' and
> there is nothing left to worry about. This can be done right at the beginning
> of pf_state_insert() after we assign to local variables skw/sks. Just a
> thought/nit.

pf_test_rule uses the skw and sks pointers after pf_state_insert sets
them via pf_create_state. i would happily change pf_test rule so it
reads the pf_state_key pointers out of pf_state rather than carry them
around on the stack like that, but i figured the diff was big enough as
it was.

> the recent diff is OK by me.

thanks. i'll wait until i can be around to look after it before i commit
it.

Reply via email to