Hi, Eelco Thanks for your comments. Eelco Chaudron <[email protected]> 于2022年4月29日周五 18:54写道:
> > > On 12 Apr 2022, at 11:09, Peng He wrote: > > > David Marchand <[email protected]> 于2022年4月12日周二 16:40写道: > > > >> On Thu, Apr 7, 2022 at 4:13 AM Peng He <[email protected]> wrote: > >>> > >>> I understand there is no need to introduce a rcu api, > >>> but at least put these codes into a separate function ? :-) > >> > >> No strong opinion. > >> > >> > >>>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > >>>> index 6601f2346..402cdcdf5 100644 > >>>> --- a/ofproto/ofproto-dpif.c > >>>> +++ b/ofproto/ofproto-dpif.c > >>>> @@ -1805,6 +1805,7 @@ destruct(struct ofproto *ofproto_, bool del) > >>>> struct rule_dpif *rule; > >>>> struct oftable *table; > >>>> struct ovs_list ams; > >>>> + struct seq *seq; > >>>> > >>>> ofproto->backer->need_revalidate = REV_RECONFIGURE; > >>>> xlate_txn_start(); > >>>> @@ -1848,6 +1849,14 @@ destruct(struct ofproto *ofproto_, bool del) > >>>> > >>>> seq_destroy(ofproto->ams_seq); > >>>> > >>>> + /* Wait for all the meter rules to be destroyed. */ > >>>> + seq = seq_create(); > >>>> + ovsrcu_synchronize(); > >>>> + seq_wait(seq, seq_read(seq)); > >>>> + ovsrcu_postpone__((void (*)(void *))seq_change, seq); > >>>> > >>>> + poll_block(); > >>> > >>> > >>> after poll block, we should check if seq is changed or not, other fds > >> will > >>> wake up block too. so we need a while loop to do the seq_wait + > postpone > >> + check > >>> stuff. > >>> > >>>> + seq_destroy(seq); > >>>> + > >> > >> If there can be other event nodes registered at this point, once you > >> leave poll_block() no event node is kept. > >> > > > > IMHO, this is how OVS event loop works. > > > > even you lose all other event nodes after the first poll_block returns, > > eventually (after you got seq changes) you are not blocking and running > to > > the next > > poll_block point, and every modules in between will check fd in its > XX_run > > function, > > if event is ready, do the work, when EAGAIN happens, the node is added > back. > > > > all the previous lost events will be added back eventually. > > > > So it's ok to call poll_block anywhere. I think. > > > > Adding to this, poll_block -> timepoll -> poll can fail (though I am > >> not clear it is something that is supposed to happen). > > > > > > why fail? > > > > Once a first poll_block() returns, the only event that this code can > >> wait for is the seq changing. > >> There should be no need to wake up with a timeout, since there is no > >> useful work to do. > >> > >> Am I missing something else? > >> > > > > yes, timeout is for the RCU api, if used here, I agree no need to add > > timeout. > > > Sorry for joining in late in the conversation, but I do not see any harm > in introducing the new rcu API. It will be way cleaner, and if we add some > good documentation (and maybe a checkpatch warning), I think we should be > ok. the checkpatch warning is about ? an experimental API for RCU? > However looking at the implementation from patch 1, I see two problems > (well they are is actually one): > > + > +static void > +ovsrcu_barrier_func(void *seq_) > +{ > + struct seq *seq = (struct seq*)seq_; > + seq_change(seq); > +} > + > +bool > +ovsrcu_barrier(struct seq *seq, long long int timeout) > +{ > + /* first let all threads flush their cbset */ > + ovsrcu_synchronize(); > + > + /* then register a new cbset, ensure this cbset > + * is at the tail of global listi > + */ > + uint64_t seqno = seq_read(seq); > + ovsrcu_postpone__(ovsrcu_barrier_func, (void*)seq); > + long long int now = time_msec(); > + long long int deadline = now + timeout; > + > + do { > + seq_wait(seq, seqno); > + poll_timer_wait_until(deadline); > + poll_block(); > + now = time_msec(); /* update now */ > + } while (seqno == seq_read(seq) && now < deadline); > + > + return !(seqno == seq_read(seq)); > +} > > 1) I do not like that you have to supply the seq as a parameter. The API > should not take any parameters if you ask me. > 2) The timeout is a problem here, if the timeout happens you will call > seq_destroy(), so the later invocation of ovsrcu_barrier_func() would > access invalid memory. > Agree, will send a new version. > > So I guess the API should look something like this (not tested, but also > changed comments ;): > > +void > +ovsrcu_barrier() > +{ > + struct seq *seq = seq_create(); > + > + /* First let all threads flush their cbset’s. */ > + ovsrcu_synchronize(); > + > + /* Then register a new cbset, ensure this cbset > + * is at the tail of the global list. > + */ > + uint64_t seqno = seq_read(seq); > + ovsrcu_postpone__(ovsrcu_barrier_func, (void*)seq); > + > + do { > + seq_wait(seq, seqno); > + poll_block(); > + } while (seqno == seq_read(seq)); > + > + seq_destroy(seq); > +} > > Which you can then just use as (see comment changes ;): > > + /* Wait for all the meter destroy work to finish. */ > + ovsrcu_barrier(); > close_dpif_backer(ofproto->backer, del); > } > > > >> > >> > >> In the end, that would translate to: > >> > >> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > >> index 6601f23464..dd1b9e5138 100644 > >> --- a/ofproto/ofproto-dpif.c > >> +++ b/ofproto/ofproto-dpif.c > >> @@ -1805,6 +1805,8 @@ destruct(struct ofproto *ofproto_, bool del) > >> struct rule_dpif *rule; > >> struct oftable *table; > >> struct ovs_list ams; > >> + struct seq *seq; > >> + uint64_t seqno; > >> > >> ofproto->backer->need_revalidate = REV_RECONFIGURE; > >> xlate_txn_start(); > >> @@ -1848,6 +1850,17 @@ destruct(struct ofproto *ofproto_, bool del) > >> > >> seq_destroy(ofproto->ams_seq); > >> > >> + /* Wait for all the meter rules to be destroyed. */ > >> + seq = seq_create(); > >> + seqno = seq_read(); > >> + ovsrcu_synchronize(); > >> + ovsrcu_postpone__((void (*)(void *))seq_change, seq); > >> + do { > >> + seq_wait(seq, seqno); > >> + poll_block(); > >> + } while (seqno == seq_read(seq)); > >> + seq_destroy(seq); > >> + > >> close_dpif_backer(ofproto->backer, del); > >> } > >> > >> > >> -- > >> David Marchand > >> > >> > > > > -- > > hepeng > > _______________________________________________ > > dev mailing list > > [email protected] > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > -- hepeng _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
